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-2013 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 
    292 
    293 /*------------------------------------------------------------*/
    294 /*--- Extract instruction fields                          --- */
    295 /*------------------------------------------------------------*/
    296 
    297 /* Extract field from insn, given idx (zero = lsb) and field length */
    298 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
    299 
    300 /* Extract primary opcode, instr[31:26] */
    301 static UChar ifieldOPC( UInt instr ) {
    302    return toUChar( IFIELD( instr, 26, 6 ) );
    303 }
    304 
    305 /* Extract 10-bit secondary opcode, instr[10:1] */
    306 static UInt ifieldOPClo10 ( UInt instr) {
    307    return IFIELD( instr, 1, 10 );
    308 }
    309 
    310 /* Extract 9-bit secondary opcode, instr[9:1] */
    311 static UInt ifieldOPClo9 ( UInt instr) {
    312    return IFIELD( instr, 1, 9 );
    313 }
    314 
    315 /* Extract 8-bit secondary opcode, instr[8:1] */
    316 static UInt ifieldOPClo8 ( UInt instr) {
    317    return IFIELD( instr, 1, 8 );
    318 }
    319 
    320 /* Extract 5-bit secondary opcode, instr[5:1] */
    321 static UInt ifieldOPClo5 ( UInt instr) {
    322    return IFIELD( instr, 1, 5 );
    323 }
    324 
    325 /* Extract RD (destination register) field, instr[25:21] */
    326 static UChar ifieldRegDS( UInt instr ) {
    327    return toUChar( IFIELD( instr, 21, 5 ) );
    328 }
    329 
    330 /* Extract XT (destination register) field, instr[0,25:21] */
    331 static UChar ifieldRegXT ( UInt instr )
    332 {
    333   UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
    334   UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
    335   return (upper_bit << 5) | lower_bits;
    336 }
    337 
    338 /* Extract XS (store source register) field, instr[0,25:21] */
    339 static inline UChar ifieldRegXS ( UInt instr )
    340 {
    341   return ifieldRegXT ( instr );
    342 }
    343 
    344 /* Extract RA (1st source register) field, instr[20:16] */
    345 static UChar ifieldRegA ( UInt instr ) {
    346    return toUChar( IFIELD( instr, 16, 5 ) );
    347 }
    348 
    349 /* Extract XA (1st source register) field, instr[2,20:16] */
    350 static UChar ifieldRegXA ( UInt instr )
    351 {
    352   UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
    353   UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
    354   return (upper_bit << 5) | lower_bits;
    355 }
    356 
    357 /* Extract RB (2nd source register) field, instr[15:11] */
    358 static UChar ifieldRegB ( UInt instr ) {
    359    return toUChar( IFIELD( instr, 11, 5 ) );
    360 }
    361 
    362 /* Extract XB (2nd source register) field, instr[1,15:11] */
    363 static UChar ifieldRegXB ( UInt instr )
    364 {
    365   UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
    366   UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
    367   return (upper_bit << 5) | lower_bits;
    368 }
    369 
    370 /* Extract RC (3rd source register) field, instr[10:6] */
    371 static UChar ifieldRegC ( UInt instr ) {
    372    return toUChar( IFIELD( instr, 6, 5 ) );
    373 }
    374 
    375 /* Extract XC (3rd source register) field, instr[3,10:6] */
    376 static UChar ifieldRegXC ( UInt instr )
    377 {
    378   UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
    379   UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
    380   return (upper_bit << 5) | lower_bits;
    381 }
    382 
    383 /* Extract bit 10, instr[10] */
    384 static UChar ifieldBIT10 ( UInt instr ) {
    385    return toUChar( IFIELD( instr, 10, 1 ) );
    386 }
    387 
    388 /* Extract 2nd lowest bit, instr[1] */
    389 static UChar ifieldBIT1 ( UInt instr ) {
    390    return toUChar( IFIELD( instr, 1, 1 ) );
    391 }
    392 
    393 /* Extract lowest bit, instr[0] */
    394 static UChar ifieldBIT0 ( UInt instr ) {
    395    return toUChar( instr & 0x1 );
    396 }
    397 
    398 /* Extract unsigned bottom half, instr[15:0] */
    399 static UInt ifieldUIMM16 ( UInt instr ) {
    400    return instr & 0xFFFF;
    401 }
    402 
    403 /* Extract unsigned bottom 26 bits, instr[25:0] */
    404 static UInt ifieldUIMM26 ( UInt instr ) {
    405    return instr & 0x3FFFFFF;
    406 }
    407 
    408 /* Extract DM field, instr[9:8] */
    409 static UChar ifieldDM ( UInt instr ) {
    410    return toUChar( IFIELD( instr, 8, 2 ) );
    411 }
    412 
    413 /* Extract SHW field, instr[9:8] */
    414 static inline UChar ifieldSHW ( UInt instr )
    415 {
    416   return ifieldDM ( instr );
    417 }
    418 
    419 /*------------------------------------------------------------*/
    420 /*--- Guest-state identifiers                              ---*/
    421 /*------------------------------------------------------------*/
    422 
    423 typedef enum {
    424     PPC_GST_CIA,    // Current Instruction Address
    425     PPC_GST_LR,     // Link Register
    426     PPC_GST_CTR,    // Count Register
    427     PPC_GST_XER,    // Overflow, carry flags, byte count
    428     PPC_GST_CR,     // Condition Register
    429     PPC_GST_FPSCR,  // Floating Point Status/Control Register
    430     PPC_GST_VRSAVE, // Vector Save/Restore Register
    431     PPC_GST_VSCR,   // Vector Status and Control Register
    432     PPC_GST_EMWARN, // Emulation warnings
    433     PPC_GST_CMSTART,// For icbi: start of area to invalidate
    434     PPC_GST_CMLEN,  // For icbi: length of area to invalidate
    435     PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
    436     PPC_GST_SPRG3_RO, // SPRG3
    437     PPC_GST_TFHAR,  // Transactional Failure Handler Address Register
    438     PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
    439     PPC_GST_TEXASR, // Transactional EXception And Summary Register
    440     PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper
    441     PPC_GST_MAX
    442 } PPC_GST;
    443 
    444 #define MASK_FPSCR_RN   0x3ULL  // Binary floating point rounding mode
    445 #define MASK_FPSCR_DRN  0x700000000ULL // Decimal floating point rounding mode
    446 #define MASK_VSCR_VALID 0x00010001
    447 
    448 
    449 /*------------------------------------------------------------*/
    450 /*---  FP Helpers                                          ---*/
    451 /*------------------------------------------------------------*/
    452 
    453 /* Produce the 32-bit pattern corresponding to the supplied
    454    float. */
    455 static UInt float_to_bits ( Float f )
    456 {
    457    union { UInt i; Float f; } u;
    458    vassert(4 == sizeof(UInt));
    459    vassert(4 == sizeof(Float));
    460    vassert(4 == sizeof(u));
    461    u.f = f;
    462    return u.i;
    463 }
    464 
    465 
    466 /*------------------------------------------------------------*/
    467 /*--- Misc Helpers                                         ---*/
    468 /*------------------------------------------------------------*/
    469 
    470 /* Generate mask with 1's from 'begin' through 'end',
    471    wrapping if begin > end.
    472    begin->end works from right to left, 0=lsb
    473 */
    474 static UInt MASK32( UInt begin, UInt end )
    475 {
    476    UInt m1, m2, mask;
    477    vassert(begin < 32);
    478    vassert(end < 32);
    479    m1   = ((UInt)(-1)) << begin;
    480    m2   = ((UInt)(-1)) << end << 1;
    481    mask = m1 ^ m2;
    482    if (begin > end) mask = ~mask;  // wrap mask
    483    return mask;
    484 }
    485 
    486 static ULong MASK64( UInt begin, UInt end )
    487 {
    488    ULong m1, m2, mask;
    489    vassert(begin < 64);
    490    vassert(end < 64);
    491    m1   = ((ULong)(-1)) << begin;
    492    m2   = ((ULong)(-1)) << end << 1;
    493    mask = m1 ^ m2;
    494    if (begin > end) mask = ~mask;  // wrap mask
    495    return mask;
    496 }
    497 
    498 static Addr64 nextInsnAddr( void )
    499 {
    500    return guest_CIA_curr_instr + 4;
    501 }
    502 
    503 
    504 /*------------------------------------------------------------*/
    505 /*--- Helper bits and pieces for deconstructing the        ---*/
    506 /*--- ppc32/64 insn stream.                                ---*/
    507 /*------------------------------------------------------------*/
    508 
    509 /* Add a statement to the list held by "irsb". */
    510 static void stmt ( IRStmt* st )
    511 {
    512    addStmtToIRSB( irsb, st );
    513 }
    514 
    515 /* Generate a new temporary of the given type. */
    516 static IRTemp newTemp ( IRType ty )
    517 {
    518    vassert(isPlausibleIRType(ty));
    519    return newIRTemp( irsb->tyenv, ty );
    520 }
    521 
    522 /* Various simple conversions */
    523 
    524 static UChar extend_s_5to8 ( UChar x )
    525 {
    526    return toUChar((((Int)x) << 27) >> 27);
    527 }
    528 
    529 static UInt extend_s_8to32( UChar x )
    530 {
    531    return (UInt)((((Int)x) << 24) >> 24);
    532 }
    533 
    534 static UInt extend_s_16to32 ( UInt x )
    535 {
    536    return (UInt)((((Int)x) << 16) >> 16);
    537 }
    538 
    539 static ULong extend_s_16to64 ( UInt x )
    540 {
    541    return (ULong)((((Long)x) << 48) >> 48);
    542 }
    543 
    544 static ULong extend_s_26to64 ( UInt x )
    545 {
    546    return (ULong)((((Long)x) << 38) >> 38);
    547 }
    548 
    549 static ULong extend_s_32to64 ( UInt x )
    550 {
    551    return (ULong)((((Long)x) << 32) >> 32);
    552 }
    553 
    554 /* Do a proper-endian load of a 32-bit word, regardless of the endianness
    555    of the underlying host. */
    556 static UInt getUIntPPCendianly ( const UChar* p )
    557 {
    558    UInt w = 0;
    559    if (host_endness == VexEndnessBE) {
    560        w = (w << 8) | p[0];
    561        w = (w << 8) | p[1];
    562        w = (w << 8) | p[2];
    563        w = (w << 8) | p[3];
    564    } else {
    565        w = (w << 8) | p[3];
    566        w = (w << 8) | p[2];
    567        w = (w << 8) | p[1];
    568        w = (w << 8) | p[0];
    569    }
    570    return w;
    571 }
    572 
    573 
    574 /*------------------------------------------------------------*/
    575 /*--- Helpers for constructing IR.                         ---*/
    576 /*------------------------------------------------------------*/
    577 
    578 static void assign ( IRTemp dst, IRExpr* e )
    579 {
    580    stmt( IRStmt_WrTmp(dst, e) );
    581 }
    582 
    583 /* This generates a normal (non store-conditional) store. */
    584 static void store ( IRExpr* addr, IRExpr* data )
    585 {
    586    IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
    587    vassert(tyA == Ity_I32 || tyA == Ity_I64);
    588 
    589    if (host_endness == VexEndnessBE)
    590       stmt( IRStmt_Store(Iend_BE, addr, data) );
    591    else
    592       stmt( IRStmt_Store(Iend_LE, addr, data) );
    593 }
    594 
    595 static IRExpr* unop ( IROp op, IRExpr* a )
    596 {
    597    return IRExpr_Unop(op, a);
    598 }
    599 
    600 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
    601 {
    602    return IRExpr_Binop(op, a1, a2);
    603 }
    604 
    605 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
    606 {
    607    return IRExpr_Triop(op, a1, a2, a3);
    608 }
    609 
    610 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
    611                               IRExpr* a3, IRExpr* a4 )
    612 {
    613    return IRExpr_Qop(op, a1, a2, a3, a4);
    614 }
    615 
    616 static IRExpr* mkexpr ( IRTemp tmp )
    617 {
    618    return IRExpr_RdTmp(tmp);
    619 }
    620 
    621 static IRExpr* mkU8 ( UChar i )
    622 {
    623    return IRExpr_Const(IRConst_U8(i));
    624 }
    625 
    626 static IRExpr* mkU16 ( UInt i )
    627 {
    628    return IRExpr_Const(IRConst_U16(i));
    629 }
    630 
    631 static IRExpr* mkU32 ( UInt i )
    632 {
    633    return IRExpr_Const(IRConst_U32(i));
    634 }
    635 
    636 static IRExpr* mkU64 ( ULong i )
    637 {
    638    return IRExpr_Const(IRConst_U64(i));
    639 }
    640 
    641 static IRExpr* mkV128 ( UShort i )
    642 {
    643    vassert(i == 0 || i == 0xffff);
    644    return IRExpr_Const(IRConst_V128(i));
    645 }
    646 
    647 /* This generates a normal (non load-linked) load. */
    648 static IRExpr* load ( IRType ty, IRExpr* addr )
    649 {
    650    if (host_endness == VexEndnessBE)
    651       return IRExpr_Load(Iend_BE, ty, addr);
    652    else
    653       return IRExpr_Load(Iend_LE, ty, addr);
    654 }
    655 
    656 static IRStmt* stmt_load ( IRTemp result,
    657                            IRExpr* addr, IRExpr* storedata )
    658 {
    659    if (host_endness == VexEndnessBE)
    660       return IRStmt_LLSC(Iend_BE, result, addr, storedata);
    661    else
    662       return IRStmt_LLSC(Iend_LE, result, addr, storedata);
    663 }
    664 
    665 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
    666 {
    667    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    668    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    669    return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
    670                                           unop(Iop_1Uto32, arg2)));
    671 }
    672 
    673 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
    674 {
    675    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    676    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    677    return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
    678                                            unop(Iop_1Uto32, arg2)));
    679 }
    680 
    681 /* expand V128_8Ux16 to 2x V128_16Ux8's */
    682 static void expand8Ux16( IRExpr* vIn,
    683                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    684 {
    685    IRTemp ones8x16 = newTemp(Ity_V128);
    686 
    687    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    688    vassert(vEvn && *vEvn == IRTemp_INVALID);
    689    vassert(vOdd && *vOdd == IRTemp_INVALID);
    690    *vEvn = newTemp(Ity_V128);
    691    *vOdd = newTemp(Ity_V128);
    692 
    693    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    694    assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
    695    assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
    696                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    697 }
    698 
    699 /* expand V128_8Sx16 to 2x V128_16Sx8's */
    700 static void expand8Sx16( IRExpr* vIn,
    701                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    702 {
    703    IRTemp ones8x16 = newTemp(Ity_V128);
    704 
    705    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    706    vassert(vEvn && *vEvn == IRTemp_INVALID);
    707    vassert(vOdd && *vOdd == IRTemp_INVALID);
    708    *vEvn = newTemp(Ity_V128);
    709    *vOdd = newTemp(Ity_V128);
    710 
    711    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    712    assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
    713    assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
    714                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    715 }
    716 
    717 /* expand V128_16Uto8 to 2x V128_32Ux4's */
    718 static void expand16Ux8( IRExpr* vIn,
    719                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    720 {
    721    IRTemp ones16x8 = newTemp(Ity_V128);
    722 
    723    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    724    vassert(vEvn && *vEvn == IRTemp_INVALID);
    725    vassert(vOdd && *vOdd == IRTemp_INVALID);
    726    *vEvn = newTemp(Ity_V128);
    727    *vOdd = newTemp(Ity_V128);
    728 
    729    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    730    assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
    731    assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
    732                         binop(Iop_ShrV128, vIn, mkU8(16))) );
    733 }
    734 
    735 /* expand V128_16Sto8 to 2x V128_32Sx4's */
    736 static void expand16Sx8( IRExpr* vIn,
    737                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    738 {
    739    IRTemp ones16x8 = newTemp(Ity_V128);
    740 
    741    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    742    vassert(vEvn && *vEvn == IRTemp_INVALID);
    743    vassert(vOdd && *vOdd == IRTemp_INVALID);
    744    *vEvn = newTemp(Ity_V128);
    745    *vOdd = newTemp(Ity_V128);
    746 
    747    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    748    assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
    749    assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
    750                        binop(Iop_ShrV128, vIn, mkU8(16))) );
    751 }
    752 
    753 /* break V128 to 4xF64's*/
    754 static void breakV128to4xF64( IRExpr* t128,
    755                               /*OUTs*/
    756                               IRTemp* t3, IRTemp* t2,
    757                               IRTemp* t1, IRTemp* t0 )
    758 {
    759    IRTemp hi64 = newTemp(Ity_I64);
    760    IRTemp lo64 = newTemp(Ity_I64);
    761 
    762    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    763    vassert(t0 && *t0 == IRTemp_INVALID);
    764    vassert(t1 && *t1 == IRTemp_INVALID);
    765    vassert(t2 && *t2 == IRTemp_INVALID);
    766    vassert(t3 && *t3 == IRTemp_INVALID);
    767    *t0 = newTemp(Ity_F64);
    768    *t1 = newTemp(Ity_F64);
    769    *t2 = newTemp(Ity_F64);
    770    *t3 = newTemp(Ity_F64);
    771 
    772    assign( hi64, unop(Iop_V128HIto64, t128) );
    773    assign( lo64, unop(Iop_V128to64,   t128) );
    774    assign( *t3,
    775            unop( Iop_F32toF64,
    776                  unop( Iop_ReinterpI32asF32,
    777                        unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
    778    assign( *t2,
    779            unop( Iop_F32toF64,
    780                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
    781    assign( *t1,
    782            unop( Iop_F32toF64,
    783                  unop( Iop_ReinterpI32asF32,
    784                        unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
    785    assign( *t0,
    786            unop( Iop_F32toF64,
    787                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
    788 }
    789 
    790 
    791 /* break V128 to 4xI32's, then sign-extend to I64's */
    792 static void breakV128to4x64S( IRExpr* t128,
    793                               /*OUTs*/
    794                               IRTemp* t3, IRTemp* t2,
    795                               IRTemp* t1, IRTemp* t0 )
    796 {
    797    IRTemp hi64 = newTemp(Ity_I64);
    798    IRTemp lo64 = newTemp(Ity_I64);
    799 
    800    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    801    vassert(t0 && *t0 == IRTemp_INVALID);
    802    vassert(t1 && *t1 == IRTemp_INVALID);
    803    vassert(t2 && *t2 == IRTemp_INVALID);
    804    vassert(t3 && *t3 == IRTemp_INVALID);
    805    *t0 = newTemp(Ity_I64);
    806    *t1 = newTemp(Ity_I64);
    807    *t2 = newTemp(Ity_I64);
    808    *t3 = newTemp(Ity_I64);
    809 
    810    assign( hi64, unop(Iop_V128HIto64, t128) );
    811    assign( lo64, unop(Iop_V128to64,   t128) );
    812    assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    813    assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
    814    assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    815    assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
    816 }
    817 
    818 /* break V128 to 4xI32's, then zero-extend to I64's */
    819 static void breakV128to4x64U ( IRExpr* t128,
    820                                /*OUTs*/
    821                                IRTemp* t3, IRTemp* t2,
    822                                IRTemp* t1, IRTemp* t0 )
    823 {
    824    IRTemp hi64 = newTemp(Ity_I64);
    825    IRTemp lo64 = newTemp(Ity_I64);
    826 
    827    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    828    vassert(t0 && *t0 == IRTemp_INVALID);
    829    vassert(t1 && *t1 == IRTemp_INVALID);
    830    vassert(t2 && *t2 == IRTemp_INVALID);
    831    vassert(t3 && *t3 == IRTemp_INVALID);
    832    *t0 = newTemp(Ity_I64);
    833    *t1 = newTemp(Ity_I64);
    834    *t2 = newTemp(Ity_I64);
    835    *t3 = newTemp(Ity_I64);
    836 
    837    assign( hi64, unop(Iop_V128HIto64, t128) );
    838    assign( lo64, unop(Iop_V128to64,   t128) );
    839    assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    840    assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
    841    assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    842    assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
    843 }
    844 
    845 static void breakV128to4x32( IRExpr* t128,
    846                               /*OUTs*/
    847                               IRTemp* t3, IRTemp* t2,
    848                               IRTemp* t1, IRTemp* t0 )
    849 {
    850    IRTemp hi64 = newTemp(Ity_I64);
    851    IRTemp lo64 = newTemp(Ity_I64);
    852 
    853    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    854    vassert(t0 && *t0 == IRTemp_INVALID);
    855    vassert(t1 && *t1 == IRTemp_INVALID);
    856    vassert(t2 && *t2 == IRTemp_INVALID);
    857    vassert(t3 && *t3 == IRTemp_INVALID);
    858    *t0 = newTemp(Ity_I32);
    859    *t1 = newTemp(Ity_I32);
    860    *t2 = newTemp(Ity_I32);
    861    *t3 = newTemp(Ity_I32);
    862 
    863    assign( hi64, unop(Iop_V128HIto64, t128) );
    864    assign( lo64, unop(Iop_V128to64,   t128) );
    865    assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
    866    assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
    867    assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
    868    assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
    869 }
    870 
    871 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2,
    872                                IRTemp t1, IRTemp t0 )
    873 {
    874    return
    875       binop( Iop_64HLtoV128,
    876              binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
    877              binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
    878    );
    879 }
    880 
    881 
    882 /* Signed saturating narrow 64S to 32 */
    883 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
    884 {
    885    IRTemp hi32 = newTemp(Ity_I32);
    886    IRTemp lo32 = newTemp(Ity_I32);
    887 
    888    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    889 
    890    assign( hi32, unop(Iop_64HIto32, t64));
    891    assign( lo32, unop(Iop_64to32,   t64));
    892 
    893    return IRExpr_ITE(
    894              /* if (hi32 == (lo32 >>s 31)) */
    895              binop(Iop_CmpEQ32, mkexpr(hi32),
    896                    binop( Iop_Sar32, mkexpr(lo32), mkU8(31))),
    897              /* then: within signed-32 range: lo half good enough */
    898              mkexpr(lo32),
    899              /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
    900              binop(Iop_Add32, mkU32(0x7FFFFFFF),
    901                    binop(Iop_Shr32, mkexpr(hi32), mkU8(31))));
    902 }
    903 
    904 /* Unsigned saturating narrow 64S to 32 */
    905 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
    906 {
    907    IRTemp hi32 = newTemp(Ity_I32);
    908    IRTemp lo32 = newTemp(Ity_I32);
    909 
    910    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    911 
    912    assign( hi32, unop(Iop_64HIto32, t64));
    913    assign( lo32, unop(Iop_64to32,   t64));
    914 
    915    return IRExpr_ITE(
    916             /* if (top 32 bits of t64 are 0) */
    917             binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)),
    918             /* then: within unsigned-32 range: lo half good enough */
    919             mkexpr(lo32),
    920             /* else: positive saturate -> 0xFFFFFFFF */
    921             mkU32(0xFFFFFFFF));
    922 }
    923 
    924 /* Signed saturate narrow 64->32, combining to V128 */
    925 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
    926                                  IRExpr* t1, IRExpr* t0 )
    927 {
    928    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    929    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    930    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    931    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    932    return binop(Iop_64HLtoV128,
    933                 binop(Iop_32HLto64,
    934                       mkQNarrow64Sto32( t3 ),
    935                       mkQNarrow64Sto32( t2 )),
    936                 binop(Iop_32HLto64,
    937                       mkQNarrow64Sto32( t1 ),
    938                       mkQNarrow64Sto32( t0 )));
    939 }
    940 
    941 /* Unsigned saturate narrow 64->32, combining to V128 */
    942 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
    943                                  IRExpr* t1, IRExpr* t0 )
    944 {
    945    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    946    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    947    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    948    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    949    return binop(Iop_64HLtoV128,
    950                 binop(Iop_32HLto64,
    951                       mkQNarrow64Uto32( t3 ),
    952                       mkQNarrow64Uto32( t2 )),
    953                 binop(Iop_32HLto64,
    954                       mkQNarrow64Uto32( t1 ),
    955                       mkQNarrow64Uto32( t0 )));
    956 }
    957 
    958 /* Simulate irops Iop_MullOdd*, since we don't have them  */
    959 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
    960       binop(Iop_MullEven8Ux16, \
    961             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    962             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    963 
    964 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
    965       binop(Iop_MullEven8Sx16, \
    966             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    967             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    968 
    969 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
    970       binop(Iop_MullEven16Ux8, \
    971             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    972             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    973 
    974 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
    975       binop(Iop_MullEven32Ux4, \
    976             binop(Iop_ShrV128, expr_vA, mkU8(32)), \
    977             binop(Iop_ShrV128, expr_vB, mkU8(32)))
    978 
    979 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
    980       binop(Iop_MullEven16Sx8, \
    981             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    982             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    983 
    984 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
    985       binop(Iop_MullEven32Sx4, \
    986             binop(Iop_ShrV128, expr_vA, mkU8(32)), \
    987             binop(Iop_ShrV128, expr_vB, mkU8(32)))
    988 
    989 
    990 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
    991 {
    992    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
    993    return unop(Iop_32Sto64, unop(Iop_64to32, src));
    994 }
    995 
    996 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
    997 {
    998    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
    999    return unop(Iop_32Uto64, unop(Iop_64to32, src));
   1000 }
   1001 
   1002 static IROp mkSzOp ( IRType ty, IROp op8 )
   1003 {
   1004    Int adj;
   1005    vassert(ty == Ity_I8  || ty == Ity_I16 ||
   1006            ty == Ity_I32 || ty == Ity_I64);
   1007    vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
   1008            op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
   1009            op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
   1010            op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
   1011            op8 == Iop_Not8 );
   1012    adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
   1013    return adj + op8;
   1014 }
   1015 
   1016 /* Make sure we get valid 32 and 64bit addresses */
   1017 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
   1018 {
   1019    vassert(ty == Ity_I32 || ty == Ity_I64);
   1020    return ( ty == Ity_I64 ?
   1021             (Addr64)addr :
   1022             (Addr64)extend_s_32to64( toUInt(addr) ) );
   1023 }
   1024 
   1025 /* sz, ULong -> IRExpr */
   1026 static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
   1027 {
   1028    vassert(ty == Ity_I32 || ty == Ity_I64);
   1029    return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
   1030 }
   1031 
   1032 /* sz, ULong -> IRConst */
   1033 static IRConst* mkSzConst ( IRType ty, ULong imm64 )
   1034 {
   1035    vassert(ty == Ity_I32 || ty == Ity_I64);
   1036    return ( ty == Ity_I64 ?
   1037             IRConst_U64(imm64) :
   1038             IRConst_U32((UInt)imm64) );
   1039 }
   1040 
   1041 /* Sign extend imm16 -> IRExpr* */
   1042 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
   1043 {
   1044    vassert(ty == Ity_I32 || ty == Ity_I64);
   1045    return ( ty == Ity_I64 ?
   1046             mkU64(extend_s_16to64(imm16)) :
   1047             mkU32(extend_s_16to32(imm16)) );
   1048 }
   1049 
   1050 /* Sign extend imm32 -> IRExpr* */
   1051 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
   1052 {
   1053    vassert(ty == Ity_I32 || ty == Ity_I64);
   1054    return ( ty == Ity_I64 ?
   1055             mkU64(extend_s_32to64(imm32)) :
   1056             mkU32(imm32) );
   1057 }
   1058 
   1059 /* IR narrows I32/I64 -> I8/I16/I32 */
   1060 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
   1061 {
   1062    vassert(ty == Ity_I32 || ty == Ity_I64);
   1063    return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
   1064 }
   1065 
   1066 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
   1067 {
   1068    vassert(ty == Ity_I32 || ty == Ity_I64);
   1069    return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
   1070 }
   1071 
   1072 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
   1073 {
   1074    vassert(ty == Ity_I32 || ty == Ity_I64);
   1075    return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
   1076 }
   1077 
   1078 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
   1079 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
   1080 {
   1081    IROp op;
   1082    vassert(ty == Ity_I32 || ty == Ity_I64);
   1083    if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
   1084    else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
   1085    return unop(op, src);
   1086 }
   1087 
   1088 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
   1089 {
   1090    IROp op;
   1091    vassert(ty == Ity_I32 || ty == Ity_I64);
   1092    if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
   1093    else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
   1094    return unop(op, src);
   1095 }
   1096 
   1097 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
   1098 {
   1099    vassert(ty == Ity_I32 || ty == Ity_I64);
   1100    if (ty == Ity_I32)
   1101       return src;
   1102    return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
   1103 }
   1104 
   1105 
   1106 static Int integerGuestRegOffset ( UInt archreg )
   1107 {
   1108    vassert(archreg < 32);
   1109 
   1110    // jrs: probably not necessary; only matters if we reference sub-parts
   1111    // of the ppc registers, but that isn't the case
   1112    // later: this might affect Altivec though?
   1113 
   1114    switch (archreg) {
   1115    case  0: return offsetofPPCGuestState(guest_GPR0);
   1116    case  1: return offsetofPPCGuestState(guest_GPR1);
   1117    case  2: return offsetofPPCGuestState(guest_GPR2);
   1118    case  3: return offsetofPPCGuestState(guest_GPR3);
   1119    case  4: return offsetofPPCGuestState(guest_GPR4);
   1120    case  5: return offsetofPPCGuestState(guest_GPR5);
   1121    case  6: return offsetofPPCGuestState(guest_GPR6);
   1122    case  7: return offsetofPPCGuestState(guest_GPR7);
   1123    case  8: return offsetofPPCGuestState(guest_GPR8);
   1124    case  9: return offsetofPPCGuestState(guest_GPR9);
   1125    case 10: return offsetofPPCGuestState(guest_GPR10);
   1126    case 11: return offsetofPPCGuestState(guest_GPR11);
   1127    case 12: return offsetofPPCGuestState(guest_GPR12);
   1128    case 13: return offsetofPPCGuestState(guest_GPR13);
   1129    case 14: return offsetofPPCGuestState(guest_GPR14);
   1130    case 15: return offsetofPPCGuestState(guest_GPR15);
   1131    case 16: return offsetofPPCGuestState(guest_GPR16);
   1132    case 17: return offsetofPPCGuestState(guest_GPR17);
   1133    case 18: return offsetofPPCGuestState(guest_GPR18);
   1134    case 19: return offsetofPPCGuestState(guest_GPR19);
   1135    case 20: return offsetofPPCGuestState(guest_GPR20);
   1136    case 21: return offsetofPPCGuestState(guest_GPR21);
   1137    case 22: return offsetofPPCGuestState(guest_GPR22);
   1138    case 23: return offsetofPPCGuestState(guest_GPR23);
   1139    case 24: return offsetofPPCGuestState(guest_GPR24);
   1140    case 25: return offsetofPPCGuestState(guest_GPR25);
   1141    case 26: return offsetofPPCGuestState(guest_GPR26);
   1142    case 27: return offsetofPPCGuestState(guest_GPR27);
   1143    case 28: return offsetofPPCGuestState(guest_GPR28);
   1144    case 29: return offsetofPPCGuestState(guest_GPR29);
   1145    case 30: return offsetofPPCGuestState(guest_GPR30);
   1146    case 31: return offsetofPPCGuestState(guest_GPR31);
   1147    default: break;
   1148    }
   1149    vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
   1150 }
   1151 
   1152 static IRExpr* getIReg ( UInt archreg )
   1153 {
   1154    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1155    vassert(archreg < 32);
   1156    return IRExpr_Get( integerGuestRegOffset(archreg), ty );
   1157 }
   1158 
   1159 /* Ditto, but write to a reg instead. */
   1160 static void putIReg ( UInt archreg, IRExpr* e )
   1161 {
   1162    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1163    vassert(archreg < 32);
   1164    vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
   1165    stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
   1166 }
   1167 
   1168 
   1169 /* Floating point egisters are mapped to VSX registers[0..31]. */
   1170 static Int floatGuestRegOffset ( UInt archreg )
   1171 {
   1172    vassert(archreg < 32);
   1173 
   1174    if (host_endness == VexEndnessLE) {
   1175       switch (archreg) {
   1176          case  0: return offsetofPPCGuestState(guest_VSR0) + 8;
   1177          case  1: return offsetofPPCGuestState(guest_VSR1) + 8;
   1178          case  2: return offsetofPPCGuestState(guest_VSR2) + 8;
   1179          case  3: return offsetofPPCGuestState(guest_VSR3) + 8;
   1180          case  4: return offsetofPPCGuestState(guest_VSR4) + 8;
   1181          case  5: return offsetofPPCGuestState(guest_VSR5) + 8;
   1182          case  6: return offsetofPPCGuestState(guest_VSR6) + 8;
   1183          case  7: return offsetofPPCGuestState(guest_VSR7) + 8;
   1184          case  8: return offsetofPPCGuestState(guest_VSR8) + 8;
   1185          case  9: return offsetofPPCGuestState(guest_VSR9) + 8;
   1186          case 10: return offsetofPPCGuestState(guest_VSR10) + 8;
   1187          case 11: return offsetofPPCGuestState(guest_VSR11) + 8;
   1188          case 12: return offsetofPPCGuestState(guest_VSR12) + 8;
   1189          case 13: return offsetofPPCGuestState(guest_VSR13) + 8;
   1190          case 14: return offsetofPPCGuestState(guest_VSR14) + 8;
   1191          case 15: return offsetofPPCGuestState(guest_VSR15) + 8;
   1192          case 16: return offsetofPPCGuestState(guest_VSR16) + 8;
   1193          case 17: return offsetofPPCGuestState(guest_VSR17) + 8;
   1194          case 18: return offsetofPPCGuestState(guest_VSR18) + 8;
   1195          case 19: return offsetofPPCGuestState(guest_VSR19) + 8;
   1196          case 20: return offsetofPPCGuestState(guest_VSR20) + 8;
   1197          case 21: return offsetofPPCGuestState(guest_VSR21) + 8;
   1198          case 22: return offsetofPPCGuestState(guest_VSR22) + 8;
   1199          case 23: return offsetofPPCGuestState(guest_VSR23) + 8;
   1200          case 24: return offsetofPPCGuestState(guest_VSR24) + 8;
   1201          case 25: return offsetofPPCGuestState(guest_VSR25) + 8;
   1202          case 26: return offsetofPPCGuestState(guest_VSR26) + 8;
   1203          case 27: return offsetofPPCGuestState(guest_VSR27) + 8;
   1204          case 28: return offsetofPPCGuestState(guest_VSR28) + 8;
   1205          case 29: return offsetofPPCGuestState(guest_VSR29) + 8;
   1206          case 30: return offsetofPPCGuestState(guest_VSR30) + 8;
   1207          case 31: return offsetofPPCGuestState(guest_VSR31) + 8;
   1208          default: break;
   1209       }
   1210    } else {
   1211       switch (archreg) {
   1212          case  0: return offsetofPPCGuestState(guest_VSR0);
   1213          case  1: return offsetofPPCGuestState(guest_VSR1);
   1214          case  2: return offsetofPPCGuestState(guest_VSR2);
   1215          case  3: return offsetofPPCGuestState(guest_VSR3);
   1216          case  4: return offsetofPPCGuestState(guest_VSR4);
   1217          case  5: return offsetofPPCGuestState(guest_VSR5);
   1218          case  6: return offsetofPPCGuestState(guest_VSR6);
   1219          case  7: return offsetofPPCGuestState(guest_VSR7);
   1220          case  8: return offsetofPPCGuestState(guest_VSR8);
   1221          case  9: return offsetofPPCGuestState(guest_VSR9);
   1222          case 10: return offsetofPPCGuestState(guest_VSR10);
   1223          case 11: return offsetofPPCGuestState(guest_VSR11);
   1224          case 12: return offsetofPPCGuestState(guest_VSR12);
   1225          case 13: return offsetofPPCGuestState(guest_VSR13);
   1226          case 14: return offsetofPPCGuestState(guest_VSR14);
   1227          case 15: return offsetofPPCGuestState(guest_VSR15);
   1228          case 16: return offsetofPPCGuestState(guest_VSR16);
   1229          case 17: return offsetofPPCGuestState(guest_VSR17);
   1230          case 18: return offsetofPPCGuestState(guest_VSR18);
   1231          case 19: return offsetofPPCGuestState(guest_VSR19);
   1232          case 20: return offsetofPPCGuestState(guest_VSR20);
   1233          case 21: return offsetofPPCGuestState(guest_VSR21);
   1234          case 22: return offsetofPPCGuestState(guest_VSR22);
   1235          case 23: return offsetofPPCGuestState(guest_VSR23);
   1236          case 24: return offsetofPPCGuestState(guest_VSR24);
   1237          case 25: return offsetofPPCGuestState(guest_VSR25);
   1238          case 26: return offsetofPPCGuestState(guest_VSR26);
   1239          case 27: return offsetofPPCGuestState(guest_VSR27);
   1240          case 28: return offsetofPPCGuestState(guest_VSR28);
   1241          case 29: return offsetofPPCGuestState(guest_VSR29);
   1242          case 30: return offsetofPPCGuestState(guest_VSR30);
   1243          case 31: return offsetofPPCGuestState(guest_VSR31);
   1244          default: break;
   1245       }
   1246    }
   1247    vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
   1248 }
   1249 
   1250 static IRExpr* getFReg ( UInt archreg )
   1251 {
   1252    vassert(archreg < 32);
   1253    return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
   1254 }
   1255 
   1256 /* Ditto, but write to a reg instead. */
   1257 static void putFReg ( UInt archreg, IRExpr* e )
   1258 {
   1259    vassert(archreg < 32);
   1260    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
   1261    stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
   1262 }
   1263 
   1264 /* get Decimal float value.  Note, they share floating point register file. */
   1265 static IRExpr* getDReg(UInt archreg) {
   1266    IRExpr *e;
   1267    vassert( archreg < 32 );
   1268    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
   1269    return e;
   1270 }
   1271 static IRExpr* getDReg32(UInt archreg) {
   1272    IRExpr *e;
   1273    vassert( archreg < 32 );
   1274    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
   1275    return e;
   1276 }
   1277 
   1278 /* Read a floating point register pair and combine their contents into a
   1279  128-bit value */
   1280 static IRExpr *getDReg_pair(UInt archreg) {
   1281    IRExpr *high = getDReg( archreg );
   1282    IRExpr *low = getDReg( archreg + 1 );
   1283 
   1284    return binop( Iop_D64HLtoD128, high, low );
   1285 }
   1286 
   1287 /* Ditto, but write to a reg instead. */
   1288 static void putDReg32(UInt archreg, IRExpr* e) {
   1289    vassert( archreg < 32 );
   1290    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
   1291    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
   1292 }
   1293 
   1294 static void putDReg(UInt archreg, IRExpr* e) {
   1295    vassert( archreg < 32 );
   1296    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
   1297    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
   1298 }
   1299 
   1300 /* Write a 128-bit floating point value into a register pair. */
   1301 static void putDReg_pair(UInt archreg, IRExpr *e) {
   1302    IRTemp low = newTemp( Ity_D64 );
   1303    IRTemp high = newTemp( Ity_D64 );
   1304 
   1305    vassert( archreg < 32 );
   1306    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
   1307 
   1308    assign( low, unop( Iop_D128LOtoD64, e ) );
   1309    assign( high, unop( Iop_D128HItoD64, e ) );
   1310 
   1311    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
   1312    stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
   1313 }
   1314 
   1315 static Int vsxGuestRegOffset ( UInt archreg )
   1316 {
   1317    vassert(archreg < 64);
   1318    switch (archreg) {
   1319    case  0: return offsetofPPCGuestState(guest_VSR0);
   1320    case  1: return offsetofPPCGuestState(guest_VSR1);
   1321    case  2: return offsetofPPCGuestState(guest_VSR2);
   1322    case  3: return offsetofPPCGuestState(guest_VSR3);
   1323    case  4: return offsetofPPCGuestState(guest_VSR4);
   1324    case  5: return offsetofPPCGuestState(guest_VSR5);
   1325    case  6: return offsetofPPCGuestState(guest_VSR6);
   1326    case  7: return offsetofPPCGuestState(guest_VSR7);
   1327    case  8: return offsetofPPCGuestState(guest_VSR8);
   1328    case  9: return offsetofPPCGuestState(guest_VSR9);
   1329    case 10: return offsetofPPCGuestState(guest_VSR10);
   1330    case 11: return offsetofPPCGuestState(guest_VSR11);
   1331    case 12: return offsetofPPCGuestState(guest_VSR12);
   1332    case 13: return offsetofPPCGuestState(guest_VSR13);
   1333    case 14: return offsetofPPCGuestState(guest_VSR14);
   1334    case 15: return offsetofPPCGuestState(guest_VSR15);
   1335    case 16: return offsetofPPCGuestState(guest_VSR16);
   1336    case 17: return offsetofPPCGuestState(guest_VSR17);
   1337    case 18: return offsetofPPCGuestState(guest_VSR18);
   1338    case 19: return offsetofPPCGuestState(guest_VSR19);
   1339    case 20: return offsetofPPCGuestState(guest_VSR20);
   1340    case 21: return offsetofPPCGuestState(guest_VSR21);
   1341    case 22: return offsetofPPCGuestState(guest_VSR22);
   1342    case 23: return offsetofPPCGuestState(guest_VSR23);
   1343    case 24: return offsetofPPCGuestState(guest_VSR24);
   1344    case 25: return offsetofPPCGuestState(guest_VSR25);
   1345    case 26: return offsetofPPCGuestState(guest_VSR26);
   1346    case 27: return offsetofPPCGuestState(guest_VSR27);
   1347    case 28: return offsetofPPCGuestState(guest_VSR28);
   1348    case 29: return offsetofPPCGuestState(guest_VSR29);
   1349    case 30: return offsetofPPCGuestState(guest_VSR30);
   1350    case 31: return offsetofPPCGuestState(guest_VSR31);
   1351    case 32: return offsetofPPCGuestState(guest_VSR32);
   1352    case 33: return offsetofPPCGuestState(guest_VSR33);
   1353    case 34: return offsetofPPCGuestState(guest_VSR34);
   1354    case 35: return offsetofPPCGuestState(guest_VSR35);
   1355    case 36: return offsetofPPCGuestState(guest_VSR36);
   1356    case 37: return offsetofPPCGuestState(guest_VSR37);
   1357    case 38: return offsetofPPCGuestState(guest_VSR38);
   1358    case 39: return offsetofPPCGuestState(guest_VSR39);
   1359    case 40: return offsetofPPCGuestState(guest_VSR40);
   1360    case 41: return offsetofPPCGuestState(guest_VSR41);
   1361    case 42: return offsetofPPCGuestState(guest_VSR42);
   1362    case 43: return offsetofPPCGuestState(guest_VSR43);
   1363    case 44: return offsetofPPCGuestState(guest_VSR44);
   1364    case 45: return offsetofPPCGuestState(guest_VSR45);
   1365    case 46: return offsetofPPCGuestState(guest_VSR46);
   1366    case 47: return offsetofPPCGuestState(guest_VSR47);
   1367    case 48: return offsetofPPCGuestState(guest_VSR48);
   1368    case 49: return offsetofPPCGuestState(guest_VSR49);
   1369    case 50: return offsetofPPCGuestState(guest_VSR50);
   1370    case 51: return offsetofPPCGuestState(guest_VSR51);
   1371    case 52: return offsetofPPCGuestState(guest_VSR52);
   1372    case 53: return offsetofPPCGuestState(guest_VSR53);
   1373    case 54: return offsetofPPCGuestState(guest_VSR54);
   1374    case 55: return offsetofPPCGuestState(guest_VSR55);
   1375    case 56: return offsetofPPCGuestState(guest_VSR56);
   1376    case 57: return offsetofPPCGuestState(guest_VSR57);
   1377    case 58: return offsetofPPCGuestState(guest_VSR58);
   1378    case 59: return offsetofPPCGuestState(guest_VSR59);
   1379    case 60: return offsetofPPCGuestState(guest_VSR60);
   1380    case 61: return offsetofPPCGuestState(guest_VSR61);
   1381    case 62: return offsetofPPCGuestState(guest_VSR62);
   1382    case 63: return offsetofPPCGuestState(guest_VSR63);
   1383    default: break;
   1384    }
   1385    vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
   1386 }
   1387 
   1388 /* Vector registers are mapped to VSX registers[32..63]. */
   1389 static Int vectorGuestRegOffset ( UInt archreg )
   1390 {
   1391    vassert(archreg < 32);
   1392 
   1393    switch (archreg) {
   1394    case  0: return offsetofPPCGuestState(guest_VSR32);
   1395    case  1: return offsetofPPCGuestState(guest_VSR33);
   1396    case  2: return offsetofPPCGuestState(guest_VSR34);
   1397    case  3: return offsetofPPCGuestState(guest_VSR35);
   1398    case  4: return offsetofPPCGuestState(guest_VSR36);
   1399    case  5: return offsetofPPCGuestState(guest_VSR37);
   1400    case  6: return offsetofPPCGuestState(guest_VSR38);
   1401    case  7: return offsetofPPCGuestState(guest_VSR39);
   1402    case  8: return offsetofPPCGuestState(guest_VSR40);
   1403    case  9: return offsetofPPCGuestState(guest_VSR41);
   1404    case 10: return offsetofPPCGuestState(guest_VSR42);
   1405    case 11: return offsetofPPCGuestState(guest_VSR43);
   1406    case 12: return offsetofPPCGuestState(guest_VSR44);
   1407    case 13: return offsetofPPCGuestState(guest_VSR45);
   1408    case 14: return offsetofPPCGuestState(guest_VSR46);
   1409    case 15: return offsetofPPCGuestState(guest_VSR47);
   1410    case 16: return offsetofPPCGuestState(guest_VSR48);
   1411    case 17: return offsetofPPCGuestState(guest_VSR49);
   1412    case 18: return offsetofPPCGuestState(guest_VSR50);
   1413    case 19: return offsetofPPCGuestState(guest_VSR51);
   1414    case 20: return offsetofPPCGuestState(guest_VSR52);
   1415    case 21: return offsetofPPCGuestState(guest_VSR53);
   1416    case 22: return offsetofPPCGuestState(guest_VSR54);
   1417    case 23: return offsetofPPCGuestState(guest_VSR55);
   1418    case 24: return offsetofPPCGuestState(guest_VSR56);
   1419    case 25: return offsetofPPCGuestState(guest_VSR57);
   1420    case 26: return offsetofPPCGuestState(guest_VSR58);
   1421    case 27: return offsetofPPCGuestState(guest_VSR59);
   1422    case 28: return offsetofPPCGuestState(guest_VSR60);
   1423    case 29: return offsetofPPCGuestState(guest_VSR61);
   1424    case 30: return offsetofPPCGuestState(guest_VSR62);
   1425    case 31: return offsetofPPCGuestState(guest_VSR63);
   1426    default: break;
   1427    }
   1428    vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
   1429 }
   1430 
   1431 static IRExpr* getVReg ( UInt archreg )
   1432 {
   1433    vassert(archreg < 32);
   1434    return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
   1435 }
   1436 
   1437 /* Ditto, but write to a reg instead. */
   1438 static void putVReg ( UInt archreg, IRExpr* e )
   1439 {
   1440    vassert(archreg < 32);
   1441    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
   1442    stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
   1443 }
   1444 
   1445 /* Get contents of VSX guest register */
   1446 static IRExpr* getVSReg ( UInt archreg )
   1447 {
   1448    vassert(archreg < 64);
   1449    return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
   1450 }
   1451 
   1452 /* Ditto, but write to a VSX reg instead. */
   1453 static void putVSReg ( UInt archreg, IRExpr* e )
   1454 {
   1455    vassert(archreg < 64);
   1456    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
   1457    stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
   1458 }
   1459 
   1460 
   1461 static Int guestCR321offset ( UInt cr )
   1462 {
   1463    switch (cr) {
   1464    case 0: return offsetofPPCGuestState(guest_CR0_321 );
   1465    case 1: return offsetofPPCGuestState(guest_CR1_321 );
   1466    case 2: return offsetofPPCGuestState(guest_CR2_321 );
   1467    case 3: return offsetofPPCGuestState(guest_CR3_321 );
   1468    case 4: return offsetofPPCGuestState(guest_CR4_321 );
   1469    case 5: return offsetofPPCGuestState(guest_CR5_321 );
   1470    case 6: return offsetofPPCGuestState(guest_CR6_321 );
   1471    case 7: return offsetofPPCGuestState(guest_CR7_321 );
   1472    default: vpanic("guestCR321offset(ppc)");
   1473    }
   1474 }
   1475 
   1476 static Int guestCR0offset ( UInt cr )
   1477 {
   1478    switch (cr) {
   1479    case 0: return offsetofPPCGuestState(guest_CR0_0 );
   1480    case 1: return offsetofPPCGuestState(guest_CR1_0 );
   1481    case 2: return offsetofPPCGuestState(guest_CR2_0 );
   1482    case 3: return offsetofPPCGuestState(guest_CR3_0 );
   1483    case 4: return offsetofPPCGuestState(guest_CR4_0 );
   1484    case 5: return offsetofPPCGuestState(guest_CR5_0 );
   1485    case 6: return offsetofPPCGuestState(guest_CR6_0 );
   1486    case 7: return offsetofPPCGuestState(guest_CR7_0 );
   1487    default: vpanic("guestCR3offset(ppc)");
   1488    }
   1489 }
   1490 
   1491 typedef enum {
   1492    _placeholder0,
   1493    _placeholder1,
   1494    _placeholder2,
   1495    BYTE,
   1496    HWORD,
   1497    WORD,
   1498    DWORD
   1499 } _popcount_data_type;
   1500 
   1501 /* Generate an IR sequence to do a popcount operation on the supplied
   1502    IRTemp, and return a new IRTemp holding the result.  'ty' may be
   1503    Ity_I32 or Ity_I64 only. */
   1504 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type )
   1505 {
   1506   /* Do count across 2^data_type bits,
   1507      byte:        data_type = 3
   1508      half word:   data_type = 4
   1509      word:        data_type = 5
   1510      double word: data_type = 6  (not supported for 32-bit type)
   1511     */
   1512    Int shift[6];
   1513    _popcount_data_type idx, i;
   1514    IRTemp mask[6];
   1515    IRTemp old = IRTemp_INVALID;
   1516    IRTemp nyu = IRTemp_INVALID;
   1517 
   1518    vassert(ty == Ity_I64 || ty == Ity_I32);
   1519 
   1520    if (ty == Ity_I32) {
   1521 
   1522       for (idx = 0; idx < WORD; idx++) {
   1523          mask[idx]  = newTemp(ty);
   1524          shift[idx] = 1 << idx;
   1525       }
   1526       assign(mask[0], mkU32(0x55555555));
   1527       assign(mask[1], mkU32(0x33333333));
   1528       assign(mask[2], mkU32(0x0F0F0F0F));
   1529       assign(mask[3], mkU32(0x00FF00FF));
   1530       assign(mask[4], mkU32(0x0000FFFF));
   1531       old = src;
   1532       for (i = 0; i < data_type; i++) {
   1533          nyu = newTemp(ty);
   1534          assign(nyu,
   1535                 binop(Iop_Add32,
   1536                       binop(Iop_And32,
   1537                             mkexpr(old),
   1538                             mkexpr(mask[i])),
   1539                       binop(Iop_And32,
   1540                             binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
   1541                             mkexpr(mask[i]))));
   1542          old = nyu;
   1543       }
   1544       return nyu;
   1545    }
   1546 
   1547 // else, ty == Ity_I64
   1548    vassert(mode64);
   1549 
   1550    for (i = 0; i < DWORD; i++) {
   1551       mask[i] = newTemp( Ity_I64 );
   1552       shift[i] = 1 << i;
   1553    }
   1554    assign( mask[0], mkU64( 0x5555555555555555ULL ) );
   1555    assign( mask[1], mkU64( 0x3333333333333333ULL ) );
   1556    assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
   1557    assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
   1558    assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
   1559    assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
   1560    old = src;
   1561    for (i = 0; i < data_type; i++) {
   1562       nyu = newTemp( Ity_I64 );
   1563       assign( nyu,
   1564               binop( Iop_Add64,
   1565                      binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
   1566                      binop( Iop_And64,
   1567                             binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
   1568                             mkexpr( mask[i] ) ) ) );
   1569       old = nyu;
   1570    }
   1571    return nyu;
   1572 }
   1573 
   1574 /* Special purpose population count function for
   1575  * vpopcntd in 32-bit mode.
   1576  */
   1577 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 )
   1578 {
   1579    Int i, shift[6];
   1580    IRTemp mask[6];
   1581    IRTemp old = IRTemp_INVALID;
   1582    IRTemp nyu1 = IRTemp_INVALID;
   1583    IRTemp nyu2 = IRTemp_INVALID;
   1584    IRTemp retval = newTemp(Ity_I64);
   1585 
   1586    vassert(!mode64);
   1587 
   1588    for (i = 0; i < WORD; i++) {
   1589       mask[i]  = newTemp(Ity_I32);
   1590       shift[i] = 1 << i;
   1591    }
   1592    assign(mask[0], mkU32(0x55555555));
   1593    assign(mask[1], mkU32(0x33333333));
   1594    assign(mask[2], mkU32(0x0F0F0F0F));
   1595    assign(mask[3], mkU32(0x00FF00FF));
   1596    assign(mask[4], mkU32(0x0000FFFF));
   1597    old = src1;
   1598    for (i = 0; i < WORD; i++) {
   1599       nyu1 = newTemp(Ity_I32);
   1600       assign(nyu1,
   1601              binop(Iop_Add32,
   1602                    binop(Iop_And32,
   1603                          mkexpr(old),
   1604                          mkexpr(mask[i])),
   1605                    binop(Iop_And32,
   1606                          binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
   1607                          mkexpr(mask[i]))));
   1608       old = nyu1;
   1609    }
   1610 
   1611    old = src2;
   1612    for (i = 0; i < WORD; i++) {
   1613       nyu2 = newTemp(Ity_I32);
   1614       assign(nyu2,
   1615              binop(Iop_Add32,
   1616                    binop(Iop_And32,
   1617                          mkexpr(old),
   1618                          mkexpr(mask[i])),
   1619                    binop(Iop_And32,
   1620                          binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
   1621                          mkexpr(mask[i]))));
   1622       old = nyu2;
   1623    }
   1624    assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2))));
   1625    return retval;
   1626 }
   1627 
   1628 
   1629 // ROTL(src32/64, rot_amt5/6)
   1630 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
   1631                                           IRExpr* rot_amt )
   1632 {
   1633    IRExpr *mask, *rot;
   1634    vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
   1635 
   1636    if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
   1637       // rot = (src << rot_amt) | (src >> (64-rot_amt))
   1638       mask = binop(Iop_And8, rot_amt, mkU8(63));
   1639       rot  = binop(Iop_Or64,
   1640                 binop(Iop_Shl64, src, mask),
   1641                 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
   1642    } else {
   1643       // rot = (src << rot_amt) | (src >> (32-rot_amt))
   1644       mask = binop(Iop_And8, rot_amt, mkU8(31));
   1645       rot  = binop(Iop_Or32,
   1646                 binop(Iop_Shl32, src, mask),
   1647                 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
   1648    }
   1649    /* Note: the ITE not merely an optimisation; it's needed
   1650       because otherwise the Shr is a shift by the word size when
   1651       mask denotes zero.  For rotates by immediates, a lot of
   1652       this junk gets folded out. */
   1653    return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)),
   1654                       /* non-zero rotate */ rot,
   1655                       /*     zero rotate */ src);
   1656 }
   1657 
   1658 /* Standard effective address calc: (rA + rB) */
   1659 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
   1660 {
   1661    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1662    vassert(rA < 32);
   1663    vassert(rB < 32);
   1664    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
   1665 }
   1666 
   1667 /* Standard effective address calc: (rA + simm) */
   1668 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
   1669 {
   1670    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1671    vassert(rA < 32);
   1672    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
   1673                 mkSzExtendS16(ty, simm16));
   1674 }
   1675 
   1676 /* Standard effective address calc: (rA|0) */
   1677 static IRExpr* ea_rAor0 ( UInt rA )
   1678 {
   1679    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1680    vassert(rA < 32);
   1681    if (rA == 0) {
   1682       return mkSzImm(ty, 0);
   1683    } else {
   1684       return getIReg(rA);
   1685    }
   1686 }
   1687 
   1688 /* Standard effective address calc: (rA|0) + rB */
   1689 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
   1690 {
   1691    vassert(rA < 32);
   1692    vassert(rB < 32);
   1693    return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
   1694 }
   1695 
   1696 /* Standard effective address calc: (rA|0) + simm16 */
   1697 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
   1698 {
   1699    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1700    vassert(rA < 32);
   1701    if (rA == 0) {
   1702       return mkSzExtendS16(ty, simm16);
   1703    } else {
   1704       return ea_rA_simm( rA, simm16 );
   1705    }
   1706 }
   1707 
   1708 
   1709 /* Align effective address */
   1710 static IRExpr* addr_align( IRExpr* addr, UChar align )
   1711 {
   1712    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1713    Long mask;
   1714    switch (align) {
   1715    case 1:  return addr;                    // byte aligned
   1716    case 2:  mask = ((Long)-1) << 1; break;  // half-word aligned
   1717    case 4:  mask = ((Long)-1) << 2; break;  // word aligned
   1718    case 16: mask = ((Long)-1) << 4; break;  // quad-word aligned
   1719    default:
   1720       vex_printf("addr_align: align = %u\n", align);
   1721       vpanic("addr_align(ppc)");
   1722    }
   1723 
   1724    vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
   1725    return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
   1726 }
   1727 
   1728 
   1729 /* Exit the trace if ADDR (intended to be a guest memory address) is
   1730    not ALIGN-aligned, generating a request for a SIGBUS followed by a
   1731    restart of the current insn. */
   1732 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
   1733 {
   1734    vassert(align == 2 || align == 4 || align == 8 || align == 16);
   1735    if (mode64) {
   1736       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
   1737       stmt(
   1738          IRStmt_Exit(
   1739             binop(Iop_CmpNE64,
   1740                   binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
   1741                   mkU64(0)),
   1742             Ijk_SigBUS,
   1743             IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
   1744          )
   1745       );
   1746    } else {
   1747       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
   1748       stmt(
   1749          IRStmt_Exit(
   1750             binop(Iop_CmpNE32,
   1751                   binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
   1752                   mkU32(0)),
   1753             Ijk_SigBUS,
   1754             IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
   1755          )
   1756       );
   1757    }
   1758 }
   1759 
   1760 
   1761 /* Generate AbiHints which mark points at which the ELF or PowerOpen
   1762    ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
   1763    N) becomes undefined.  That is at function calls and returns.  ELF
   1764    ppc32 doesn't have this "feature" (how fortunate for it).  nia is
   1765    the address of the next instruction to be executed.
   1766 */
   1767 static void make_redzone_AbiHint ( const VexAbiInfo* vbi,
   1768                                    IRTemp nia, const HChar* who )
   1769 {
   1770    Int szB = vbi->guest_stack_redzone_size;
   1771    if (0) vex_printf("AbiHint: %s\n", who);
   1772    vassert(szB >= 0);
   1773    if (szB > 0) {
   1774       if (mode64) {
   1775          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
   1776          stmt( IRStmt_AbiHint(
   1777                   binop(Iop_Sub64, getIReg(1), mkU64(szB)),
   1778                   szB,
   1779                   mkexpr(nia)
   1780          ));
   1781       } else {
   1782          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
   1783          stmt( IRStmt_AbiHint(
   1784                   binop(Iop_Sub32, getIReg(1), mkU32(szB)),
   1785                   szB,
   1786                   mkexpr(nia)
   1787          ));
   1788       }
   1789    }
   1790 }
   1791 
   1792 
   1793 /*------------------------------------------------------------*/
   1794 /*--- Helpers for condition codes.                         ---*/
   1795 /*------------------------------------------------------------*/
   1796 
   1797 /* Condition register layout.
   1798 
   1799    In the hardware, CR is laid out like this.  The leftmost end is the
   1800    most significant bit in the register; however the IBM documentation
   1801    numbers the bits backwards for some reason.
   1802 
   1803    CR0      CR1    ..........   CR6       CR7
   1804    0 .. 3   .......................  28 .. 31    (IBM bit numbering)
   1805    31  28                             3    0     (normal bit numbering)
   1806 
   1807    Each CR field is 4 bits:  [<,>,==,SO]
   1808 
   1809    Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
   1810 
   1811    Indexing from BI to guest state:
   1812 
   1813      let    n = BI / 4
   1814           off = BI % 4
   1815      this references CR n:
   1816 
   1817         off==0   ->  guest_CRn_321 >> 3
   1818         off==1   ->  guest_CRn_321 >> 2
   1819         off==2   ->  guest_CRn_321 >> 1
   1820         off==3   ->  guest_CRn_SO
   1821 
   1822    Bear in mind the only significant bit in guest_CRn_SO is bit 0
   1823    (normal notation) and in guest_CRn_321 the significant bits are
   1824    3, 2 and 1 (normal notation).
   1825 */
   1826 
   1827 static void putCR321 ( UInt cr, IRExpr* e )
   1828 {
   1829    vassert(cr < 8);
   1830    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1831    stmt( IRStmt_Put(guestCR321offset(cr), e) );
   1832 }
   1833 
   1834 static void putCR0 ( UInt cr, IRExpr* e )
   1835 {
   1836    vassert(cr < 8);
   1837    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1838    stmt( IRStmt_Put(guestCR0offset(cr), e) );
   1839 }
   1840 
   1841 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
   1842 {
   1843    vassert(cr < 8);
   1844    return IRExpr_Get(guestCR0offset(cr), Ity_I8);
   1845 }
   1846 
   1847 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
   1848 {
   1849    vassert(cr < 8);
   1850    return IRExpr_Get(guestCR321offset(cr), Ity_I8);
   1851 }
   1852 
   1853 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1854    return it at the bottom of an I32; the top 31 bits are guaranteed
   1855    to be zero. */
   1856 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
   1857 {
   1858    UInt n   = bi / 4;
   1859    UInt off = bi % 4;
   1860    vassert(bi < 32);
   1861    if (off == 3) {
   1862       /* Fetch the SO bit for this CR field */
   1863       /* Note: And32 is redundant paranoia iff guest state only has 0
   1864          or 1 in that slot. */
   1865       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1866    } else {
   1867       /* Fetch the <, > or == bit for this CR field */
   1868       return binop( Iop_And32,
   1869                     binop( Iop_Shr32,
   1870                            unop(Iop_8Uto32, getCR321(n)),
   1871                            mkU8(toUChar(3-off)) ),
   1872                     mkU32(1) );
   1873    }
   1874 }
   1875 
   1876 /* Dually, write the least significant bit of BIT to the specified CR
   1877    bit.  Indexing as per getCRbit. */
   1878 static void putCRbit ( UInt bi, IRExpr* bit )
   1879 {
   1880    UInt    n, off;
   1881    IRExpr* safe;
   1882    vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
   1883    safe = binop(Iop_And32, bit, mkU32(1));
   1884    n   = bi / 4;
   1885    off = bi % 4;
   1886    vassert(bi < 32);
   1887    if (off == 3) {
   1888       /* This is the SO bit for this CR field */
   1889       putCR0(n, unop(Iop_32to8, safe));
   1890    } else {
   1891       off = 3 - off;
   1892       vassert(off == 1 || off == 2 || off == 3);
   1893       putCR321(
   1894          n,
   1895          unop( Iop_32to8,
   1896                binop( Iop_Or32,
   1897                       /* old value with field masked out */
   1898                       binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
   1899                                        mkU32(~(1 << off))),
   1900                       /* new value in the right place */
   1901                       binop(Iop_Shl32, safe, mkU8(toUChar(off)))
   1902                )
   1903          )
   1904       );
   1905    }
   1906 }
   1907 
   1908 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1909    return it somewhere in an I32; it does not matter where, but
   1910    whichever bit it is, all other bits are guaranteed to be zero.  In
   1911    other words, the I32-typed expression will be zero if the bit is
   1912    zero and nonzero if the bit is 1.  Write into *where the index
   1913    of where the bit will be. */
   1914 
   1915 static
   1916 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
   1917 {
   1918    UInt n   = bi / 4;
   1919    UInt off = bi % 4;
   1920    vassert(bi < 32);
   1921    if (off == 3) {
   1922       /* Fetch the SO bit for this CR field */
   1923       /* Note: And32 is redundant paranoia iff guest state only has 0
   1924          or 1 in that slot. */
   1925       *where = 0;
   1926       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1927    } else {
   1928       /* Fetch the <, > or == bit for this CR field */
   1929       *where = 3-off;
   1930       return binop( Iop_And32,
   1931                     unop(Iop_8Uto32, getCR321(n)),
   1932                     mkU32(1 << (3-off)) );
   1933    }
   1934 }
   1935 
   1936 /* Set the CR0 flags following an arithmetic operation.
   1937    (Condition Register CR0 Field Definition, PPC32 p60)
   1938 */
   1939 static IRExpr* getXER_SO ( void );
   1940 static void set_CR0 ( IRExpr* result )
   1941 {
   1942    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
   1943            typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
   1944    if (mode64) {
   1945       putCR321( 0, unop(Iop_64to8,
   1946                         binop(Iop_CmpORD64S, result, mkU64(0))) );
   1947    } else {
   1948       putCR321( 0, unop(Iop_32to8,
   1949                         binop(Iop_CmpORD32S, result, mkU32(0))) );
   1950    }
   1951    putCR0( 0, getXER_SO() );
   1952 }
   1953 
   1954 
   1955 /* Set the CR6 flags following an AltiVec compare operation.
   1956  * NOTE: This also works for VSX single-precision compares.
   1957  * */
   1958 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
   1959 {
   1960    /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
   1961       all_ones  = (v[0] && v[1] && v[2] && v[3])
   1962       all_zeros = ~(v[0] || v[1] || v[2] || v[3])
   1963    */
   1964    IRTemp v0 = newTemp(Ity_V128);
   1965    IRTemp v1 = newTemp(Ity_V128);
   1966    IRTemp v2 = newTemp(Ity_V128);
   1967    IRTemp v3 = newTemp(Ity_V128);
   1968    IRTemp rOnes  = newTemp(Ity_I8);
   1969    IRTemp rZeros = newTemp(Ity_I8);
   1970 
   1971    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
   1972 
   1973    assign( v0, result );
   1974    assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
   1975    assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
   1976    assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
   1977 
   1978    assign( rZeros, unop(Iop_1Uto8,
   1979        binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   1980              unop(Iop_Not32,
   1981                   unop(Iop_V128to32,
   1982                        binop(Iop_OrV128,
   1983                              binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
   1984                              binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
   1985                   ))) );
   1986 
   1987    if (test_all_ones) {
   1988       assign( rOnes, unop(Iop_1Uto8,
   1989          binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   1990                unop(Iop_V128to32,
   1991                     binop(Iop_AndV128,
   1992                           binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
   1993                           binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
   1994                     ))) );
   1995       putCR321( 6, binop(Iop_Or8,
   1996                          binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
   1997                          binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
   1998    } else {
   1999       putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
   2000    }
   2001    putCR0( 6, mkU8(0) );
   2002 }
   2003 
   2004 
   2005 
   2006 /*------------------------------------------------------------*/
   2007 /*--- Helpers for XER flags.                               ---*/
   2008 /*------------------------------------------------------------*/
   2009 
   2010 static void putXER_SO ( IRExpr* e )
   2011 {
   2012    IRExpr* so;
   2013    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   2014    so = binop(Iop_And8, e, mkU8(1));
   2015    stmt( IRStmt_Put( OFFB_XER_SO, so ) );
   2016 }
   2017 
   2018 static void putXER_OV ( IRExpr* e )
   2019 {
   2020    IRExpr* ov;
   2021    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   2022    ov = binop(Iop_And8, e, mkU8(1));
   2023    stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
   2024 }
   2025 
   2026 static void putXER_CA ( IRExpr* e )
   2027 {
   2028    IRExpr* ca;
   2029    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   2030    ca = binop(Iop_And8, e, mkU8(1));
   2031    stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
   2032 }
   2033 
   2034 static void putXER_BC ( IRExpr* e )
   2035 {
   2036    IRExpr* bc;
   2037    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   2038    bc = binop(Iop_And8, e, mkU8(0x7F));
   2039    stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
   2040 }
   2041 
   2042 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
   2043 {
   2044    return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
   2045 }
   2046 
   2047 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
   2048 {
   2049    return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
   2050 }
   2051 
   2052 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
   2053 {
   2054    return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
   2055 }
   2056 
   2057 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
   2058 {
   2059    return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
   2060 }
   2061 
   2062 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
   2063 {
   2064    IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
   2065    return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
   2066 }
   2067 
   2068 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
   2069 {
   2070    return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   2071 }
   2072 
   2073 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
   2074 {
   2075    IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   2076    return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
   2077 }
   2078 
   2079 
   2080 /* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
   2081    %XER.SO accordingly. */
   2082 
   2083 static void set_XER_OV_32( UInt op, IRExpr* res,
   2084                            IRExpr* argL, IRExpr* argR )
   2085 {
   2086    IRTemp  t64;
   2087    IRExpr* xer_ov;
   2088    vassert(op < PPCG_FLAG_OP_NUMBER);
   2089    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
   2090    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
   2091    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
   2092 
   2093 #  define INT32_MIN 0x80000000
   2094 
   2095 #  define XOR2(_aa,_bb) \
   2096       binop(Iop_Xor32,(_aa),(_bb))
   2097 
   2098 #  define XOR3(_cc,_dd,_ee) \
   2099       binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
   2100 
   2101 #  define AND3(_ff,_gg,_hh) \
   2102       binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
   2103 
   2104 #define NOT(_jj) \
   2105       unop(Iop_Not32, (_jj))
   2106 
   2107    switch (op) {
   2108    case /* 0  */ PPCG_FLAG_OP_ADD:
   2109    case /* 1  */ PPCG_FLAG_OP_ADDE:
   2110       /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
   2111       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   2112       xer_ov
   2113          = AND3( XOR3(argL,argR,mkU32(-1)),
   2114                  XOR2(argL,res),
   2115                  mkU32(INT32_MIN) );
   2116       /* xer_ov can only be 0 or 1<<31 */
   2117       xer_ov
   2118          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   2119       break;
   2120 
   2121    case /* 2  */ PPCG_FLAG_OP_DIVW:
   2122       /* (argL == INT32_MIN && argR == -1) || argR == 0 */
   2123       xer_ov
   2124          = mkOR1(
   2125               mkAND1(
   2126                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
   2127                  binop(Iop_CmpEQ32, argR, mkU32(-1))
   2128               ),
   2129               binop(Iop_CmpEQ32, argR, mkU32(0) )
   2130            );
   2131       xer_ov
   2132          = unop(Iop_1Uto32, xer_ov);
   2133       break;
   2134 
   2135    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   2136       /* argR == 0 */
   2137       xer_ov
   2138          = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
   2139       break;
   2140 
   2141    case /* 4  */ PPCG_FLAG_OP_MULLW:
   2142       /* OV true if result can't be represented in 32 bits
   2143          i.e sHi != sign extension of sLo */
   2144       t64 = newTemp(Ity_I64);
   2145       assign( t64, binop(Iop_MullS32, argL, argR) );
   2146       xer_ov
   2147          = binop( Iop_CmpNE32,
   2148                   unop(Iop_64HIto32, mkexpr(t64)),
   2149                   binop( Iop_Sar32,
   2150                          unop(Iop_64to32, mkexpr(t64)),
   2151                          mkU8(31))
   2152                   );
   2153       xer_ov
   2154          = unop(Iop_1Uto32, xer_ov);
   2155       break;
   2156 
   2157    case /* 5  */ PPCG_FLAG_OP_NEG:
   2158       /* argL == INT32_MIN */
   2159       xer_ov
   2160          = unop( Iop_1Uto32,
   2161                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
   2162       break;
   2163 
   2164    case /* 6  */ PPCG_FLAG_OP_SUBF:
   2165    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   2166    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   2167       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
   2168       xer_ov
   2169          = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
   2170                  XOR2(NOT(argL),res),
   2171                  mkU32(INT32_MIN) );
   2172       /* xer_ov can only be 0 or 1<<31 */
   2173       xer_ov
   2174          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   2175       break;
   2176 
   2177    case PPCG_FLAG_OP_DIVWEU:
   2178       xer_ov
   2179                = binop( Iop_Or32,
   2180                         unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
   2181                         unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
   2182       break;
   2183 
   2184    case PPCG_FLAG_OP_DIVWE:
   2185 
   2186       /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
   2187        * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
   2188        * an overflow is implied.
   2189        */
   2190       xer_ov = binop( Iop_Or32,
   2191                       unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
   2192                       unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
   2193                               mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
   2194                                       binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
   2195       break;
   2196 
   2197 
   2198 
   2199    default:
   2200       vex_printf("set_XER_OV: op = %u\n", op);
   2201       vpanic("set_XER_OV(ppc)");
   2202    }
   2203 
   2204    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   2205    putXER_OV( unop(Iop_32to8, xer_ov) );
   2206 
   2207    /* Update the summary overflow */
   2208    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   2209 
   2210 #  undef INT32_MIN
   2211 #  undef AND3
   2212 #  undef XOR3
   2213 #  undef XOR2
   2214 #  undef NOT
   2215 }
   2216 
   2217 static void set_XER_OV_64( UInt op, IRExpr* res,
   2218                            IRExpr* argL, IRExpr* argR )
   2219 {
   2220    IRExpr* xer_ov;
   2221    vassert(op < PPCG_FLAG_OP_NUMBER);
   2222    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
   2223    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
   2224    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
   2225 
   2226 #  define INT64_MIN 0x8000000000000000ULL
   2227 
   2228 #  define XOR2(_aa,_bb) \
   2229       binop(Iop_Xor64,(_aa),(_bb))
   2230 
   2231 #  define XOR3(_cc,_dd,_ee) \
   2232       binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
   2233 
   2234 #  define AND3(_ff,_gg,_hh) \
   2235       binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
   2236 
   2237 #define NOT(_jj) \
   2238       unop(Iop_Not64, (_jj))
   2239 
   2240    switch (op) {
   2241    case /* 0  */ PPCG_FLAG_OP_ADD:
   2242    case /* 1  */ PPCG_FLAG_OP_ADDE:
   2243       /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
   2244       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   2245       xer_ov
   2246          = AND3( XOR3(argL,argR,mkU64(-1)),
   2247                  XOR2(argL,res),
   2248                  mkU64(INT64_MIN) );
   2249       /* xer_ov can only be 0 or 1<<63 */
   2250       xer_ov
   2251          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   2252       break;
   2253 
   2254    case /* 2  */ PPCG_FLAG_OP_DIVW:
   2255       /* (argL == INT64_MIN && argR == -1) || argR == 0 */
   2256       xer_ov
   2257          = mkOR1(
   2258               mkAND1(
   2259                  binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
   2260                  binop(Iop_CmpEQ64, argR, mkU64(-1))
   2261               ),
   2262               binop(Iop_CmpEQ64, argR, mkU64(0) )
   2263            );
   2264       break;
   2265 
   2266    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   2267       /* argR == 0 */
   2268       xer_ov
   2269          = binop(Iop_CmpEQ64, argR, mkU64(0));
   2270       break;
   2271 
   2272    case /* 4  */ PPCG_FLAG_OP_MULLW: {
   2273       /* OV true if result can't be represented in 64 bits
   2274          i.e sHi != sign extension of sLo */
   2275       xer_ov
   2276          = binop( Iop_CmpNE32,
   2277                   unop(Iop_64HIto32, res),
   2278                   binop( Iop_Sar32,
   2279                          unop(Iop_64to32, res),
   2280                          mkU8(31))
   2281                   );
   2282       break;
   2283    }
   2284 
   2285    case /* 5  */ PPCG_FLAG_OP_NEG:
   2286       /* argL == INT64_MIN */
   2287       xer_ov
   2288          = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
   2289       break;
   2290 
   2291    case /* 6  */ PPCG_FLAG_OP_SUBF:
   2292    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   2293    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   2294       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
   2295       xer_ov
   2296          = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
   2297                  XOR2(NOT(argL),res),
   2298                  mkU64(INT64_MIN) );
   2299       /* xer_ov can only be 0 or 1<<63 */
   2300       xer_ov
   2301          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   2302       break;
   2303 
   2304    case PPCG_FLAG_OP_DIVDE:
   2305 
   2306       /* If argR == 0, we must set the OV bit.  But there's another condition
   2307        * where we can get overflow set for divde . . . when the
   2308        * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
   2309        * both dividend and divisor are non-zero, it implies an overflow.
   2310        */
   2311       xer_ov
   2312                   = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
   2313                            mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
   2314                                    mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
   2315                                            binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
   2316       break;
   2317 
   2318    case PPCG_FLAG_OP_DIVDEU:
   2319      /* If argR == 0 or if argL >= argR, set OV. */
   2320      xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
   2321                          binop( Iop_CmpLE64U, argR, argL ) );
   2322      break;
   2323 
   2324    case /* 18 */ PPCG_FLAG_OP_MULLD: {
   2325       IRTemp  t128;
   2326       /* OV true if result can't be represented in 64 bits
   2327          i.e sHi != sign extension of sLo */
   2328       t128 = newTemp(Ity_I128);
   2329       assign( t128, binop(Iop_MullS64, argL, argR) );
   2330       xer_ov
   2331          = binop( Iop_CmpNE64,
   2332                   unop(Iop_128HIto64, mkexpr(t128)),
   2333                   binop( Iop_Sar64,
   2334                          unop(Iop_128to64, mkexpr(t128)),
   2335                          mkU8(63))
   2336                   );
   2337       break;
   2338    }
   2339 
   2340    default:
   2341       vex_printf("set_XER_OV: op = %u\n", op);
   2342       vpanic("set_XER_OV(ppc64)");
   2343    }
   2344 
   2345    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   2346    putXER_OV( unop(Iop_1Uto8, xer_ov) );
   2347 
   2348    /* Update the summary overflow */
   2349    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   2350 
   2351 #  undef INT64_MIN
   2352 #  undef AND3
   2353 #  undef XOR3
   2354 #  undef XOR2
   2355 #  undef NOT
   2356 }
   2357 
   2358 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
   2359                          IRExpr* argL, IRExpr* argR )
   2360 {
   2361    if (ty == Ity_I32)
   2362       set_XER_OV_32( op, res, argL, argR );
   2363    else
   2364       set_XER_OV_64( op, res, argL, argR );
   2365 }
   2366 
   2367 
   2368 
   2369 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
   2370    value being OLDCA.  Set %XER.CA accordingly. */
   2371 
   2372 static void set_XER_CA_32 ( UInt op, IRExpr* res,
   2373                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2374 {
   2375    IRExpr* xer_ca;
   2376    vassert(op < PPCG_FLAG_OP_NUMBER);
   2377    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
   2378    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
   2379    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
   2380    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
   2381 
   2382    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   2383       seems reasonable given that it's always generated by
   2384       getXER_CA32(), which masks it accordingly.  In any case it being
   2385       0 or 1 is an invariant of the ppc guest state representation;
   2386       if it has any other value, that invariant has been violated. */
   2387 
   2388    switch (op) {
   2389    case /* 0 */ PPCG_FLAG_OP_ADD:
   2390       /* res <u argL */
   2391       xer_ca
   2392          = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
   2393       break;
   2394 
   2395    case /* 1 */ PPCG_FLAG_OP_ADDE:
   2396       /* res <u argL || (old_ca==1 && res==argL) */
   2397       xer_ca
   2398          = mkOR1(
   2399               binop(Iop_CmpLT32U, res, argL),
   2400               mkAND1(
   2401                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   2402                  binop(Iop_CmpEQ32, res, argL)
   2403               )
   2404            );
   2405       xer_ca
   2406          = unop(Iop_1Uto32, xer_ca);
   2407       break;
   2408 
   2409    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   2410       /* res <u argR || (old_ca==1 && res==argR) */
   2411       xer_ca
   2412          = mkOR1(
   2413               binop(Iop_CmpLT32U, res, argR),
   2414               mkAND1(
   2415                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   2416                  binop(Iop_CmpEQ32, res, argR)
   2417               )
   2418            );
   2419       xer_ca
   2420          = unop(Iop_1Uto32, xer_ca);
   2421       break;
   2422 
   2423    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   2424    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   2425       /* res <=u argR */
   2426       xer_ca
   2427          = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
   2428       break;
   2429 
   2430    case /* 10 */ PPCG_FLAG_OP_SRAW:
   2431       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   2432          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   2433          bit of argL. */
   2434       /* This term valid for shift amount < 32 only */
   2435       xer_ca
   2436          = binop(
   2437               Iop_And32,
   2438               binop(Iop_Sar32, argL, mkU8(31)),
   2439               binop( Iop_And32,
   2440                      argL,
   2441                      binop( Iop_Sub32,
   2442                             binop(Iop_Shl32, mkU32(1),
   2443                                              unop(Iop_32to8,argR)),
   2444                             mkU32(1) )
   2445                      )
   2446               );
   2447       xer_ca
   2448          = IRExpr_ITE(
   2449               /* shift amt > 31 ? */
   2450               binop(Iop_CmpLT32U, mkU32(31), argR),
   2451               /* yes -- get sign bit of argL */
   2452               binop(Iop_Shr32, argL, mkU8(31)),
   2453               /* no -- be like srawi */
   2454               unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)))
   2455            );
   2456       break;
   2457 
   2458    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   2459       /* xer_ca is 1 iff src was negative and bits_shifted_out !=
   2460          0.  Since the shift amount is known to be in the range
   2461          0 .. 31 inclusive the following seems viable:
   2462          xer.ca == 1 iff the following is nonzero:
   2463          (argL >>s 31)           -- either all 0s or all 1s
   2464          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2465       xer_ca
   2466          = binop(
   2467               Iop_And32,
   2468               binop(Iop_Sar32, argL, mkU8(31)),
   2469               binop( Iop_And32,
   2470                      argL,
   2471                      binop( Iop_Sub32,
   2472                             binop(Iop_Shl32, mkU32(1),
   2473                                              unop(Iop_32to8,argR)),
   2474                             mkU32(1) )
   2475                      )
   2476               );
   2477       xer_ca
   2478          = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
   2479       break;
   2480 
   2481    default:
   2482       vex_printf("set_XER_CA: op = %u\n", op);
   2483       vpanic("set_XER_CA(ppc)");
   2484    }
   2485 
   2486    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   2487    putXER_CA( unop(Iop_32to8, xer_ca) );
   2488 }
   2489 
   2490 static void set_XER_CA_64 ( UInt op, IRExpr* res,
   2491                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2492 {
   2493    IRExpr* xer_ca;
   2494    vassert(op < PPCG_FLAG_OP_NUMBER);
   2495    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
   2496    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
   2497    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
   2498    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
   2499 
   2500    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   2501       seems reasonable given that it's always generated by
   2502       getXER_CA32(), which masks it accordingly.  In any case it being
   2503       0 or 1 is an invariant of the ppc guest state representation;
   2504       if it has any other value, that invariant has been violated. */
   2505 
   2506    switch (op) {
   2507    case /* 0 */ PPCG_FLAG_OP_ADD:
   2508       /* res <u argL */
   2509       xer_ca
   2510          = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
   2511       break;
   2512 
   2513    case /* 1 */ PPCG_FLAG_OP_ADDE:
   2514       /* res <u argL || (old_ca==1 && res==argL) */
   2515       xer_ca
   2516          = mkOR1(
   2517               binop(Iop_CmpLT64U, res, argL),
   2518               mkAND1(
   2519                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   2520                  binop(Iop_CmpEQ64, res, argL)
   2521                  )
   2522               );
   2523       xer_ca
   2524          = unop(Iop_1Uto32, xer_ca);
   2525       break;
   2526 
   2527    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   2528       /* res <u argR || (old_ca==1 && res==argR) */
   2529       xer_ca
   2530          = mkOR1(
   2531               binop(Iop_CmpLT64U, res, argR),
   2532               mkAND1(
   2533                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   2534                  binop(Iop_CmpEQ64, res, argR)
   2535               )
   2536            );
   2537       xer_ca
   2538          = unop(Iop_1Uto32, xer_ca);
   2539       break;
   2540 
   2541    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   2542    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   2543       /* res <=u argR */
   2544       xer_ca
   2545          = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
   2546       break;
   2547 
   2548 
   2549    case /* 10 */ PPCG_FLAG_OP_SRAW:
   2550       /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
   2551          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   2552          bit of argL. */
   2553          /* This term valid for shift amount < 31 only */
   2554 
   2555       xer_ca
   2556          = binop(
   2557               Iop_And64,
   2558               binop(Iop_Sar64, argL, mkU8(31)),
   2559               binop( Iop_And64,
   2560                      argL,
   2561                      binop( Iop_Sub64,
   2562                             binop(Iop_Shl64, mkU64(1),
   2563                                              unop(Iop_64to8,argR)),
   2564                             mkU64(1) )
   2565               )
   2566            );
   2567       xer_ca
   2568          = IRExpr_ITE(
   2569               /* shift amt > 31 ? */
   2570               binop(Iop_CmpLT64U, mkU64(31), argR),
   2571               /* yes -- get sign bit of argL */
   2572               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
   2573               /* no -- be like srawi */
   2574               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
   2575           );
   2576       break;
   2577 
   2578    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   2579       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   2580          Since the shift amount is known to be in the range 0 .. 31
   2581          inclusive the following seems viable:
   2582          xer.ca == 1 iff the following is nonzero:
   2583          (argL >>s 31)           -- either all 0s or all 1s
   2584          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2585 
   2586       xer_ca
   2587          = binop(
   2588               Iop_And64,
   2589               binop(Iop_Sar64, argL, mkU8(31)),
   2590               binop( Iop_And64,
   2591                      argL,
   2592                      binop( Iop_Sub64,
   2593                             binop(Iop_Shl64, mkU64(1),
   2594                                              unop(Iop_64to8,argR)),
   2595                             mkU64(1) )
   2596               )
   2597            );
   2598       xer_ca
   2599          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   2600       break;
   2601 
   2602 
   2603    case /* 12 */ PPCG_FLAG_OP_SRAD:
   2604       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   2605          If it is <= 63, behave like SRADI; else XER.CA is the sign
   2606          bit of argL. */
   2607          /* This term valid for shift amount < 63 only */
   2608 
   2609       xer_ca
   2610          = binop(
   2611               Iop_And64,
   2612               binop(Iop_Sar64, argL, mkU8(63)),
   2613               binop( Iop_And64,
   2614                      argL,
   2615                      binop( Iop_Sub64,
   2616                             binop(Iop_Shl64, mkU64(1),
   2617                                              unop(Iop_64to8,argR)),
   2618                             mkU64(1) )
   2619               )
   2620            );
   2621       xer_ca
   2622          = IRExpr_ITE(
   2623               /* shift amt > 63 ? */
   2624               binop(Iop_CmpLT64U, mkU64(63), argR),
   2625               /* yes -- get sign bit of argL */
   2626               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
   2627               /* no -- be like sradi */
   2628               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
   2629            );
   2630       break;
   2631 
   2632 
   2633    case /* 13 */ PPCG_FLAG_OP_SRADI:
   2634       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   2635          Since the shift amount is known to be in the range 0 .. 63
   2636          inclusive, the following seems viable:
   2637          xer.ca == 1 iff the following is nonzero:
   2638          (argL >>s 63)           -- either all 0s or all 1s
   2639          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2640 
   2641       xer_ca
   2642          = binop(
   2643               Iop_And64,
   2644               binop(Iop_Sar64, argL, mkU8(63)),
   2645               binop( Iop_And64,
   2646                      argL,
   2647                      binop( Iop_Sub64,
   2648                             binop(Iop_Shl64, mkU64(1),
   2649                                              unop(Iop_64to8,argR)),
   2650                             mkU64(1) )
   2651               )
   2652            );
   2653       xer_ca
   2654          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   2655       break;
   2656 
   2657    default:
   2658       vex_printf("set_XER_CA: op = %u\n", op);
   2659       vpanic("set_XER_CA(ppc64)");
   2660    }
   2661 
   2662    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   2663    putXER_CA( unop(Iop_32to8, xer_ca) );
   2664 }
   2665 
   2666 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
   2667                          IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2668 {
   2669    if (ty == Ity_I32)
   2670       set_XER_CA_32( op, res, argL, argR, oldca );
   2671    else
   2672       set_XER_CA_64( op, res, argL, argR, oldca );
   2673 }
   2674 
   2675 
   2676 
   2677 /*------------------------------------------------------------*/
   2678 /*--- Read/write to guest-state                           --- */
   2679 /*------------------------------------------------------------*/
   2680 
   2681 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
   2682 {
   2683    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2684    switch (reg) {
   2685    case PPC_GST_SPRG3_RO:
   2686       return IRExpr_Get( OFFB_SPRG3_RO, ty );
   2687 
   2688    case PPC_GST_CIA:
   2689       return IRExpr_Get( OFFB_CIA, ty );
   2690 
   2691    case PPC_GST_LR:
   2692       return IRExpr_Get( OFFB_LR, ty );
   2693 
   2694    case PPC_GST_CTR:
   2695       return IRExpr_Get( OFFB_CTR, ty );
   2696 
   2697    case PPC_GST_VRSAVE:
   2698       return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
   2699 
   2700    case PPC_GST_VSCR:
   2701       return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
   2702                               mkU32(MASK_VSCR_VALID));
   2703 
   2704    case PPC_GST_CR: {
   2705       /* Synthesise the entire CR into a single word.  Expensive. */
   2706 #     define FIELD(_n)                                               \
   2707          binop(Iop_Shl32,                                            \
   2708                unop(Iop_8Uto32,                                      \
   2709                     binop(Iop_Or8,                                   \
   2710                           binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
   2711                           binop(Iop_And8, getCR0(_n), mkU8(1))       \
   2712                     )                                                \
   2713                ),                                                    \
   2714                mkU8(4 * (7-(_n)))                                    \
   2715          )
   2716       return binop(Iop_Or32,
   2717                    binop(Iop_Or32,
   2718                          binop(Iop_Or32, FIELD(0), FIELD(1)),
   2719                          binop(Iop_Or32, FIELD(2), FIELD(3))
   2720                          ),
   2721                    binop(Iop_Or32,
   2722                          binop(Iop_Or32, FIELD(4), FIELD(5)),
   2723                          binop(Iop_Or32, FIELD(6), FIELD(7))
   2724                          )
   2725                    );
   2726 #     undef FIELD
   2727    }
   2728 
   2729    case PPC_GST_XER:
   2730       return binop(Iop_Or32,
   2731                    binop(Iop_Or32,
   2732                          binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
   2733                          binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
   2734                    binop(Iop_Or32,
   2735                          binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
   2736                          getXER_BC32()));
   2737 
   2738    case PPC_GST_TFHAR:
   2739       return IRExpr_Get( OFFB_TFHAR, ty );
   2740 
   2741    case PPC_GST_TEXASR:
   2742       return IRExpr_Get( OFFB_TEXASR, ty );
   2743 
   2744    case PPC_GST_TEXASRU:
   2745       return IRExpr_Get( OFFB_TEXASRU, ty );
   2746 
   2747    case PPC_GST_TFIAR:
   2748       return IRExpr_Get( OFFB_TFIAR, ty );
   2749 
   2750    default:
   2751       vex_printf("getGST(ppc): reg = %u", reg);
   2752       vpanic("getGST(ppc)");
   2753    }
   2754 }
   2755 
   2756 /* Get a masked word from the given reg */
   2757 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
   2758 {
   2759    IRTemp val = newTemp(Ity_I32);
   2760    vassert( reg < PPC_GST_MAX );
   2761 
   2762    switch (reg) {
   2763 
   2764    case PPC_GST_FPSCR: {
   2765       /* Vex-generated code expects the FPSCR to be set as follows:
   2766          all exceptions masked, round-to-nearest.
   2767          This corresponds to a FPSCR value of 0x0. */
   2768 
   2769       /* In the lower 32 bits of FPSCR, we're only keeping track of
   2770        * the binary floating point rounding mode, so if the mask isn't
   2771        * asking for this, just return 0x0.
   2772        */
   2773       if (mask & MASK_FPSCR_RN) {
   2774          assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) );
   2775       } else {
   2776          assign( val, mkU32(0x0) );
   2777       }
   2778       break;
   2779    }
   2780 
   2781    default:
   2782       vex_printf("getGST_masked(ppc): reg = %u", reg);
   2783       vpanic("getGST_masked(ppc)");
   2784    }
   2785 
   2786    if (mask != 0xFFFFFFFF) {
   2787       return binop(Iop_And32, mkexpr(val), mkU32(mask));
   2788    } else {
   2789       return mkexpr(val);
   2790    }
   2791 }
   2792 
   2793 /* Get a masked word from the given reg */
   2794 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
   2795    IRExpr * val;
   2796    vassert( reg < PPC_GST_MAX );
   2797 
   2798    switch (reg) {
   2799 
   2800    case PPC_GST_FPSCR: {
   2801       /* In the upper 32 bits of FPSCR, we're only keeping track
   2802        * of the decimal floating point rounding mode, so if the mask
   2803        * isn't asking for this, just return 0x0.
   2804        */
   2805       if (mask & MASK_FPSCR_DRN) {
   2806          val = binop( Iop_And32,
   2807                       unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
   2808                       unop( Iop_64HIto32, mkU64( mask ) ) );
   2809       } else {
   2810          val = mkU32( 0x0ULL );
   2811       }
   2812       break;
   2813    }
   2814 
   2815    default:
   2816       vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
   2817       vpanic( "getGST_masked_upper(ppc)" );
   2818    }
   2819    return val;
   2820 }
   2821 
   2822 
   2823 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
   2824    and return it at the bottom of an I32; the top 27 bits are
   2825    guaranteed to be zero. */
   2826 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
   2827 {
   2828    UInt shft, mask;
   2829 
   2830    vassert( fld < 8 );
   2831    vassert( reg < PPC_GST_MAX );
   2832 
   2833    shft = 4*(7-fld);
   2834    mask = 0xF<<shft;
   2835 
   2836    switch (reg) {
   2837    case PPC_GST_XER:
   2838       vassert(fld ==7);
   2839       return binop(Iop_Or32,
   2840                    binop(Iop_Or32,
   2841                          binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
   2842                          binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
   2843                    binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
   2844       break;
   2845 
   2846    default:
   2847       if (shft == 0)
   2848          return getGST_masked( reg, mask );
   2849       else
   2850          return binop(Iop_Shr32,
   2851                       getGST_masked( reg, mask ),
   2852                       mkU8(toUChar( shft )));
   2853    }
   2854 }
   2855 
   2856 static void putGST ( PPC_GST reg, IRExpr* src )
   2857 {
   2858    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   2859    IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
   2860    vassert( reg < PPC_GST_MAX );
   2861    switch (reg) {
   2862    case PPC_GST_IP_AT_SYSCALL:
   2863       vassert( ty_src == ty );
   2864       stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
   2865       break;
   2866    case PPC_GST_CIA:
   2867       vassert( ty_src == ty );
   2868       stmt( IRStmt_Put( OFFB_CIA, src ) );
   2869       break;
   2870    case PPC_GST_LR:
   2871       vassert( ty_src == ty );
   2872       stmt( IRStmt_Put( OFFB_LR, src ) );
   2873       break;
   2874    case PPC_GST_CTR:
   2875       vassert( ty_src == ty );
   2876       stmt( IRStmt_Put( OFFB_CTR, src ) );
   2877       break;
   2878    case PPC_GST_VRSAVE:
   2879       vassert( ty_src == Ity_I32 );
   2880       stmt( IRStmt_Put( OFFB_VRSAVE,src));
   2881       break;
   2882    case PPC_GST_VSCR:
   2883       vassert( ty_src == Ity_I32 );
   2884       stmt( IRStmt_Put( OFFB_VSCR,
   2885                         binop(Iop_And32, src,
   2886                               mkU32(MASK_VSCR_VALID)) ) );
   2887       break;
   2888    case PPC_GST_XER:
   2889       vassert( ty_src == Ity_I32 );
   2890       putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
   2891       putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
   2892       putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
   2893       putXER_BC( unop(Iop_32to8, src) );
   2894       break;
   2895 
   2896    case PPC_GST_EMWARN:
   2897       vassert( ty_src == Ity_I32 );
   2898       stmt( IRStmt_Put( OFFB_EMNOTE,src) );
   2899       break;
   2900 
   2901    case PPC_GST_CMSTART:
   2902       vassert( ty_src == ty );
   2903       stmt( IRStmt_Put( OFFB_CMSTART, src) );
   2904       break;
   2905 
   2906    case PPC_GST_CMLEN:
   2907       vassert( ty_src == ty );
   2908       stmt( IRStmt_Put( OFFB_CMLEN, src) );
   2909       break;
   2910 
   2911    case PPC_GST_TEXASR:
   2912       vassert( ty_src == Ity_I64 );
   2913       stmt( IRStmt_Put( OFFB_TEXASR, src ) );
   2914       break;
   2915 
   2916    case PPC_GST_TEXASRU:
   2917       vassert( ty_src == Ity_I32 );
   2918       stmt( IRStmt_Put( OFFB_TEXASRU, src ) );
   2919       break;
   2920 
   2921    case PPC_GST_TFIAR:
   2922       vassert( ty_src == Ity_I64 );
   2923       stmt( IRStmt_Put( OFFB_TFIAR, src ) );
   2924       break;
   2925    case PPC_GST_TFHAR:
   2926       vassert( ty_src == Ity_I64 );
   2927       stmt( IRStmt_Put( OFFB_TFHAR, src ) );
   2928       break;
   2929    default:
   2930       vex_printf("putGST(ppc): reg = %u", reg);
   2931       vpanic("putGST(ppc)");
   2932    }
   2933 }
   2934 
   2935 /* Write masked src to the given reg */
   2936 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
   2937 {
   2938    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2939    vassert( reg < PPC_GST_MAX );
   2940    vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
   2941 
   2942    switch (reg) {
   2943    case PPC_GST_FPSCR: {
   2944       /* Allow writes to either binary or decimal floating point
   2945          Rounding Mode.
   2946       */
   2947       /* If any part of |mask| covers FPSCR.RN, update the bits of
   2948          FPSCR.RN by copying in |src| for locations where the
   2949          corresponding bit in |mask| is 1, and leaving it unchanged
   2950          for corresponding |mask| zero bits. */
   2951       if (mask & MASK_FPSCR_RN) {
   2952          stmt(
   2953             IRStmt_Put(
   2954                OFFB_FPROUND,
   2955                unop(
   2956                   Iop_32to8,
   2957                   binop(
   2958                      Iop_Or32,
   2959                      binop(
   2960                         Iop_And32,
   2961                         unop(Iop_64to32, src),
   2962                         mkU32(MASK_FPSCR_RN & mask)
   2963                      ),
   2964                      binop(
   2965                         Iop_And32,
   2966                         unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)),
   2967                         mkU32(MASK_FPSCR_RN & ~mask)
   2968                      )
   2969                   )
   2970                )
   2971             )
   2972          );
   2973       }
   2974       /* Similarly, update FPSCR.DRN if any bits of |mask|
   2975          corresponding to FPSCR.DRN are set. */
   2976       if (mask & MASK_FPSCR_DRN) {
   2977          stmt(
   2978             IRStmt_Put(
   2979                OFFB_DFPROUND,
   2980                unop(
   2981                   Iop_32to8,
   2982                   binop(
   2983                      Iop_Or32,
   2984                      binop(
   2985                         Iop_And32,
   2986                         unop(Iop_64HIto32, src),
   2987                         mkU32((MASK_FPSCR_DRN & mask) >> 32)
   2988                      ),
   2989                      binop(
   2990                         Iop_And32,
   2991                         unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)),
   2992                         mkU32((MASK_FPSCR_DRN & ~mask) >> 32)
   2993                      )
   2994                   )
   2995                )
   2996             )
   2997          );
   2998       }
   2999 
   3000       /* Give EmNote for attempted writes to:
   3001          - Exception Controls
   3002          - Non-IEEE Mode
   3003       */
   3004       if (mask & 0xFC) {  // Exception Control, Non-IEE mode
   3005          VexEmNote ew = EmWarn_PPCexns;
   3006 
   3007          /* If any of the src::exception_control bits are actually set,
   3008             side-exit to the next insn, reporting the warning,
   3009             so that Valgrind's dispatcher sees the warning. */
   3010          putGST( PPC_GST_EMWARN, mkU32(ew) );
   3011          stmt(
   3012             IRStmt_Exit(
   3013                binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
   3014                Ijk_EmWarn,
   3015                mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
   3016       }
   3017 
   3018       /* Ignore all other writes */
   3019       break;
   3020    }
   3021 
   3022    default:
   3023       vex_printf("putGST_masked(ppc): reg = %u", reg);
   3024       vpanic("putGST_masked(ppc)");
   3025    }
   3026 }
   3027 
   3028 /* Write the least significant nibble of src to the specified
   3029    REG[FLD] (as per IBM/hardware notation). */
   3030 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
   3031 {
   3032    UInt shft;
   3033    ULong mask;
   3034 
   3035    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
   3036    vassert( fld < 16 );
   3037    vassert( reg < PPC_GST_MAX );
   3038 
   3039    if (fld < 8)
   3040       shft = 4*(7-fld);
   3041    else
   3042       shft = 4*(15-fld);
   3043    mask = 0xF;
   3044    mask = mask << shft;
   3045 
   3046    switch (reg) {
   3047    case PPC_GST_CR:
   3048       putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
   3049       putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
   3050       break;
   3051 
   3052    default:
   3053       {
   3054          IRExpr * src64 = unop( Iop_32Uto64, src );
   3055 
   3056          if (shft == 0) {
   3057             putGST_masked( reg, src64, mask );
   3058          } else {
   3059             putGST_masked( reg,
   3060                            binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
   3061                            mask );
   3062          }
   3063       }
   3064    }
   3065 }
   3066 
   3067 /*------------------------------------------------------------*/
   3068 /* Helpers for VSX instructions that do floating point
   3069  * operations and need to determine if a src contains a
   3070  * special FP value.
   3071  *
   3072  *------------------------------------------------------------*/
   3073 
   3074 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
   3075 #define FP_FRAC_PART(x) binop( Iop_And64, \
   3076                                mkexpr( x ), \
   3077                                mkU64( NONZERO_FRAC_MASK ) )
   3078 
   3079 // Returns exponent part of a single precision floating point as I32
   3080 static IRExpr * fp_exp_part_sp(IRTemp src)
   3081 {
   3082    return binop( Iop_And32,
   3083                  binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
   3084                  mkU32( 0xff ) );
   3085 }
   3086 
   3087 // Returns exponent part of floating point as I32
   3088 static IRExpr * fp_exp_part(IRTemp src, Bool sp)
   3089 {
   3090    IRExpr * exp;
   3091    if (sp)
   3092       return fp_exp_part_sp(src);
   3093 
   3094    if (!mode64)
   3095       exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
   3096                                                       mkexpr( src ) ),
   3097                                      mkU8( 20 ) ), mkU32( 0x7ff ) );
   3098    else
   3099       exp = unop( Iop_64to32,
   3100                   binop( Iop_And64,
   3101                          binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
   3102                          mkU64( 0x7ff ) ) );
   3103    return exp;
   3104 }
   3105 
   3106 static IRExpr * is_Inf_sp(IRTemp src)
   3107 {
   3108    IRTemp frac_part = newTemp(Ity_I32);
   3109    IRExpr * Inf_exp;
   3110 
   3111    assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
   3112    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
   3113    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
   3114 }
   3115 
   3116 
   3117 // Infinity: exp = 7ff and fraction is zero; s = 0/1
   3118 static IRExpr * is_Inf(IRTemp src, Bool sp)
   3119 {
   3120    IRExpr * Inf_exp, * hi32, * low32;
   3121    IRTemp frac_part;
   3122 
   3123    if (sp)
   3124       return is_Inf_sp(src);
   3125 
   3126    frac_part = newTemp(Ity_I64);
   3127    assign( frac_part, FP_FRAC_PART(src) );
   3128    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
   3129    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   3130    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   3131    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
   3132                                   mkU32( 0 ) ) );
   3133 }
   3134 
   3135 static IRExpr * is_Zero_sp(IRTemp src)
   3136 {
   3137    IRTemp sign_less_part = newTemp(Ity_I32);
   3138    assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
   3139    return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
   3140 }
   3141 
   3142 // Zero: exp is zero and fraction is zero; s = 0/1
   3143 static IRExpr * is_Zero(IRTemp src, Bool sp)
   3144 {
   3145    IRExpr * hi32, * low32;
   3146    IRTemp sign_less_part;
   3147    if (sp)
   3148       return is_Zero_sp(src);
   3149 
   3150    sign_less_part = newTemp(Ity_I64);
   3151 
   3152    assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
   3153    hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
   3154    low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
   3155    return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
   3156                               mkU32( 0 ) );
   3157 }
   3158 
   3159 /*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
   3160  *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
   3161  *  This function returns an IRExpr value of '1' for any type of NaN.
   3162  */
   3163 static IRExpr * is_NaN(IRTemp src)
   3164 {
   3165    IRExpr * NaN_exp, * hi32, * low32;
   3166    IRTemp frac_part = newTemp(Ity_I64);
   3167 
   3168    assign( frac_part, FP_FRAC_PART(src) );
   3169    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   3170    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   3171    NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
   3172                     mkU32( 0x7ff ) );
   3173 
   3174    return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   3175                                                mkU32( 0 ) ) );
   3176 }
   3177 
   3178 /* This function returns an IRExpr value of '1' for any type of NaN.
   3179  * The passed 'src' argument is assumed to be Ity_I32.
   3180  */
   3181 static IRExpr * is_NaN_32(IRTemp src)
   3182 {
   3183 #define NONZERO_FRAC_MASK32 0x007fffffULL
   3184 #define FP_FRAC_PART32(x) binop( Iop_And32, \
   3185                                  mkexpr( x ), \
   3186                                  mkU32( NONZERO_FRAC_MASK32 ) )
   3187 
   3188    IRExpr * frac_part = FP_FRAC_PART32(src);
   3189    IRExpr * exp_part = binop( Iop_And32,
   3190                               binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
   3191                               mkU32( 0x0ff ) );
   3192    IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
   3193 
   3194    return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
   3195 }
   3196 
   3197 /* This function takes an Ity_I32 input argument interpreted
   3198  * as a single-precision floating point value. If src is a
   3199  * SNaN, it is changed to a QNaN and returned; otherwise,
   3200  * the original value is returned.
   3201  */
   3202 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src)
   3203 {
   3204 #define SNAN_MASK32 0x00400000
   3205    IRTemp tmp = newTemp(Ity_I32);
   3206    IRTemp mask = newTemp(Ity_I32);
   3207    IRTemp is_SNAN = newTemp(Ity_I1);
   3208 
   3209    vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 );
   3210    assign(tmp, src);
   3211 
   3212    /* check if input is SNaN, if it is convert to QNaN */
   3213    assign( is_SNAN,
   3214            mkAND1( is_NaN_32( tmp ),
   3215                    binop( Iop_CmpEQ32,
   3216                           binop( Iop_And32, mkexpr( tmp ),
   3217                                  mkU32( SNAN_MASK32 ) ),
   3218                           mkU32( 0 ) ) ) );
   3219    /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
   3220    assign ( mask, binop( Iop_And32,
   3221                          unop( Iop_1Sto32, mkexpr( is_SNAN ) ),
   3222                          mkU32( SNAN_MASK32 ) ) );
   3223    return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) );
   3224 }
   3225 
   3226 
   3227 /* This helper function performs the negation part of operations of the form:
   3228  *    "Negate Multiply-<op>"
   3229  *  where "<op>" is either "Add" or "Sub".
   3230  *
   3231  * This function takes one argument -- the floating point intermediate result (converted to
   3232  * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
   3233  * the operation described above.
   3234  */
   3235 static IRTemp getNegatedResult(IRTemp intermediateResult)
   3236 {
   3237    ULong signbit_mask = 0x8000000000000000ULL;
   3238    IRTemp signbit_32 = newTemp(Ity_I32);
   3239    IRTemp resultantSignbit = newTemp(Ity_I1);
   3240    IRTemp negatedResult = newTemp(Ity_I64);
   3241    assign( signbit_32, binop( Iop_Shr32,
   3242                           unop( Iop_64HIto32,
   3243                                  binop( Iop_And64, mkexpr( intermediateResult ),
   3244                                         mkU64( signbit_mask ) ) ),
   3245                                  mkU8( 31 ) ) );
   3246    /* We negate the signbit if and only if the intermediate result from the
   3247     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
   3248     */
   3249    assign( resultantSignbit,
   3250         unop( Iop_Not1,
   3251               binop( Iop_CmpEQ32,
   3252                      binop( Iop_Xor32,
   3253                             mkexpr( signbit_32 ),
   3254                             unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
   3255                      mkU32( 1 ) ) ) );
   3256 
   3257    assign( negatedResult,
   3258         binop( Iop_Or64,
   3259                binop( Iop_And64,
   3260                       mkexpr( intermediateResult ),
   3261                       mkU64( ~signbit_mask ) ),
   3262                binop( Iop_32HLto64,
   3263                       binop( Iop_Shl32,
   3264                              unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
   3265                              mkU8( 31 ) ),
   3266                       mkU32( 0 ) ) ) );
   3267 
   3268    return negatedResult;
   3269 }
   3270 
   3271 /* This helper function performs the negation part of operations of the form:
   3272  *    "Negate Multiply-<op>"
   3273  *  where "<op>" is either "Add" or "Sub".
   3274  *
   3275  * This function takes one argument -- the floating point intermediate result (converted to
   3276  * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
   3277  * the operation described above.
   3278  */
   3279 static IRTemp getNegatedResult_32(IRTemp intermediateResult)
   3280 {
   3281    UInt signbit_mask = 0x80000000;
   3282    IRTemp signbit_32 = newTemp(Ity_I32);
   3283    IRTemp resultantSignbit = newTemp(Ity_I1);
   3284    IRTemp negatedResult = newTemp(Ity_I32);
   3285    assign( signbit_32, binop( Iop_Shr32,
   3286                                  binop( Iop_And32, mkexpr( intermediateResult ),
   3287                                         mkU32( signbit_mask ) ),
   3288                                  mkU8( 31 ) ) );
   3289    /* We negate the signbit if and only if the intermediate result from the
   3290     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
   3291     */
   3292    assign( resultantSignbit,
   3293         unop( Iop_Not1,
   3294               binop( Iop_CmpEQ32,
   3295                      binop( Iop_Xor32,
   3296                             mkexpr( signbit_32 ),
   3297                             unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
   3298                      mkU32( 1 ) ) ) );
   3299 
   3300    assign( negatedResult,
   3301            binop( Iop_Or32,
   3302                   binop( Iop_And32,
   3303                          mkexpr( intermediateResult ),
   3304                          mkU32( ~signbit_mask ) ),
   3305                   binop( Iop_Shl32,
   3306                          unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
   3307                          mkU8( 31 ) ) ) );
   3308 
   3309    return negatedResult;
   3310 }
   3311 
   3312 /*------------------------------------------------------------*/
   3313 /* Transactional memory helpers
   3314  *
   3315  *------------------------------------------------------------*/
   3316 
   3317 static ULong generate_TMreason( UInt failure_code,
   3318                                              UInt persistant,
   3319                                              UInt nest_overflow,
   3320                                              UInt tm_exact )
   3321 {
   3322    ULong tm_err_code =
   3323      ( (ULong) 0) << (63-6)   /* Failure code */
   3324      | ( (ULong) persistant) << (63-7)     /* Failure persistant */
   3325      | ( (ULong) 0) << (63-8)   /* Disallowed */
   3326      | ( (ULong) nest_overflow) << (63-9)   /* Nesting Overflow */
   3327      | ( (ULong) 0) << (63-10)  /* Footprint Overflow */
   3328      | ( (ULong) 0) << (63-11)  /* Self-Induced Conflict */
   3329      | ( (ULong) 0) << (63-12)  /* Non-Transactional Conflict */
   3330      | ( (ULong) 0) << (63-13)  /* Transactional Conflict */
   3331      | ( (ULong) 0) << (63-14)  /* Translation Invalidation Conflict */
   3332      | ( (ULong) 0) << (63-15)  /* Implementation-specific */
   3333      | ( (ULong) 0) << (63-16)  /* Instruction Fetch Conflict */
   3334      | ( (ULong) 0) << (63-30)  /* Reserved */
   3335      | ( (ULong) 0) << (63-31)  /* Abort */
   3336      | ( (ULong) 0) << (63-32)  /* Suspend */
   3337      | ( (ULong) 0) << (63-33)  /* Reserved */
   3338      | ( (ULong) 0) << (63-35)  /* Privilege */
   3339      | ( (ULong) 0) << (63-36)  /* Failure Summary */
   3340      | ( (ULong) tm_exact) << (63-37)  /* TFIAR Exact */
   3341      | ( (ULong) 0) << (63-38)  /* ROT */
   3342      | ( (ULong) 0) << (63-51)  /* Reserved */
   3343      | ( (ULong) 0) << (63-63);  /* Transaction Level */
   3344 
   3345      return tm_err_code;
   3346 }
   3347 
   3348 static void storeTMfailure( Addr64 err_address, ULong tm_reason,
   3349                             Addr64 handler_address )
   3350 {
   3351    putGST( PPC_GST_TFIAR,   mkU64( err_address ) );
   3352    putGST( PPC_GST_TEXASR,  mkU64( tm_reason ) );
   3353    putGST( PPC_GST_TEXASRU, mkU32( 0 ) );
   3354    putGST( PPC_GST_TFHAR,   mkU64( handler_address ) );
   3355 }
   3356 
   3357 /*------------------------------------------------------------*/
   3358 /*--- Integer Instruction Translation                     --- */
   3359 /*------------------------------------------------------------*/
   3360 
   3361 /*
   3362   Integer Arithmetic Instructions
   3363 */
   3364 static Bool dis_int_arith ( UInt theInstr )
   3365 {
   3366    /* D-Form, XO-Form */
   3367    UChar opc1    = ifieldOPC(theInstr);
   3368    UChar rD_addr = ifieldRegDS(theInstr);
   3369    UChar rA_addr = ifieldRegA(theInstr);
   3370    UInt  uimm16  = ifieldUIMM16(theInstr);
   3371    UChar rB_addr = ifieldRegB(theInstr);
   3372    UChar flag_OE = ifieldBIT10(theInstr);
   3373    UInt  opc2    = ifieldOPClo9(theInstr);
   3374    UChar flag_rC = ifieldBIT0(theInstr);
   3375 
   3376    Long   simm16 = extend_s_16to64(uimm16);
   3377    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   3378    IRTemp rA     = newTemp(ty);
   3379    IRTemp rB     = newTemp(ty);
   3380    IRTemp rD     = newTemp(ty);
   3381 
   3382    Bool do_rc = False;
   3383 
   3384    assign( rA, getIReg(rA_addr) );
   3385    assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
   3386 
   3387    switch (opc1) {
   3388    /* D-Form */
   3389    case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
   3390       DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3391       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3392                          mkSzExtendS16(ty, uimm16) ) );
   3393       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3394                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3395                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3396       break;
   3397 
   3398    case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
   3399       DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3400       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3401                          mkSzExtendS16(ty, uimm16) ) );
   3402       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3403                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3404                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3405       do_rc = True;  // Always record to CR
   3406       flag_rC = 1;
   3407       break;
   3408 
   3409    case 0x0E: // addi   (Add Immediate, PPC32 p350)
   3410       // li rD,val   == addi rD,0,val
   3411       // la disp(rA) == addi rD,rA,disp
   3412       if ( rA_addr == 0 ) {
   3413          DIP("li r%u,%d\n", rD_addr, (Int)simm16);
   3414          assign( rD, mkSzExtendS16(ty, uimm16) );
   3415       } else {
   3416          DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3417          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3418                             mkSzExtendS16(ty, uimm16) ) );
   3419       }
   3420       break;
   3421 
   3422    case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
   3423       // lis rD,val == addis rD,0,val
   3424       if ( rA_addr == 0 ) {
   3425          DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
   3426          assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
   3427       } else {
   3428          DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
   3429          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3430                             mkSzExtendS32(ty, uimm16 << 16) ) );
   3431       }
   3432       break;
   3433 
   3434    case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
   3435       DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3436       if (mode64)
   3437          assign( rD, unop(Iop_128to64,
   3438                           binop(Iop_MullS64, mkexpr(rA),
   3439                                 mkSzExtendS16(ty, uimm16))) );
   3440       else
   3441          assign( rD, unop(Iop_64to32,
   3442                           binop(Iop_MullS32, mkexpr(rA),
   3443                                 mkSzExtendS16(ty, uimm16))) );
   3444       break;
   3445 
   3446    case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
   3447       DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3448       // rD = simm16 - rA
   3449       assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3450                          mkSzExtendS16(ty, uimm16),
   3451                          mkexpr(rA)) );
   3452       set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
   3453                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3454                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3455       break;
   3456 
   3457    /* XO-Form */
   3458    case 0x1F:
   3459       do_rc = True;    // All below record to CR
   3460 
   3461       switch (opc2) {
   3462       case 0x10A: // add  (Add, PPC32 p347)
   3463          DIP("add%s%s r%u,r%u,r%u\n",
   3464              flag_OE ? "o" : "", flag_rC ? ".":"",
   3465              rD_addr, rA_addr, rB_addr);
   3466          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3467                             mkexpr(rA), mkexpr(rB) ) );
   3468          if (flag_OE) {
   3469             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   3470                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3471          }
   3472          break;
   3473 
   3474       case 0x00A: // addc      (Add Carrying, PPC32 p348)
   3475          DIP("addc%s%s r%u,r%u,r%u\n",
   3476              flag_OE ? "o" : "", flag_rC ? ".":"",
   3477              rD_addr, rA_addr, rB_addr);
   3478          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3479                             mkexpr(rA), mkexpr(rB)) );
   3480          set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3481                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3482                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3483          if (flag_OE) {
   3484             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   3485                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3486          }
   3487          break;
   3488 
   3489       case 0x08A: { // adde      (Add Extended, PPC32 p349)
   3490          IRTemp old_xer_ca = newTemp(ty);
   3491          DIP("adde%s%s r%u,r%u,r%u\n",
   3492              flag_OE ? "o" : "", flag_rC ? ".":"",
   3493              rD_addr, rA_addr, rB_addr);
   3494          // rD = rA + rB + XER[CA]
   3495          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3496          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3497                             binop( mkSzOp(ty, Iop_Add8),
   3498                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   3499          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3500                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3501                      mkexpr(old_xer_ca) );
   3502          if (flag_OE) {
   3503             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3504                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3505          }
   3506          break;
   3507       }
   3508 
   3509       case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
   3510          IRTemp old_xer_ca = newTemp(ty);
   3511          IRExpr *min_one;
   3512          if (rB_addr != 0) {
   3513             vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
   3514             return False;
   3515          }
   3516          DIP("addme%s%s r%u,r%u,r%u\n",
   3517              flag_OE ? "o" : "", flag_rC ? ".":"",
   3518              rD_addr, rA_addr, rB_addr);
   3519          // rD = rA + (-1) + XER[CA]
   3520          // => Just another form of adde
   3521          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3522          min_one = mkSzImm(ty, (Long)-1);
   3523          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3524                             binop( mkSzOp(ty, Iop_Add8),
   3525                                    min_one, mkexpr(old_xer_ca)) ));
   3526          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3527                      mkexpr(rD), mkexpr(rA), min_one,
   3528                      mkexpr(old_xer_ca) );
   3529          if (flag_OE) {
   3530             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3531                         mkexpr(rD), mkexpr(rA), min_one );
   3532          }
   3533          break;
   3534       }
   3535 
   3536       case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
   3537          IRTemp old_xer_ca = newTemp(ty);
   3538          if (rB_addr != 0) {
   3539             vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
   3540             return False;
   3541          }
   3542          DIP("addze%s%s r%u,r%u,r%u\n",
   3543              flag_OE ? "o" : "", flag_rC ? ".":"",
   3544              rD_addr, rA_addr, rB_addr);
   3545          // rD = rA + (0) + XER[CA]
   3546          // => Just another form of adde
   3547          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3548          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3549                             mkexpr(rA), mkexpr(old_xer_ca)) );
   3550          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3551                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   3552                      mkexpr(old_xer_ca) );
   3553          if (flag_OE) {
   3554             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3555                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   3556          }
   3557          break;
   3558       }
   3559 
   3560       case 0x1EB: // divw       (Divide Word, PPC32 p388)
   3561          DIP("divw%s%s r%u,r%u,r%u\n",
   3562              flag_OE ? "o" : "", flag_rC ? ".":"",
   3563              rD_addr, rA_addr, rB_addr);
   3564          if (mode64) {
   3565             /* Note:
   3566                XER settings are mode independent, and reflect the
   3567                overflow of the low-order 32bit result
   3568                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   3569             */
   3570             /* rD[hi32] are undefined: setting them to sign of lo32
   3571                 - makes set_CR0 happy */
   3572             IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
   3573             IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
   3574             assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
   3575                                                          divisor) ) );
   3576             if (flag_OE) {
   3577                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3578                            mkexpr(rD), dividend, divisor );
   3579             }
   3580          } else {
   3581             assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
   3582             if (flag_OE) {
   3583                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3584                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3585             }
   3586          }
   3587          /* Note:
   3588             if (0x8000_0000 / -1) or (x / 0)
   3589             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   3590             => But _no_ exception raised. */
   3591          break;
   3592 
   3593       case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
   3594          DIP("divwu%s%s r%u,r%u,r%u\n",
   3595              flag_OE ? "o" : "", flag_rC ? ".":"",
   3596              rD_addr, rA_addr, rB_addr);
   3597          if (mode64) {
   3598             /* Note:
   3599                XER settings are mode independent, and reflect the
   3600                overflow of the low-order 32bit result
   3601                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   3602             */
   3603             IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
   3604             IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
   3605             assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
   3606                                                          divisor) ) );
   3607             if (flag_OE) {
   3608                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3609                            mkexpr(rD), dividend, divisor );
   3610             }
   3611          } else {
   3612             assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
   3613             if (flag_OE) {
   3614                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3615                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3616             }
   3617          }
   3618          /* Note: ditto comment divw, for (x / 0) */
   3619          break;
   3620 
   3621       case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
   3622          if (flag_OE != 0) {
   3623             vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
   3624             return False;
   3625          }
   3626          DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3627              rD_addr, rA_addr, rB_addr);
   3628          if (mode64) {
   3629             /* rD[hi32] are undefined: setting them to sign of lo32
   3630                 - makes set_CR0 happy */
   3631             assign( rD, binop(Iop_Sar64,
   3632                            binop(Iop_Mul64,
   3633                                  mk64lo32Sto64( mkexpr(rA) ),
   3634                                  mk64lo32Sto64( mkexpr(rB) )),
   3635                               mkU8(32)) );
   3636          } else {
   3637             assign( rD, unop(Iop_64HIto32,
   3638                              binop(Iop_MullS32,
   3639                                    mkexpr(rA), mkexpr(rB))) );
   3640          }
   3641          break;
   3642 
   3643       case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
   3644          if (flag_OE != 0) {
   3645             vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
   3646             return False;
   3647          }
   3648          DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3649              rD_addr, rA_addr, rB_addr);
   3650          if (mode64) {
   3651             /* rD[hi32] are undefined: setting them to sign of lo32
   3652                 - makes set_CR0 happy */
   3653             assign( rD, binop(Iop_Sar64,
   3654                            binop(Iop_Mul64,
   3655                                  mk64lo32Uto64( mkexpr(rA) ),
   3656                                  mk64lo32Uto64( mkexpr(rB) ) ),
   3657                               mkU8(32)) );
   3658          } else {
   3659             assign( rD, unop(Iop_64HIto32,
   3660                              binop(Iop_MullU32,
   3661                                    mkexpr(rA), mkexpr(rB))) );
   3662          }
   3663          break;
   3664 
   3665       case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
   3666          DIP("mullw%s%s r%u,r%u,r%u\n",
   3667              flag_OE ? "o" : "", flag_rC ? ".":"",
   3668              rD_addr, rA_addr, rB_addr);
   3669          if (mode64) {
   3670             /* rD[hi32] are undefined: setting them to sign of lo32
   3671                 - set_XER_OV() and set_CR0() depend on this */
   3672             IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
   3673             IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
   3674             assign( rD, binop(Iop_MullS32, a, b) );
   3675             if (flag_OE) {
   3676                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3677                            mkexpr(rD),
   3678                            unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
   3679             }
   3680          } else {
   3681             assign( rD, unop(Iop_64to32,
   3682                              binop(Iop_MullU32,
   3683                                    mkexpr(rA), mkexpr(rB))) );
   3684             if (flag_OE) {
   3685                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3686                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3687             }
   3688          }
   3689          break;
   3690 
   3691       case 0x068: // neg        (Negate, PPC32 p493)
   3692          if (rB_addr != 0) {
   3693             vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
   3694             return False;
   3695          }
   3696          DIP("neg%s%s r%u,r%u\n",
   3697              flag_OE ? "o" : "", flag_rC ? ".":"",
   3698              rD_addr, rA_addr);
   3699          // rD = (~rA) + 1
   3700          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3701                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
   3702                             mkSzImm(ty, 1)) );
   3703          if (flag_OE) {
   3704             set_XER_OV( ty, PPCG_FLAG_OP_NEG,
   3705                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3706          }
   3707          break;
   3708 
   3709       case 0x028: // subf       (Subtract From, PPC32 p537)
   3710          DIP("subf%s%s r%u,r%u,r%u\n",
   3711              flag_OE ? "o" : "", flag_rC ? ".":"",
   3712              rD_addr, rA_addr, rB_addr);
   3713          // rD = rB - rA
   3714          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3715                             mkexpr(rB), mkexpr(rA)) );
   3716          if (flag_OE) {
   3717             set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
   3718                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3719          }
   3720          break;
   3721 
   3722       case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
   3723          DIP("subfc%s%s r%u,r%u,r%u\n",
   3724              flag_OE ? "o" : "", flag_rC ? ".":"",
   3725              rD_addr, rA_addr, rB_addr);
   3726          // rD = rB - rA
   3727          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3728                             mkexpr(rB), mkexpr(rA)) );
   3729          set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
   3730                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3731                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3732          if (flag_OE) {
   3733             set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
   3734                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3735          }
   3736          break;
   3737 
   3738       case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
   3739          IRTemp old_xer_ca = newTemp(ty);
   3740          DIP("subfe%s%s r%u,r%u,r%u\n",
   3741              flag_OE ? "o" : "", flag_rC ? ".":"",
   3742              rD_addr, rA_addr, rB_addr);
   3743          // rD = (log not)rA + rB + XER[CA]
   3744          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3745          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3746                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   3747                             binop( mkSzOp(ty, Iop_Add8),
   3748                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   3749          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3750                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3751                      mkexpr(old_xer_ca) );
   3752          if (flag_OE) {
   3753             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3754                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3755          }
   3756          break;
   3757       }
   3758 
   3759       case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
   3760          IRTemp old_xer_ca = newTemp(ty);
   3761          IRExpr *min_one;
   3762          if (rB_addr != 0) {
   3763             vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
   3764             return False;
   3765          }
   3766          DIP("subfme%s%s r%u,r%u\n",
   3767              flag_OE ? "o" : "", flag_rC ? ".":"",
   3768              rD_addr, rA_addr);
   3769          // rD = (log not)rA + (-1) + XER[CA]
   3770          // => Just another form of subfe
   3771          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3772          min_one = mkSzImm(ty, (Long)-1);
   3773          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3774                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   3775                             binop( mkSzOp(ty, Iop_Add8),
   3776                                    min_one, mkexpr(old_xer_ca))) );
   3777          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3778                      mkexpr(rD), mkexpr(rA), min_one,
   3779                      mkexpr(old_xer_ca) );
   3780          if (flag_OE) {
   3781             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3782                         mkexpr(rD), mkexpr(rA), min_one );
   3783          }
   3784          break;
   3785       }
   3786 
   3787       case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
   3788          IRTemp old_xer_ca = newTemp(ty);
   3789          if (rB_addr != 0) {
   3790             vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
   3791             return False;
   3792          }
   3793          DIP("subfze%s%s r%u,r%u\n",
   3794              flag_OE ? "o" : "", flag_rC ? ".":"",
   3795              rD_addr, rA_addr);
   3796          // rD = (log not)rA + (0) + XER[CA]
   3797          // => Just another form of subfe
   3798          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3799          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3800                            unop( mkSzOp(ty, Iop_Not8),
   3801                                  mkexpr(rA)), mkexpr(old_xer_ca)) );
   3802          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3803                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   3804                      mkexpr(old_xer_ca) );
   3805          if (flag_OE) {
   3806             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3807                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   3808          }
   3809          break;
   3810       }
   3811 
   3812 
   3813       /* 64bit Arithmetic */
   3814       case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
   3815          if (flag_OE != 0) {
   3816             vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
   3817             return False;
   3818          }
   3819          DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3820              rD_addr, rA_addr, rB_addr);
   3821          assign( rD, unop(Iop_128HIto64,
   3822                           binop(Iop_MullS64,
   3823                                 mkexpr(rA), mkexpr(rB))) );
   3824 
   3825          break;
   3826 
   3827       case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
   3828          if (flag_OE != 0) {
   3829             vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
   3830             return False;
   3831          }
   3832          DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3833              rD_addr, rA_addr, rB_addr);
   3834          assign( rD, unop(Iop_128HIto64,
   3835                           binop(Iop_MullU64,
   3836                                 mkexpr(rA), mkexpr(rB))) );
   3837          break;
   3838 
   3839       case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
   3840          DIP("mulld%s%s r%u,r%u,r%u\n",
   3841              flag_OE ? "o" : "", flag_rC ? ".":"",
   3842              rD_addr, rA_addr, rB_addr);
   3843          assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
   3844          if (flag_OE) {
   3845             set_XER_OV( ty, PPCG_FLAG_OP_MULLD,
   3846                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3847          }
   3848          break;
   3849 
   3850       case 0x1E9: // divd (Divide DWord, PPC64 p419)
   3851          DIP("divd%s%s r%u,r%u,r%u\n",
   3852              flag_OE ? "o" : "", flag_rC ? ".":"",
   3853              rD_addr, rA_addr, rB_addr);
   3854          assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
   3855          if (flag_OE) {
   3856             set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3857                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3858          }
   3859          break;
   3860          /* Note:
   3861             if (0x8000_0000_0000_0000 / -1) or (x / 0)
   3862             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   3863             => But _no_ exception raised. */
   3864 
   3865       case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
   3866          DIP("divdu%s%s r%u,r%u,r%u\n",
   3867              flag_OE ? "o" : "", flag_rC ? ".":"",
   3868              rD_addr, rA_addr, rB_addr);
   3869          assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
   3870          if (flag_OE) {
   3871             set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3872                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3873          }
   3874          break;
   3875          /* Note: ditto comment divd, for (x / 0) */
   3876 
   3877       case 0x18B: // divweu (Divide Word Extended Unsigned)
   3878       {
   3879         /*
   3880          *  If (RA) >= (RB), or if an attempt is made to perform the division
   3881          *         <anything> / 0
   3882          * then the contents of register RD are undefined as are (if Rc=1) the contents of
   3883          * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
   3884          * to 1.
   3885          */
   3886          IRTemp res = newTemp(Ity_I32);
   3887          IRExpr * dividend, * divisor;
   3888          DIP("divweu%s%s r%u,r%u,r%u\n",
   3889              flag_OE ? "o" : "", flag_rC ? ".":"",
   3890                                          rD_addr, rA_addr, rB_addr);
   3891          if (mode64) {
   3892             dividend = unop( Iop_64to32, mkexpr( rA ) );
   3893             divisor = unop( Iop_64to32, mkexpr( rB ) );
   3894             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
   3895             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
   3896          } else {
   3897             dividend = mkexpr( rA );
   3898             divisor =  mkexpr( rB );
   3899             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
   3900             assign( rD, mkexpr( res) );
   3901          }
   3902 
   3903          if (flag_OE) {
   3904             set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
   3905                            mkexpr(res), dividend, divisor );
   3906          }
   3907          break;
   3908       }
   3909 
   3910       case 0x1AB: // divwe (Divide Word Extended)
   3911       {
   3912          /*
   3913           * If the quotient cannot be represented in 32 bits, or if an
   3914           * attempt is made to perform the division
   3915           *      <anything> / 0
   3916           * then the contents of register RD are undefined as are (if
   3917           * Rc=1) the contents of the LT, GT, and EQ bits of CR
   3918           * Field 0. In these cases, if OE=1 then OV is set to 1.
   3919           */
   3920 
   3921          IRTemp res = newTemp(Ity_I32);
   3922          IRExpr * dividend, * divisor;
   3923          DIP("divwe%s%s r%u,r%u,r%u\n",
   3924              flag_OE ? "o" : "", flag_rC ? ".":"",
   3925                                          rD_addr, rA_addr, rB_addr);
   3926          if (mode64) {
   3927             dividend = unop( Iop_64to32, mkexpr( rA ) );
   3928             divisor = unop( Iop_64to32, mkexpr( rB ) );
   3929             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
   3930             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
   3931          } else {
   3932             dividend = mkexpr( rA );
   3933             divisor =  mkexpr( rB );
   3934             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
   3935             assign( rD, mkexpr( res) );
   3936          }
   3937 
   3938          if (flag_OE) {
   3939             set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
   3940                            mkexpr(res), dividend, divisor );
   3941          }
   3942          break;
   3943       }
   3944 
   3945 
   3946       case 0x1A9: // divde (Divide Doubleword Extended)
   3947         /*
   3948          * If the quotient cannot be represented in 64 bits, or if an
   3949          * attempt is made to perform the division
   3950          *      <anything> / 0
   3951          * then the contents of register RD are undefined as are (if
   3952          * Rc=1) the contents of the LT, GT, and EQ bits of CR
   3953          * Field 0. In these cases, if OE=1 then OV is set to 1.
   3954          */
   3955          DIP("divde%s%s r%u,r%u,r%u\n",
   3956              flag_OE ? "o" : "", flag_rC ? ".":"",
   3957              rD_addr, rA_addr, rB_addr);
   3958          assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
   3959          if (flag_OE) {
   3960             set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
   3961                            mkexpr( rA ), mkexpr( rB ) );
   3962          }
   3963          break;
   3964 
   3965       case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
   3966         // Same CR and OV rules as given for divweu above
   3967         DIP("divdeu%s%s r%u,r%u,r%u\n",
   3968             flag_OE ? "o" : "", flag_rC ? ".":"",
   3969             rD_addr, rA_addr, rB_addr);
   3970         assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
   3971         if (flag_OE) {
   3972            set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
   3973                           mkexpr( rA ), mkexpr( rB ) );
   3974         }
   3975         break;
   3976 
   3977       default:
   3978          vex_printf("dis_int_arith(ppc)(opc2)\n");
   3979          return False;
   3980       }
   3981       break;
   3982 
   3983    default:
   3984       vex_printf("dis_int_arith(ppc)(opc1)\n");
   3985       return False;
   3986    }
   3987 
   3988    putIReg( rD_addr, mkexpr(rD) );
   3989 
   3990    if (do_rc && flag_rC) {
   3991       set_CR0( mkexpr(rD) );
   3992    }
   3993    return True;
   3994 }
   3995 
   3996 
   3997 
   3998 /*
   3999   Integer Compare Instructions
   4000 */
   4001 static Bool dis_int_cmp ( UInt theInstr )
   4002 {
   4003    /* D-Form, X-Form */
   4004    UChar opc1    = ifieldOPC(theInstr);
   4005    UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   4006    UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
   4007    UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
   4008    UChar rA_addr = ifieldRegA(theInstr);
   4009    UInt  uimm16  = ifieldUIMM16(theInstr);
   4010    UChar rB_addr = ifieldRegB(theInstr);
   4011    UInt  opc2    = ifieldOPClo10(theInstr);
   4012    UChar b0      = ifieldBIT0(theInstr);
   4013 
   4014    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   4015    IRExpr *a = getIReg(rA_addr);
   4016    IRExpr *b;
   4017 
   4018    if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
   4019       vex_printf("dis_int_cmp(ppc)(flag_L)\n");
   4020       return False;
   4021    }
   4022 
   4023    if (b22 != 0) {
   4024       vex_printf("dis_int_cmp(ppc)(b22)\n");
   4025       return False;
   4026    }
   4027 
   4028    switch (opc1) {
   4029    case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
   4030       DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
   4031           (Int)extend_s_16to32(uimm16));
   4032       b = mkSzExtendS16( ty, uimm16 );
   4033       if (flag_L == 1) {
   4034          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   4035       } else {
   4036          a = mkNarrowTo32( ty, a );
   4037          b = mkNarrowTo32( ty, b );
   4038          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
   4039       }
   4040       putCR0( crfD, getXER_SO() );
   4041       break;
   4042 
   4043    case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
   4044       DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
   4045       b = mkSzImm( ty, uimm16 );
   4046       if (flag_L == 1) {
   4047          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   4048       } else {
   4049          a = mkNarrowTo32( ty, a );
   4050          b = mkNarrowTo32( ty, b );
   4051          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   4052       }
   4053       putCR0( crfD, getXER_SO() );
   4054       break;
   4055 
   4056    /* X Form */
   4057    case 0x1F:
   4058       if (b0 != 0) {
   4059          vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
   4060          return False;
   4061       }
   4062       b = getIReg(rB_addr);
   4063 
   4064       switch (opc2) {
   4065       case 0x000: // cmp (Compare, PPC32 p367)
   4066          DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   4067          /* Comparing a reg with itself produces a result which
   4068             doesn't depend on the contents of the reg.  Therefore
   4069             remove the false dependency, which has been known to cause
   4070             memcheck to produce false errors. */
   4071          if (rA_addr == rB_addr)
   4072             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   4073                     ? mkU64(0)  : mkU32(0);
   4074          if (flag_L == 1) {
   4075             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   4076          } else {
   4077             a = mkNarrowTo32( ty, a );
   4078             b = mkNarrowTo32( ty, b );
   4079             putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
   4080          }
   4081          putCR0( crfD, getXER_SO() );
   4082          break;
   4083 
   4084       case 0x020: // cmpl (Compare Logical, PPC32 p369)
   4085          DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   4086          /* Comparing a reg with itself produces a result which
   4087             doesn't depend on the contents of the reg.  Therefore
   4088             remove the false dependency, which has been known to cause
   4089             memcheck to produce false errors. */
   4090          if (rA_addr == rB_addr)
   4091             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   4092                     ? mkU64(0)  : mkU32(0);
   4093          if (flag_L == 1) {
   4094             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   4095          } else {
   4096             a = mkNarrowTo32( ty, a );
   4097             b = mkNarrowTo32( ty, b );
   4098             putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   4099          }
   4100          putCR0( crfD, getXER_SO() );
   4101          break;
   4102 
   4103       default:
   4104          vex_printf("dis_int_cmp(ppc)(opc2)\n");
   4105          return False;
   4106       }
   4107       break;
   4108 
   4109    default:
   4110       vex_printf("dis_int_cmp(ppc)(opc1)\n");
   4111       return False;
   4112    }
   4113 
   4114    return True;
   4115 }
   4116 
   4117 
   4118 /*
   4119   Integer Logical Instructions
   4120 */
   4121 static Bool dis_int_logic ( UInt theInstr )
   4122 {
   4123    /* D-Form, X-Form */
   4124    UChar opc1    = ifieldOPC(theInstr);
   4125    UChar rS_addr = ifieldRegDS(theInstr);
   4126    UChar rA_addr = ifieldRegA(theInstr);
   4127    UInt  uimm16  = ifieldUIMM16(theInstr);
   4128    UChar rB_addr = ifieldRegB(theInstr);
   4129    UInt  opc2    = ifieldOPClo10(theInstr);
   4130    UChar flag_rC = ifieldBIT0(theInstr);
   4131 
   4132    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4133    IRTemp rS     = newTemp(ty);
   4134    IRTemp rA     = newTemp(ty);
   4135    IRTemp rB     = newTemp(ty);
   4136    IRExpr* irx;
   4137    Bool do_rc    = False;
   4138 
   4139    assign( rS, getIReg(rS_addr) );
   4140    assign( rB, getIReg(rB_addr) );
   4141 
   4142    switch (opc1) {
   4143    case 0x1C: // andi. (AND Immediate, PPC32 p358)
   4144       DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4145       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   4146                          mkSzImm(ty, uimm16)) );
   4147       do_rc = True;  // Always record to CR
   4148       flag_rC = 1;
   4149       break;
   4150 
   4151    case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
   4152       DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4153       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   4154                          mkSzImm(ty, uimm16 << 16)) );
   4155       do_rc = True;  // Always record to CR
   4156       flag_rC = 1;
   4157       break;
   4158 
   4159    case 0x18: // ori (OR Immediate, PPC32 p497)
   4160       DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4161       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   4162                          mkSzImm(ty, uimm16)) );
   4163       break;
   4164 
   4165    case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
   4166       DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4167       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   4168                          mkSzImm(ty, uimm16 << 16)) );
   4169       break;
   4170 
   4171    case 0x1A: // xori (XOR Immediate, PPC32 p550)
   4172       DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4173       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   4174                          mkSzImm(ty, uimm16)) );
   4175       break;
   4176 
   4177    case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
   4178       DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4179       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   4180                          mkSzImm(ty, uimm16 << 16)) );
   4181       break;
   4182 
   4183    /* X Form */
   4184    case 0x1F:
   4185       do_rc = True; // All below record to CR, except for where we return at case end.
   4186 
   4187       switch (opc2) {
   4188       case 0x01C: // and (AND, PPC32 p356)
   4189          DIP("and%s r%u,r%u,r%u\n",
   4190              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4191          assign(rA, binop( mkSzOp(ty, Iop_And8),
   4192                            mkexpr(rS), mkexpr(rB)));
   4193          break;
   4194 
   4195       case 0x03C: // andc (AND with Complement, PPC32 p357)
   4196          DIP("andc%s r%u,r%u,r%u\n",
   4197              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4198          assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   4199                            unop( mkSzOp(ty, Iop_Not8),
   4200                                  mkexpr(rB))));
   4201          break;
   4202 
   4203       case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
   4204          IRExpr* lo32;
   4205          if (rB_addr!=0) {
   4206             vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
   4207             return False;
   4208          }
   4209          DIP("cntlzw%s r%u,r%u\n",
   4210              flag_rC ? ".":"", rA_addr, rS_addr);
   4211 
   4212          // mode64: count in low word only
   4213          lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
   4214 
   4215          // Iop_Clz32 undefined for arg==0, so deal with that case:
   4216          irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
   4217          assign(rA, mkWidenFrom32(ty,
   4218                          IRExpr_ITE( irx,
   4219                                      unop(Iop_Clz32, lo32),
   4220                                      mkU32(32)),
   4221                          False));
   4222 
   4223          // TODO: alternatively: assign(rA, verbose_Clz32(rS));
   4224          break;
   4225       }
   4226 
   4227       case 0x11C: // eqv (Equivalent, PPC32 p396)
   4228          DIP("eqv%s r%u,r%u,r%u\n",
   4229              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4230          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   4231                            binop( mkSzOp(ty, Iop_Xor8),
   4232                                   mkexpr(rS), mkexpr(rB))) );
   4233          break;
   4234 
   4235       case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
   4236          if (rB_addr!=0) {
   4237             vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
   4238             return False;
   4239          }
   4240          DIP("extsb%s r%u,r%u\n",
   4241              flag_rC ? ".":"", rA_addr, rS_addr);
   4242          if (mode64)
   4243             assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
   4244          else
   4245             assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
   4246          break;
   4247 
   4248       case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
   4249          if (rB_addr!=0) {
   4250             vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
   4251             return False;
   4252          }
   4253          DIP("extsh%s r%u,r%u\n",
   4254              flag_rC ? ".":"", rA_addr, rS_addr);
   4255          if (mode64)
   4256             assign( rA, unop(Iop_16Sto64,
   4257                              unop(Iop_64to16, mkexpr(rS))) );
   4258          else
   4259             assign( rA, unop(Iop_16Sto32,
   4260                              unop(Iop_32to16, mkexpr(rS))) );
   4261          break;
   4262 
   4263       case 0x1DC: // nand (NAND, PPC32 p492)
   4264          DIP("nand%s r%u,r%u,r%u\n",
   4265              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4266          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   4267                            binop( mkSzOp(ty, Iop_And8),
   4268                                   mkexpr(rS), mkexpr(rB))) );
   4269          break;
   4270 
   4271       case 0x07C: // nor (NOR, PPC32 p494)
   4272          DIP("nor%s r%u,r%u,r%u\n",
   4273              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4274          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   4275                            binop( mkSzOp(ty, Iop_Or8),
   4276                                   mkexpr(rS), mkexpr(rB))) );
   4277          break;
   4278 
   4279       case 0x1BC: // or (OR, PPC32 p495)
   4280          if ((!flag_rC) && rS_addr == rB_addr) {
   4281             DIP("mr r%u,r%u\n", rA_addr, rS_addr);
   4282             assign( rA, mkexpr(rS) );
   4283          } else {
   4284             DIP("or%s r%u,r%u,r%u\n",
   4285                 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4286             assign( rA, binop( mkSzOp(ty, Iop_Or8),
   4287                                mkexpr(rS), mkexpr(rB)) );
   4288          }
   4289          break;
   4290 
   4291       case 0x19C: // orc  (OR with Complement, PPC32 p496)
   4292          DIP("orc%s r%u,r%u,r%u\n",
   4293              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4294          assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   4295                             unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
   4296          break;
   4297 
   4298       case 0x13C: // xor (XOR, PPC32 p549)
   4299          DIP("xor%s r%u,r%u,r%u\n",
   4300              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4301          assign( rA, binop( mkSzOp(ty, Iop_Xor8),
   4302                             mkexpr(rS), mkexpr(rB)) );
   4303          break;
   4304 
   4305 
   4306       /* 64bit Integer Logical Instructions */
   4307       case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
   4308          if (rB_addr!=0) {
   4309             vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
   4310             return False;
   4311          }
   4312          DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
   4313          assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
   4314          break;
   4315 
   4316       case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
   4317          if (rB_addr!=0) {
   4318             vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
   4319             return False;
   4320          }
   4321          DIP("cntlzd%s r%u,r%u\n",
   4322              flag_rC ? ".":"", rA_addr, rS_addr);
   4323          // Iop_Clz64 undefined for arg==0, so deal with that case:
   4324          irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
   4325          assign(rA, IRExpr_ITE( irx,
   4326                                 unop(Iop_Clz64, mkexpr(rS)),
   4327                                 mkU64(64) ));
   4328          // TODO: alternatively: assign(rA, verbose_Clz64(rS));
   4329          break;
   4330 
   4331       case 0x1FC: // cmpb (Power6: compare bytes)
   4332          DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
   4333 
   4334          if (mode64)
   4335             assign( rA, unop( Iop_V128to64,
   4336                               binop( Iop_CmpEQ8x16,
   4337                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
   4338                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
   4339                                      )) );
   4340          else
   4341             assign( rA, unop( Iop_V128to32,
   4342                               binop( Iop_CmpEQ8x16,
   4343                                      unop( Iop_32UtoV128, mkexpr(rS) ),
   4344                                      unop( Iop_32UtoV128, mkexpr(rB) )
   4345                                      )) );
   4346          break;
   4347 
   4348       case 0x2DF: { // mftgpr (move floating-point to general purpose register)
   4349          IRTemp frB = newTemp(Ity_F64);
   4350          DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
   4351 
   4352          assign( frB, getFReg(rB_addr));  // always F64
   4353          if (mode64)
   4354             assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   4355          else
   4356             assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
   4357 
   4358          putIReg( rS_addr, mkexpr(rA));
   4359          return True;
   4360       }
   4361 
   4362       case 0x25F: { // mffgpr (move floating-point from general purpose register)
   4363          IRTemp frA = newTemp(Ity_F64);
   4364          DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
   4365 
   4366          if (mode64)
   4367             assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
   4368          else
   4369             assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
   4370 
   4371          putFReg( rS_addr, mkexpr(frA));
   4372          return True;
   4373       }
   4374       case 0x1FA: // popcntd (population count doubleword
   4375       {
   4376     	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
   4377     	  IRTemp result = gen_POPCOUNT(ty, rS, DWORD);
   4378     	  putIReg( rA_addr, mkexpr(result) );
   4379     	  return True;
   4380       }
   4381       case 0x17A: // popcntw (Population Count Words)
   4382       {
   4383          DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
   4384          if (mode64) {
   4385             IRTemp resultHi, resultLo;
   4386             IRTemp argLo = newTemp(Ity_I32);
   4387             IRTemp argHi = newTemp(Ity_I32);
   4388             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
   4389             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
   4390             resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD);
   4391             resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD);
   4392             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
   4393          } else {
   4394             IRTemp result = gen_POPCOUNT(ty, rS, WORD);
   4395             putIReg( rA_addr, mkexpr(result) );
   4396          }
   4397          return True;
   4398       }
   4399       case 0x7A: // popcntb (Population Count Byte)
   4400       {
   4401          DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
   4402 
   4403          if (mode64) {
   4404             IRTemp resultHi, resultLo;
   4405             IRTemp argLo = newTemp(Ity_I32);
   4406             IRTemp argHi = newTemp(Ity_I32);
   4407             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
   4408             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
   4409             resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE);
   4410             resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE);
   4411             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
   4412                                     mkexpr(resultLo)));
   4413          } else {
   4414             IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
   4415             putIReg( rA_addr, mkexpr(result) );
   4416          }
   4417          return True;
   4418       }
   4419        case 0x0FC: // bpermd (Bit Permute Doubleword)
   4420        {
   4421           /* This is a lot of rigmarole to emulate bpermd like this, as it
   4422            * could be done much faster by implementing a call to the native
   4423            * instruction.  However, where possible I want to avoid using new
   4424            * native instructions so that we can use valgrind to emulate those
   4425            * instructions on older PPC64 hardware.
   4426            */
   4427  #define BPERMD_IDX_MASK 0x00000000000000FFULL
   4428  #define BPERMD_BIT_MASK 0x8000000000000000ULL
   4429           int i;
   4430           IRExpr * rS_expr = mkexpr(rS);
   4431           IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
   4432           DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
   4433           for (i = 0; i < 8; i++) {
   4434              IRTemp idx_tmp = newTemp( Ity_I64 );
   4435              IRTemp perm_bit = newTemp( Ity_I64 );
   4436              IRTemp idx = newTemp( Ity_I8 );
   4437              IRTemp idx_LT64 = newTemp( Ity_I1 );
   4438              IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
   4439 
   4440              assign( idx_tmp,
   4441                      binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
   4442              assign( idx_LT64,
   4443                            binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
   4444              assign( idx,
   4445                            binop( Iop_And8,
   4446                                   unop( Iop_1Sto8,
   4447                                         mkexpr(idx_LT64) ),
   4448                                   unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
   4449              /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
   4450               * to determine which bit of rB to use for the perm bit, and then we shift
   4451               * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
   4452               * to set the final perm bit.
   4453               */
   4454              assign( idx_LT64_ity64,
   4455                            unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
   4456              assign( perm_bit,
   4457                            binop( Iop_And64,
   4458                                   mkexpr( idx_LT64_ity64 ),
   4459                                   binop( Iop_Shr64,
   4460                                          binop( Iop_And64,
   4461                                                 mkU64( BPERMD_BIT_MASK ),
   4462                                                 binop( Iop_Shl64,
   4463                                                        mkexpr( rB ),
   4464                                                        mkexpr( idx ) ) ),
   4465                                          mkU8( 63 ) ) ) );
   4466              res = binop( Iop_Or64,
   4467                                 res,
   4468                                 binop( Iop_Shl64,
   4469                                        mkexpr( perm_bit ),
   4470                                        mkU8( i ) ) );
   4471              rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
   4472           }
   4473           putIReg(rA_addr, res);
   4474           return True;
   4475        }
   4476 
   4477       default:
   4478          vex_printf("dis_int_logic(ppc)(opc2)\n");
   4479          return False;
   4480       }
   4481       break;
   4482 
   4483    default:
   4484       vex_printf("dis_int_logic(ppc)(opc1)\n");
   4485       return False;
   4486    }
   4487 
   4488    putIReg( rA_addr, mkexpr(rA) );
   4489 
   4490    if (do_rc && flag_rC) {
   4491       set_CR0( mkexpr(rA) );
   4492    }
   4493    return True;
   4494 }
   4495 
   4496 /*
   4497   Integer Parity Instructions
   4498 */
   4499 static Bool dis_int_parity ( UInt theInstr )
   4500 {
   4501    /* X-Form */
   4502    UChar opc1    = ifieldOPC(theInstr);
   4503    UChar rS_addr = ifieldRegDS(theInstr);
   4504    UChar rA_addr = ifieldRegA(theInstr);
   4505    UChar rB_addr = ifieldRegB(theInstr);
   4506    UInt  opc2    = ifieldOPClo10(theInstr);
   4507    UChar b0      = ifieldBIT0(theInstr);
   4508    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4509 
   4510    IRTemp rS     = newTemp(ty);
   4511    IRTemp rA     = newTemp(ty);
   4512    IRTemp iTot1  = newTemp(Ity_I32);
   4513    IRTemp iTot2  = newTemp(Ity_I32);
   4514    IRTemp iTot3  = newTemp(Ity_I32);
   4515    IRTemp iTot4  = newTemp(Ity_I32);
   4516    IRTemp iTot5  = newTemp(Ity_I32);
   4517    IRTemp iTot6  = newTemp(Ity_I32);
   4518    IRTemp iTot7  = newTemp(Ity_I32);
   4519    IRTemp iTot8  = newTemp(Ity_I32);
   4520    IRTemp rS1    = newTemp(ty);
   4521    IRTemp rS2    = newTemp(ty);
   4522    IRTemp rS3    = newTemp(ty);
   4523    IRTemp rS4    = newTemp(ty);
   4524    IRTemp rS5    = newTemp(ty);
   4525    IRTemp rS6    = newTemp(ty);
   4526    IRTemp rS7    = newTemp(ty);
   4527    IRTemp iHi    = newTemp(Ity_I32);
   4528    IRTemp iLo    = newTemp(Ity_I32);
   4529    IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
   4530    IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
   4531 
   4532    if (opc1 != 0x1f || rB_addr || b0) {
   4533       vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
   4534       return False;
   4535    }
   4536 
   4537    assign( rS, getIReg(rS_addr) );
   4538 
   4539    switch (opc2) {
   4540    case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
   4541       DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
   4542       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   4543       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   4544       assign( iTot2, binop(Iop_Add32,
   4545                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   4546                            mkexpr(iTot1)) );
   4547       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   4548       assign( iTot3, binop(Iop_Add32,
   4549                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   4550                            mkexpr(iTot2)) );
   4551       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   4552       assign( iTot4, binop(Iop_Add32,
   4553                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   4554                            mkexpr(iTot3)) );
   4555       if (mode64) {
   4556          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   4557          assign( iTot5, binop(Iop_Add32,
   4558                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
   4559                               mkexpr(iTot4)) );
   4560          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   4561          assign( iTot6, binop(Iop_Add32,
   4562                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   4563                               mkexpr(iTot5)) );
   4564          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   4565          assign( iTot7, binop(Iop_Add32,
   4566                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   4567                               mkexpr(iTot6)) );
   4568          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
   4569          assign( iTot8, binop(Iop_Add32,
   4570                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   4571                               mkexpr(iTot7)) );
   4572          assign( rA, unop(Iop_32Uto64,
   4573                           binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
   4574       } else
   4575          assign( rA, mkexpr(iTot4) );
   4576 
   4577       break;
   4578    case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
   4579       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   4580       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   4581       assign( iTot2, binop(Iop_Add32,
   4582                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   4583                            mkexpr(iTot1)) );
   4584       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   4585       assign( iTot3, binop(Iop_Add32,
   4586                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   4587                            mkexpr(iTot2)) );
   4588       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   4589       assign( iTot4, binop(Iop_Add32,
   4590                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   4591                            mkexpr(iTot3)) );
   4592       assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
   4593 
   4594       if (mode64) {
   4595          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   4596          assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
   4597          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   4598          assign( iTot6, binop(Iop_Add32,
   4599                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   4600                               mkexpr(iTot5)) );
   4601          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   4602          assign( iTot7, binop(Iop_Add32,
   4603                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   4604                               mkexpr(iTot6)) );
   4605          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
   4606          assign( iTot8, binop(Iop_Add32,
   4607                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   4608                               mkexpr(iTot7)) );
   4609          assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
   4610             assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
   4611       } else
   4612          assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
   4613       break;
   4614    default:
   4615       vex_printf("dis_int_parity(ppc)(opc2)\n");
   4616       return False;
   4617    }
   4618 
   4619    putIReg( rA_addr, mkexpr(rA) );
   4620 
   4621    return True;
   4622 }
   4623 
   4624 
   4625 /*
   4626   Integer Rotate Instructions
   4627 */
   4628 static Bool dis_int_rot ( UInt theInstr )
   4629 {
   4630    /* M-Form, MDS-Form */
   4631    UChar opc1    = ifieldOPC(theInstr);
   4632    UChar rS_addr = ifieldRegDS(theInstr);
   4633    UChar rA_addr = ifieldRegA(theInstr);
   4634    UChar rB_addr = ifieldRegB(theInstr);
   4635    UChar sh_imm  = rB_addr;
   4636    UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
   4637    UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
   4638    UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
   4639    UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
   4640    UChar b1      = ifieldBIT1(theInstr);
   4641    UChar flag_rC = ifieldBIT0(theInstr);
   4642 
   4643    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4644    IRTemp rS     = newTemp(ty);
   4645    IRTemp rA     = newTemp(ty);
   4646    IRTemp rB     = newTemp(ty);
   4647    IRTemp rot    = newTemp(ty);
   4648    IRExpr *r;
   4649    UInt   mask32;
   4650    ULong  mask64;
   4651 
   4652    assign( rS, getIReg(rS_addr) );
   4653    assign( rB, getIReg(rB_addr) );
   4654 
   4655    switch (opc1) {
   4656    case 0x14: {
   4657       // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
   4658       DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4659           rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4660       if (mode64) {
   4661          // tmp32 = (ROTL(rS_Lo32, Imm)
   4662          // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
   4663          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4664          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   4665          r = unop(Iop_32Uto64, r);
   4666          assign( rot, binop(Iop_Or64, r,
   4667                             binop(Iop_Shl64, r, mkU8(32))) );
   4668          assign( rA,
   4669             binop(Iop_Or64,
   4670                   binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
   4671                   binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
   4672       }
   4673       else {
   4674          // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
   4675          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4676          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4677          assign( rA,
   4678             binop(Iop_Or32,
   4679                   binop(Iop_And32, mkU32(mask32), r),
   4680                   binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
   4681       }
   4682       break;
   4683    }
   4684 
   4685    case 0x15: {
   4686       // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
   4687       vassert(MaskBeg < 32);
   4688       vassert(MaskEnd < 32);
   4689       vassert(sh_imm  < 32);
   4690 
   4691       if (mode64) {
   4692          IRTemp rTmp = newTemp(Ity_I64);
   4693          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4694          DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4695              rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4696          // tmp32 = (ROTL(rS_Lo32, Imm)
   4697          // rA = ((tmp32 || tmp32) & mask64)
   4698          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   4699          r = unop(Iop_32Uto64, r);
   4700          assign( rTmp, r );
   4701          r = NULL;
   4702          assign( rot, binop(Iop_Or64, mkexpr(rTmp),
   4703                             binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
   4704          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   4705       }
   4706       else {
   4707          if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
   4708             /* Special-case the ,n,0,31-n form as that is just n-bit
   4709                shift left, PPC32 p501 */
   4710             DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   4711                 rA_addr, rS_addr, sh_imm);
   4712             assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
   4713          }
   4714          else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
   4715             /* Special-case the ,32-n,n,31 form as that is just n-bit
   4716                unsigned shift right, PPC32 p501 */
   4717             DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   4718                 rA_addr, rS_addr, MaskBeg);
   4719             assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
   4720          }
   4721          else {
   4722             /* General case. */
   4723             mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4724             DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4725                 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4726             // rA = ROTL(rS, Imm) & mask
   4727             assign( rA, binop(Iop_And32,
   4728                               ROTL(mkexpr(rS), mkU8(sh_imm)),
   4729                               mkU32(mask32)) );
   4730          }
   4731       }
   4732       break;
   4733    }
   4734 
   4735    case 0x17: {
   4736       // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
   4737       DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
   4738           rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
   4739       if (mode64) {
   4740          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4741          /* weird insn alert!
   4742             tmp32 = (ROTL(rS_Lo32, rB[0-4])
   4743             rA = ((tmp32 || tmp32) & mask64)
   4744          */
   4745          // note, ROTL does the masking, so we don't do it here
   4746          r = ROTL( unop(Iop_64to32, mkexpr(rS)),
   4747                    unop(Iop_64to8, mkexpr(rB)) );
   4748          r = unop(Iop_32Uto64, r);
   4749          assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
   4750          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   4751       } else {
   4752          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4753          // rA = ROTL(rS, rB[0-4]) & mask
   4754          // note, ROTL does the masking, so we don't do it here
   4755          assign( rA, binop(Iop_And32,
   4756                            ROTL(mkexpr(rS),
   4757                                 unop(Iop_32to8, mkexpr(rB))),
   4758                            mkU32(mask32)) );
   4759       }
   4760       break;
   4761    }
   4762 
   4763    /* 64bit Integer Rotates */
   4764    case 0x1E: {
   4765       msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
   4766       sh_imm |= b1 << 5;
   4767 
   4768       vassert( msk_imm < 64 );
   4769       vassert( sh_imm < 64 );
   4770 
   4771       switch (opc2) {
   4772       case 0x4: {
   4773          /* r = ROTL64( rS, rB_lo6) */
   4774          r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
   4775 
   4776          if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
   4777             DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   4778                 rA_addr, rS_addr, rB_addr, msk_imm);
   4779             // note, ROTL does the masking, so we don't do it here
   4780             mask64 = MASK64(0, 63-msk_imm);
   4781             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4782             break;
   4783          } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
   4784             DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   4785                 rA_addr, rS_addr, rB_addr, msk_imm);
   4786             mask64 = MASK64(63-msk_imm, 63);
   4787             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4788             break;
   4789          }
   4790          break;
   4791       }
   4792       case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
   4793          DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4794              rA_addr, rS_addr, sh_imm, msk_imm);
   4795          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4796          mask64 = MASK64(sh_imm, 63-msk_imm);
   4797          assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4798          break;
   4799          // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
   4800          /*
   4801            Hmm... looks like this'll do the job more simply:
   4802            r = SHL(rS, sh_imm)
   4803            m = ~(1 << (63-msk_imm))
   4804            assign(rA, r & m);
   4805          */
   4806 
   4807       case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
   4808          if (mode64
   4809              && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
   4810             /* special-case the ,64-n,n form as that is just
   4811                unsigned shift-right by n */
   4812             DIP("srdi%s r%u,r%u,%u\n",
   4813                 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
   4814             assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
   4815          } else {
   4816             DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4817                 rA_addr, rS_addr, sh_imm, msk_imm);
   4818             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4819             mask64 = MASK64(0, 63-msk_imm);
   4820             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4821          }
   4822          break;
   4823 
   4824       case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
   4825          if (mode64
   4826              && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
   4827             /* special-case the ,n,63-n form as that is just
   4828                shift-left by n */
   4829             DIP("sldi%s r%u,r%u,%u\n",
   4830                 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   4831             assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
   4832          } else {
   4833             DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4834                 rA_addr, rS_addr, sh_imm, msk_imm);
   4835             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4836             mask64 = MASK64(63-msk_imm, 63);
   4837             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4838          }
   4839          break;
   4840 
   4841       case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
   4842          IRTemp rA_orig = newTemp(ty);
   4843          DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4844              rA_addr, rS_addr, sh_imm, msk_imm);
   4845          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4846          mask64 = MASK64(sh_imm, 63-msk_imm);
   4847          assign( rA_orig, getIReg(rA_addr) );
   4848          assign( rA, binop(Iop_Or64,
   4849                            binop(Iop_And64, mkU64(mask64),  r),
   4850                            binop(Iop_And64, mkU64(~mask64),
   4851                                             mkexpr(rA_orig))) );
   4852          break;
   4853       }
   4854       default:
   4855          vex_printf("dis_int_rot(ppc)(opc2)\n");
   4856          return False;
   4857       }
   4858       break;
   4859    }
   4860 
   4861    default:
   4862       vex_printf("dis_int_rot(ppc)(opc1)\n");
   4863       return False;
   4864    }
   4865 
   4866    putIReg( rA_addr, mkexpr(rA) );
   4867 
   4868    if (flag_rC) {
   4869       set_CR0( mkexpr(rA) );
   4870    }
   4871    return True;
   4872 }
   4873 
   4874 
   4875 /*
   4876   Integer Load Instructions
   4877 */
   4878 static Bool dis_int_load ( UInt theInstr )
   4879 {
   4880    /* D-Form, X-Form, DS-Form */
   4881    UChar opc1     = ifieldOPC(theInstr);
   4882    UChar rD_addr  = ifieldRegDS(theInstr);
   4883    UChar rA_addr  = ifieldRegA(theInstr);
   4884    UInt  uimm16   = ifieldUIMM16(theInstr);
   4885    UChar rB_addr  = ifieldRegB(theInstr);
   4886    UInt  opc2     = ifieldOPClo10(theInstr);
   4887    UChar b1       = ifieldBIT1(theInstr);
   4888    UChar b0       = ifieldBIT0(theInstr);
   4889 
   4890    Int     simm16 = extend_s_16to32(uimm16);
   4891    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   4892    IRTemp  EA     = newTemp(ty);
   4893    IRExpr* val;
   4894 
   4895    switch (opc1) {
   4896    case 0x1F: // register offset
   4897       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   4898       break;
   4899    case 0x38: // immediate offset: 64bit: lq: maskoff
   4900               // lowest 4 bits of immediate before forming EA
   4901       simm16 = simm16 & 0xFFFFFFF0;
   4902       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   4903       break;
   4904    case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
   4905               // lowest 2 bits of immediate before forming EA
   4906       simm16 = simm16 & 0xFFFFFFFC;
   4907       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   4908       break;
   4909    default:   // immediate offset
   4910       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   4911       break;
   4912    }
   4913 
   4914    switch (opc1) {
   4915    case 0x22: // lbz (Load B & Zero, PPC32 p433)
   4916       DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4917       val = load(Ity_I8, mkexpr(EA));
   4918       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4919       break;
   4920 
   4921    case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
   4922       if (rA_addr == 0 || rA_addr == rD_addr) {
   4923          vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
   4924          return False;
   4925       }
   4926       DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4927       val = load(Ity_I8, mkexpr(EA));
   4928       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4929       putIReg( rA_addr, mkexpr(EA) );
   4930       break;
   4931 
   4932    case 0x2A: // lha (Load HW Alg, PPC32 p445)
   4933       DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4934       val = load(Ity_I16, mkexpr(EA));
   4935       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4936       break;
   4937 
   4938    case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
   4939       if (rA_addr == 0 || rA_addr == rD_addr) {
   4940          vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
   4941          return False;
   4942       }
   4943       DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4944       val = load(Ity_I16, mkexpr(EA));
   4945       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4946       putIReg( rA_addr, mkexpr(EA) );
   4947       break;
   4948 
   4949    case 0x28: // lhz (Load HW & Zero, PPC32 p450)
   4950       DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4951       val = load(Ity_I16, mkexpr(EA));
   4952       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4953       break;
   4954 
   4955    case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
   4956       if (rA_addr == 0 || rA_addr == rD_addr) {
   4957          vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
   4958          return False;
   4959       }
   4960       DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4961       val = load(Ity_I16, mkexpr(EA));
   4962       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4963       putIReg( rA_addr, mkexpr(EA) );
   4964       break;
   4965 
   4966    case 0x20: // lwz (Load W & Zero, PPC32 p460)
   4967       DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4968       val = load(Ity_I32, mkexpr(EA));
   4969       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4970       break;
   4971 
   4972    case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
   4973       if (rA_addr == 0 || rA_addr == rD_addr) {
   4974          vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
   4975          return False;
   4976       }
   4977       DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4978       val = load(Ity_I32, mkexpr(EA));
   4979       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4980       putIReg( rA_addr, mkexpr(EA) );
   4981       break;
   4982 
   4983    /* X Form */
   4984    case 0x1F:
   4985       if (b0 != 0) {
   4986          vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
   4987          return False;
   4988       }
   4989 
   4990       switch (opc2) {
   4991       case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
   4992          DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4993          if (rA_addr == 0 || rA_addr == rD_addr) {
   4994             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   4995             return False;
   4996          }
   4997          val = load(Ity_I8, mkexpr(EA));
   4998          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4999          putIReg( rA_addr, mkexpr(EA) );
   5000          break;
   5001 
   5002       case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
   5003          DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5004          val = load(Ity_I8, mkexpr(EA));
   5005          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   5006          break;
   5007 
   5008       case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
   5009          if (rA_addr == 0 || rA_addr == rD_addr) {
   5010             vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
   5011             return False;
   5012          }
   5013          DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5014          val = load(Ity_I16, mkexpr(EA));
   5015          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   5016          putIReg( rA_addr, mkexpr(EA) );
   5017          break;
   5018 
   5019       case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
   5020          DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5021          val = load(Ity_I16, mkexpr(EA));
   5022          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   5023          break;
   5024 
   5025       case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
   5026          if (rA_addr == 0 || rA_addr == rD_addr) {
   5027             vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
   5028             return False;
   5029          }
   5030          DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5031          val = load(Ity_I16, mkexpr(EA));
   5032          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   5033          putIReg( rA_addr, mkexpr(EA) );
   5034          break;
   5035 
   5036       case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
   5037          DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5038          val = load(Ity_I16, mkexpr(EA));
   5039          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   5040          break;
   5041 
   5042       case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
   5043          if (rA_addr == 0 || rA_addr == rD_addr) {
   5044             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   5045             return False;
   5046          }
   5047          DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5048          val = load(Ity_I32, mkexpr(EA));
   5049          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   5050          putIReg( rA_addr, mkexpr(EA) );
   5051          break;
   5052 
   5053       case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
   5054          DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5055          val = load(Ity_I32, mkexpr(EA));
   5056          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   5057          break;
   5058 
   5059 
   5060       /* 64bit Loads */
   5061       case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
   5062          if (rA_addr == 0 || rA_addr == rD_addr) {
   5063             vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
   5064             return False;
   5065          }
   5066          DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5067          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
   5068          putIReg( rA_addr, mkexpr(EA) );
   5069          break;
   5070 
   5071       case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
   5072          DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5073          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
   5074          break;
   5075 
   5076       case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
   5077          if (rA_addr == 0 || rA_addr == rD_addr) {
   5078             vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
   5079             return False;
   5080          }
   5081          DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5082          putIReg( rD_addr,
   5083                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
   5084          putIReg( rA_addr, mkexpr(EA) );
   5085          break;
   5086 
   5087       case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
   5088          DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5089          putIReg( rD_addr,
   5090                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
   5091          break;
   5092 
   5093       default:
   5094          vex_printf("dis_int_load(ppc)(opc2)\n");
   5095          return False;
   5096       }
   5097       break;
   5098 
   5099    /* DS Form - 64bit Loads.  In each case EA will have been formed
   5100       with the lowest 2 bits masked off the immediate offset. */
   5101    case 0x3A:
   5102       switch ((b1<<1) | b0) {
   5103       case 0x0: // ld (Load DWord, PPC64 p472)
   5104          DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   5105          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
   5106          break;
   5107 
   5108       case 0x1: // ldu (Load DWord, Update, PPC64 p474)
   5109          if (rA_addr == 0 || rA_addr == rD_addr) {
   5110             vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
   5111             return False;
   5112          }
   5113          DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   5114          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
   5115          putIReg( rA_addr, mkexpr(EA) );
   5116          break;
   5117 
   5118       case 0x2: // lwa (Load Word Alg, PPC64 p499)
   5119          DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   5120          putIReg( rD_addr,
   5121                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
   5122          break;
   5123 
   5124       default:
   5125          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   5126          return False;
   5127       }
   5128       break;
   5129 
   5130    case 0x38: {
   5131       IRTemp  high = newTemp(ty);
   5132       IRTemp  low  = newTemp(ty);
   5133       /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
   5134       DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   5135       /* NOTE: there are some changes to XER[41:42] that have not been
   5136        * implemented.
   5137        */
   5138       // trap if EA misaligned on 16 byte address
   5139       if (mode64) {
   5140          if (host_endness == VexEndnessBE) {
   5141             assign(high, load(ty, mkexpr( EA ) ) );
   5142             assign(low, load(ty, binop( Iop_Add64,
   5143                                         mkexpr( EA ),
   5144                                         mkU64( 8 ) ) ) );
   5145 	 } else {
   5146             assign(low, load(ty, mkexpr( EA ) ) );
   5147             assign(high, load(ty, binop( Iop_Add64,
   5148                                          mkexpr( EA ),
   5149                                          mkU64( 8 ) ) ) );
   5150 	 }
   5151       } else {
   5152          assign(high, load(ty, binop( Iop_Add32,
   5153                                       mkexpr( EA ),
   5154                                       mkU32( 4 ) ) ) );
   5155          assign(low, load(ty, binop( Iop_Add32,
   5156                                       mkexpr( EA ),
   5157                                       mkU32( 12 ) ) ) );
   5158       }
   5159       gen_SIGBUS_if_misaligned( EA, 16 );
   5160       putIReg( rD_addr,  mkexpr( high) );
   5161       putIReg( rD_addr+1,  mkexpr( low) );
   5162       break;
   5163    }
   5164    default:
   5165       vex_printf("dis_int_load(ppc)(opc1)\n");
   5166       return False;
   5167    }
   5168    return True;
   5169 }
   5170 
   5171 
   5172 
   5173 /*
   5174   Integer Store Instructions
   5175 */
   5176 static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi )
   5177 {
   5178    /* D-Form, X-Form, DS-Form */
   5179    UChar opc1    = ifieldOPC(theInstr);
   5180    UInt  rS_addr = ifieldRegDS(theInstr);
   5181    UInt  rA_addr = ifieldRegA(theInstr);
   5182    UInt  uimm16  = ifieldUIMM16(theInstr);
   5183    UInt  rB_addr = ifieldRegB(theInstr);
   5184    UInt  opc2    = ifieldOPClo10(theInstr);
   5185    UChar b1      = ifieldBIT1(theInstr);
   5186    UChar b0      = ifieldBIT0(theInstr);
   5187 
   5188    Int    simm16 = extend_s_16to32(uimm16);
   5189    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   5190    IRTemp rS     = newTemp(ty);
   5191    IRTemp rB     = newTemp(ty);
   5192    IRTemp EA     = newTemp(ty);
   5193 
   5194    assign( rB, getIReg(rB_addr) );
   5195    assign( rS, getIReg(rS_addr) );
   5196 
   5197    switch (opc1) {
   5198    case 0x1F: // register offset
   5199       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   5200       break;
   5201    case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
   5202               // lowest 2 bits of immediate before forming EA
   5203       simm16 = simm16 & 0xFFFFFFFC;
   5204    default:   // immediate offset
   5205       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   5206       break;
   5207    }
   5208 
   5209    switch (opc1) {
   5210    case 0x26: // stb (Store B, PPC32 p509)
   5211       DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5212       store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5213       break;
   5214 
   5215    case 0x27: // stbu (Store B, Update, PPC32 p510)
   5216       if (rA_addr == 0 ) {
   5217          vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
   5218          return False;
   5219       }
   5220       DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5221       putIReg( rA_addr, mkexpr(EA) );
   5222       store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5223       break;
   5224 
   5225    case 0x2C: // sth (Store HW, PPC32 p522)
   5226       DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5227       store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5228       break;
   5229 
   5230    case 0x2D: // sthu (Store HW, Update, PPC32 p524)
   5231       if (rA_addr == 0) {
   5232          vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
   5233          return False;
   5234       }
   5235       DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5236       putIReg( rA_addr, mkexpr(EA) );
   5237       store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5238       break;
   5239 
   5240    case 0x24: // stw (Store W, PPC32 p530)
   5241       DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5242       store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5243       break;
   5244 
   5245    case 0x25: // stwu (Store W, Update, PPC32 p534)
   5246       if (rA_addr == 0) {
   5247          vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
   5248          return False;
   5249       }
   5250       DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5251       putIReg( rA_addr, mkexpr(EA) );
   5252       store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5253       break;
   5254 
   5255    /* X Form : all these use EA_indexed */
   5256    case 0x1F:
   5257       if (b0 != 0) {
   5258          vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
   5259          return False;
   5260       }
   5261 
   5262       switch (opc2) {
   5263       case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
   5264          if (rA_addr == 0) {
   5265             vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
   5266             return False;
   5267          }
   5268          DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5269          putIReg( rA_addr, mkexpr(EA) );
   5270          store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5271          break;
   5272 
   5273       case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
   5274          DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5275          store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5276          break;
   5277 
   5278       case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
   5279          if (rA_addr == 0) {
   5280             vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
   5281             return False;
   5282          }
   5283          DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5284          putIReg( rA_addr, mkexpr(EA) );
   5285          store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5286          break;
   5287 
   5288       case 0x197: // sthx (Store HW Indexed, PPC32 p526)
   5289          DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5290          store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5291          break;
   5292 
   5293       case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
   5294          if (rA_addr == 0) {
   5295             vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
   5296             return False;
   5297          }
   5298          DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5299          putIReg( rA_addr, mkexpr(EA) );
   5300          store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5301          break;
   5302 
   5303       case 0x097: // stwx (Store W Indexed, PPC32 p536)
   5304          DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5305          store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5306          break;
   5307 
   5308 
   5309       /* 64bit Stores */
   5310       case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
   5311          if (rA_addr == 0) {
   5312             vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
   5313             return False;
   5314          }
   5315          DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5316          putIReg( rA_addr, mkexpr(EA) );
   5317          store( mkexpr(EA), mkexpr(rS) );
   5318          break;
   5319 
   5320       case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
   5321          DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5322          store( mkexpr(EA), mkexpr(rS) );
   5323          break;
   5324 
   5325       default:
   5326          vex_printf("dis_int_store(ppc)(opc2)\n");
   5327          return False;
   5328       }
   5329       break;
   5330 
   5331    /* DS Form - 64bit Stores.  In each case EA will have been formed
   5332       with the lowest 2 bits masked off the immediate offset. */
   5333    case 0x3E:
   5334       switch ((b1<<1) | b0) {
   5335       case 0x0: // std (Store DWord, PPC64 p580)
   5336          if (!mode64)
   5337             return False;
   5338 
   5339          DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5340          store( mkexpr(EA), mkexpr(rS) );
   5341          break;
   5342 
   5343       case 0x1: // stdu (Store DWord, Update, PPC64 p583)
   5344          if (!mode64)
   5345             return False;
   5346 
   5347          DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5348          putIReg( rA_addr, mkexpr(EA) );
   5349          store( mkexpr(EA), mkexpr(rS) );
   5350          break;
   5351 
   5352       case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
   5353          IRTemp EA_hi = newTemp(ty);
   5354          IRTemp EA_lo = newTemp(ty);
   5355          DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5356 
   5357          if (mode64) {
   5358             if (host_endness == VexEndnessBE) {
   5359 
   5360                /* upper 64-bits */
   5361                assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
   5362 
   5363                /* lower 64-bits */
   5364                assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) );
   5365 	    } else {
   5366                /* upper 64-bits */
   5367                assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) );
   5368 
   5369                /* lower 64-bits */
   5370                assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) );
   5371 	    }
   5372          } else {
   5373             /* upper half of upper 64-bits */
   5374             assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) );
   5375 
   5376             /* lower half of upper 64-bits */
   5377             assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
   5378          }
   5379          store( mkexpr(EA_hi), mkexpr(rS) );
   5380          store( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
   5381          break;
   5382       }
   5383       default:
   5384          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   5385          return False;
   5386       }
   5387       break;
   5388 
   5389    default:
   5390       vex_printf("dis_int_store(ppc)(opc1)\n");
   5391       return False;
   5392    }
   5393    return True;
   5394 }
   5395 
   5396 
   5397 
   5398 /*
   5399   Integer Load/Store Multiple Instructions
   5400 */
   5401 static Bool dis_int_ldst_mult ( UInt theInstr )
   5402 {
   5403    /* D-Form */
   5404    UChar opc1     = ifieldOPC(theInstr);
   5405    UChar rD_addr  = ifieldRegDS(theInstr);
   5406    UChar rS_addr  = rD_addr;
   5407    UChar rA_addr  = ifieldRegA(theInstr);
   5408    UInt  uimm16   = ifieldUIMM16(theInstr);
   5409 
   5410    Int     simm16 = extend_s_16to32(uimm16);
   5411    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   5412    IROp    mkAdd  = mode64 ? Iop_Add64 : Iop_Add32;
   5413    IRTemp  EA     = newTemp(ty);
   5414    UInt    r      = 0;
   5415    UInt    ea_off = 0;
   5416    IRExpr* irx_addr;
   5417 
   5418    assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
   5419 
   5420    switch (opc1) {
   5421    case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
   5422       if (rA_addr >= rD_addr) {
   5423          vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
   5424          return False;
   5425       }
   5426       DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   5427       for (r = rD_addr; r <= 31; r++) {
   5428          irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
   5429          putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ),
   5430                                        False) );
   5431          ea_off += 4;
   5432       }
   5433       break;
   5434 
   5435    case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
   5436       DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5437       for (r = rS_addr; r <= 31; r++) {
   5438          irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
   5439          store( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
   5440          ea_off += 4;
   5441       }
   5442       break;
   5443 
   5444    default:
   5445       vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
   5446       return False;
   5447    }
   5448    return True;
   5449 }
   5450 
   5451 
   5452 
   5453 /*
   5454   Integer Load/Store String Instructions
   5455 */
   5456 static
   5457 void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   5458                              IRTemp EA,        // EA
   5459                              Int    rD,        // first dst register
   5460                              Int    maxBytes ) // 32 or 128
   5461 {
   5462    Int     i, shift = 24;
   5463    IRExpr* e_nbytes = mkexpr(tNBytes);
   5464    IRExpr* e_EA     = mkexpr(EA);
   5465    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   5466 
   5467    vassert(rD >= 0 && rD < 32);
   5468    rD--; if (rD < 0) rD = 31;
   5469 
   5470    for (i = 0; i < maxBytes; i++) {
   5471       /* if (nBytes < (i+1)) goto NIA; */
   5472       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   5473                          Ijk_Boring,
   5474                          mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
   5475       /* when crossing into a new dest register, set it to zero. */
   5476       if ((i % 4) == 0) {
   5477          rD++; if (rD == 32) rD = 0;
   5478          putIReg(rD, mkSzImm(ty, 0));
   5479          shift = 24;
   5480       }
   5481       /* rD |=  (8Uto32(*(EA+i))) << shift */
   5482       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   5483       putIReg(
   5484          rD,
   5485          mkWidenFrom32(
   5486             ty,
   5487             binop(
   5488                Iop_Or32,
   5489                mkNarrowTo32(ty, getIReg(rD)),
   5490                binop(
   5491                   Iop_Shl32,
   5492                   unop(
   5493                      Iop_8Uto32,
   5494                      load( Ity_I8,
   5495                            binop( mkSzOp(ty,Iop_Add8),
   5496                                   e_EA, mkSzImm(ty,i)))
   5497                   ),
   5498                   mkU8(toUChar(shift))
   5499                )
   5500             ),
   5501             /*Signed*/False
   5502 	 )
   5503       );
   5504       shift -= 8;
   5505    }
   5506 }
   5507 
   5508 static
   5509 void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   5510                               IRTemp EA,        // EA
   5511                               Int    rS,        // first src register
   5512                               Int    maxBytes ) // 32 or 128
   5513 {
   5514    Int     i, shift = 24;
   5515    IRExpr* e_nbytes = mkexpr(tNBytes);
   5516    IRExpr* e_EA     = mkexpr(EA);
   5517    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   5518 
   5519    vassert(rS >= 0 && rS < 32);
   5520    rS--; if (rS < 0) rS = 31;
   5521 
   5522    for (i = 0; i < maxBytes; i++) {
   5523       /* if (nBytes < (i+1)) goto NIA; */
   5524       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   5525                          Ijk_Boring,
   5526                          mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
   5527       /* check for crossing into a new src register. */
   5528       if ((i % 4) == 0) {
   5529          rS++; if (rS == 32) rS = 0;
   5530          shift = 24;
   5531       }
   5532       /* *(EA+i) = 32to8(rS >> shift) */
   5533       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   5534       store(
   5535             binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
   5536             unop( Iop_32to8,
   5537                   binop( Iop_Shr32,
   5538                          mkNarrowTo32( ty, getIReg(rS) ),
   5539                          mkU8( toUChar(shift) )))
   5540       );
   5541       shift -= 8;
   5542    }
   5543 }
   5544 
   5545 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
   5546 {
   5547    /* X-Form */
   5548    UChar opc1     = ifieldOPC(theInstr);
   5549    UChar rD_addr  = ifieldRegDS(theInstr);
   5550    UChar rS_addr  = rD_addr;
   5551    UChar rA_addr  = ifieldRegA(theInstr);
   5552    UChar rB_addr  = ifieldRegB(theInstr);
   5553    UChar NumBytes = rB_addr;
   5554    UInt  opc2     = ifieldOPClo10(theInstr);
   5555    UChar b0       = ifieldBIT0(theInstr);
   5556 
   5557    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   5558    IRTemp t_EA    = newTemp(ty);
   5559    IRTemp t_nbytes = IRTemp_INVALID;
   5560 
   5561    *stopHere = False;
   5562 
   5563    if (opc1 != 0x1F || b0 != 0) {
   5564       vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
   5565       return False;
   5566    }
   5567 
   5568    switch (opc2) {
   5569    case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
   5570       /* NB: does not reject the case where RA is in the range of
   5571          registers to be loaded.  It should. */
   5572       DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
   5573       assign( t_EA, ea_rAor0(rA_addr) );
   5574       if (NumBytes == 8 && !mode64) {
   5575          /* Special case hack */
   5576          /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
   5577          putIReg( rD_addr,
   5578                   load(Ity_I32, mkexpr(t_EA)) );
   5579          putIReg( (rD_addr+1) % 32,
   5580                   load(Ity_I32,
   5581                        binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
   5582       } else {
   5583          t_nbytes = newTemp(Ity_I32);
   5584          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   5585          generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   5586          *stopHere = True;
   5587       }
   5588       return True;
   5589 
   5590    case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
   5591       /* NB: does not reject the case where RA is in the range of
   5592          registers to be loaded.  It should.  Although considering
   5593          that that can only be detected at run time, it's not easy to
   5594          do so. */
   5595       if (rD_addr == rA_addr || rD_addr == rB_addr)
   5596          return False;
   5597       if (rD_addr == 0 && rA_addr == 0)
   5598          return False;
   5599       DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5600       t_nbytes = newTemp(Ity_I32);
   5601       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   5602       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   5603       generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
   5604       *stopHere = True;
   5605       return True;
   5606 
   5607    case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
   5608       DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
   5609       assign( t_EA, ea_rAor0(rA_addr) );
   5610       if (NumBytes == 8 && !mode64) {
   5611          /* Special case hack */
   5612          /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
   5613          store( mkexpr(t_EA),
   5614                 getIReg(rD_addr) );
   5615          store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
   5616                 getIReg((rD_addr+1) % 32) );
   5617       } else {
   5618          t_nbytes = newTemp(Ity_I32);
   5619          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   5620          generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   5621          *stopHere = True;
   5622       }
   5623       return True;
   5624 
   5625    case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
   5626       DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5627       t_nbytes = newTemp(Ity_I32);
   5628       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   5629       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   5630       generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
   5631       *stopHere = True;
   5632       return True;
   5633 
   5634    default:
   5635       vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
   5636       return False;
   5637    }
   5638    return True;
   5639 }
   5640 
   5641 
   5642 /* ------------------------------------------------------------------
   5643    Integer Branch Instructions
   5644    ------------------------------------------------------------------ */
   5645 
   5646 /*
   5647   Branch helper function
   5648   ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
   5649   Returns an I32 which is 0x00000000 if the ctr condition failed
   5650   and 0xFFFFFFFF otherwise.
   5651 */
   5652 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
   5653 {
   5654    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   5655    IRTemp ok = newTemp(Ity_I32);
   5656 
   5657    if ((BO >> 2) & 1) {     // independent of ctr
   5658       assign( ok, mkU32(0xFFFFFFFF) );
   5659    } else {
   5660       if ((BO >> 1) & 1) {  // ctr == 0 ?
   5661          assign( ok, unop( Iop_1Sto32,
   5662                            binop( mkSzOp(ty, Iop_CmpEQ8),
   5663                                   getGST( PPC_GST_CTR ),
   5664                                   mkSzImm(ty,0))) );
   5665       } else {              // ctr != 0 ?
   5666          assign( ok, unop( Iop_1Sto32,
   5667                            binop( mkSzOp(ty, Iop_CmpNE8),
   5668                                   getGST( PPC_GST_CTR ),
   5669                                   mkSzImm(ty,0))) );
   5670       }
   5671    }
   5672    return mkexpr(ok);
   5673 }
   5674 
   5675 
   5676 /*
   5677   Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
   5678   Returns an I32 which is either 0 if the condition failed or
   5679   some arbitrary nonzero value otherwise. */
   5680 
   5681 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
   5682 {
   5683    Int where;
   5684    IRTemp res   = newTemp(Ity_I32);
   5685    IRTemp cr_bi = newTemp(Ity_I32);
   5686 
   5687    if ((BO >> 4) & 1) {
   5688       assign( res, mkU32(1) );
   5689    } else {
   5690       // ok = (CR[BI] == BO[3]) Note, the following relies on
   5691       // getCRbit_anywhere returning a value which
   5692       // is either zero or has exactly 1 bit set.
   5693       assign( cr_bi, getCRbit_anywhere( BI, &where ) );
   5694 
   5695       if ((BO >> 3) & 1) {
   5696          /* We can use cr_bi as-is. */
   5697          assign( res, mkexpr(cr_bi) );
   5698       } else {
   5699          /* We have to invert the sense of the information held in
   5700             cr_bi.  For that we need to know which bit
   5701             getCRbit_anywhere regards as significant. */
   5702          assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
   5703                                        mkU32(1<<where)) );
   5704       }
   5705    }
   5706    return mkexpr(res);
   5707 }
   5708 
   5709 
   5710 /*
   5711   Integer Branch Instructions
   5712 */
   5713 static Bool dis_branch ( UInt theInstr,
   5714                          const VexAbiInfo* vbi,
   5715                          /*OUT*/DisResult* dres,
   5716                          Bool (*resteerOkFn)(void*,Addr),
   5717                          void* callback_opaque )
   5718 {
   5719    UChar opc1    = ifieldOPC(theInstr);
   5720    UChar BO      = ifieldRegDS(theInstr);
   5721    UChar BI      = ifieldRegA(theInstr);
   5722    UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
   5723    UChar b11to15 = ifieldRegB(theInstr);
   5724    UInt  opc2    = ifieldOPClo10(theInstr);
   5725    UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
   5726    UChar flag_AA = ifieldBIT1(theInstr);
   5727    UChar flag_LK = ifieldBIT0(theInstr);
   5728 
   5729    IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
   5730    Addr64   tgt       = 0;
   5731    Int      BD        = extend_s_16to32(BD_u16);
   5732    IRTemp   do_branch = newTemp(Ity_I32);
   5733    IRTemp   ctr_ok    = newTemp(Ity_I32);
   5734    IRTemp   cond_ok   = newTemp(Ity_I32);
   5735    IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
   5736    IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
   5737    IRTemp   lr_old    = newTemp(ty);
   5738 
   5739    /* Hack to pass through code that just wants to read the PC */
   5740    if (theInstr == 0x429F0005) {
   5741       DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
   5742       putGST( PPC_GST_LR, e_nia );
   5743       return True;
   5744    }
   5745 
   5746    /* The default what-next.  Individual cases can override it. */
   5747    dres->whatNext = Dis_StopHere;
   5748    vassert(dres->jk_StopHere == Ijk_INVALID);
   5749 
   5750    switch (opc1) {
   5751    case 0x12: // b     (Branch, PPC32 p360)
   5752       if (flag_AA) {
   5753          tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
   5754       } else {
   5755          tgt = mkSzAddr( ty, guest_CIA_curr_instr +
   5756                              (Long)extend_s_26to64(LI_u26) );
   5757       }
   5758       if (mode64) {
   5759          DIP("b%s%s 0x%llx\n",
   5760              flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
   5761       } else {
   5762          DIP("b%s%s 0x%x\n",
   5763              flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
   5764       }
   5765 
   5766       if (flag_LK) {
   5767          putGST( PPC_GST_LR, e_nia );
   5768          if (vbi->guest_ppc_zap_RZ_at_bl
   5769              && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
   5770             IRTemp t_tgt = newTemp(ty);
   5771             assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
   5772             make_redzone_AbiHint( vbi, t_tgt,
   5773                                   "branch-and-link (unconditional call)" );
   5774          }
   5775       }
   5776 
   5777       if (resteerOkFn( callback_opaque, tgt )) {
   5778          dres->whatNext   = Dis_ResteerU;
   5779          dres->continueAt = tgt;
   5780       } else {
   5781          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
   5782          putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
   5783       }
   5784       break;
   5785 
   5786    case 0x10: // bc    (Branch Conditional, PPC32 p361)
   5787       DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
   5788           flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
   5789 
   5790       if (!(BO & 0x4)) {
   5791          putGST( PPC_GST_CTR,
   5792                  binop(mkSzOp(ty, Iop_Sub8),
   5793                        getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   5794       }
   5795 
   5796       /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
   5797          cond_ok is either zero or nonzero, since that's the cheapest
   5798          way to compute it.  Anding them together gives a value which
   5799          is either zero or non zero and so that's what we must test
   5800          for in the IRStmt_Exit. */
   5801       assign( ctr_ok,  branch_ctr_ok( BO ) );
   5802       assign( cond_ok, branch_cond_ok( BO, BI ) );
   5803       assign( do_branch,
   5804               binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   5805 
   5806       if (flag_AA) {
   5807          tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
   5808       } else {
   5809          tgt = mkSzAddr(ty, guest_CIA_curr_instr +
   5810                             (Long)extend_s_16to64(BD_u16));
   5811       }
   5812       if (flag_LK)
   5813          putGST( PPC_GST_LR, e_nia );
   5814 
   5815       stmt( IRStmt_Exit(
   5816                binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
   5817                flag_LK ? Ijk_Call : Ijk_Boring,
   5818                mkSzConst(ty, tgt), OFFB_CIA ) );
   5819 
   5820       dres->jk_StopHere = Ijk_Boring;
   5821       putGST( PPC_GST_CIA, e_nia );
   5822       break;
   5823 
   5824    case 0x13:
   5825       /* For bclr and bcctr, it appears that the lowest two bits of
   5826          b11to15 are a branch hint, and so we only need to ensure it's
   5827          of the form 000XX. */
   5828       if ((b11to15 & ~3) != 0) {
   5829          vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15);
   5830          return False;
   5831       }
   5832 
   5833       switch (opc2) {
   5834       case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
   5835          if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
   5836             vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
   5837             return False;
   5838          }
   5839          DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   5840 
   5841          assign( cond_ok, branch_cond_ok( BO, BI ) );
   5842 
   5843          /* FIXME: this is confusing.  lr_old holds the old value
   5844             of ctr, not lr :-) */
   5845          assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
   5846 
   5847          if (flag_LK)
   5848             putGST( PPC_GST_LR, e_nia );
   5849 
   5850          stmt( IRStmt_Exit(
   5851                   binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
   5852                   Ijk_Boring,
   5853                   c_nia, OFFB_CIA ));
   5854 
   5855          if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
   5856             make_redzone_AbiHint( vbi, lr_old,
   5857                                   "b-ctr-l (indirect call)" );
   5858 	 }
   5859 
   5860          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
   5861          putGST( PPC_GST_CIA, mkexpr(lr_old) );
   5862          break;
   5863 
   5864       case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
   5865          Bool vanilla_return = False;
   5866          if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
   5867             DIP("blr\n");
   5868             vanilla_return = True;
   5869          } else {
   5870             DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   5871          }
   5872 
   5873          if (!(BO & 0x4)) {
   5874             putGST( PPC_GST_CTR,
   5875                     binop(mkSzOp(ty, Iop_Sub8),
   5876                           getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   5877          }
   5878 
   5879          /* See comments above for 'bc' about this */
   5880          assign( ctr_ok,  branch_ctr_ok( BO ) );
   5881          assign( cond_ok, branch_cond_ok( BO, BI ) );
   5882          assign( do_branch,
   5883                  binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   5884 
   5885          assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
   5886 
   5887          if (flag_LK)
   5888             putGST( PPC_GST_LR,  e_nia );
   5889 
   5890          stmt( IRStmt_Exit(
   5891                   binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
   5892                   Ijk_Boring,
   5893                   c_nia, OFFB_CIA ));
   5894 
   5895          if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
   5896             make_redzone_AbiHint( vbi, lr_old,
   5897                                   "branch-to-lr (unconditional return)" );
   5898          }
   5899 
   5900          /* blrl is pretty strange; it's like a return that sets the
   5901             return address of its caller to the insn following this
   5902             one.  Mark it as a return. */
   5903          dres->jk_StopHere = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
   5904          putGST( PPC_GST_CIA, mkexpr(lr_old) );
   5905          break;
   5906       }
   5907       default:
   5908          vex_printf("dis_int_branch(ppc)(opc2)\n");
   5909          return False;
   5910       }
   5911       break;
   5912 
   5913    default:
   5914       vex_printf("dis_int_branch(ppc)(opc1)\n");
   5915       return False;
   5916    }
   5917 
   5918    return True;
   5919 }
   5920 
   5921 
   5922 
   5923 /*
   5924   Condition Register Logical Instructions
   5925 */
   5926 static Bool dis_cond_logic ( UInt theInstr )
   5927 {
   5928    /* XL-Form */
   5929    UChar opc1      = ifieldOPC(theInstr);
   5930    UChar crbD_addr = ifieldRegDS(theInstr);
   5931    UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
   5932    UChar crbA_addr = ifieldRegA(theInstr);
   5933    UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
   5934    UChar crbB_addr = ifieldRegB(theInstr);
   5935    UInt  opc2      = ifieldOPClo10(theInstr);
   5936    UChar b0        = ifieldBIT0(theInstr);
   5937 
   5938    IRTemp crbD     = newTemp(Ity_I32);
   5939    IRTemp crbA     = newTemp(Ity_I32);
   5940    IRTemp crbB     = newTemp(Ity_I32);
   5941 
   5942    if (opc1 != 19 || b0 != 0) {
   5943       vex_printf("dis_cond_logic(ppc)(opc1)\n");
   5944       return False;
   5945    }
   5946 
   5947    if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
   5948       if (((crbD_addr & 0x3) != 0) ||
   5949           ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
   5950          vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
   5951          return False;
   5952       }
   5953       DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
   5954       putCR0(   crfD_addr, getCR0(  crfS_addr) );
   5955       putCR321( crfD_addr, getCR321(crfS_addr) );
   5956    } else {
   5957       assign( crbA, getCRbit(crbA_addr) );
   5958       if (crbA_addr == crbB_addr)
   5959          crbB = crbA;
   5960       else
   5961          assign( crbB, getCRbit(crbB_addr) );
   5962 
   5963       switch (opc2) {
   5964       case 0x101: // crand   (Cond Reg AND, PPC32 p372)
   5965          DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5966          assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
   5967          break;
   5968       case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
   5969          DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5970          assign( crbD, binop(Iop_And32,
   5971                              mkexpr(crbA),
   5972                              unop(Iop_Not32, mkexpr(crbB))) );
   5973          break;
   5974       case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
   5975          DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5976          assign( crbD, unop(Iop_Not32,
   5977                             binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
   5978          break;
   5979       case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
   5980          DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5981          assign( crbD, unop(Iop_Not32,
   5982                             binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
   5983          break;
   5984       case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
   5985          DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5986          assign( crbD, unop(Iop_Not32,
   5987                             binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
   5988          break;
   5989       case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
   5990          DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5991          assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
   5992          break;
   5993       case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
   5994          DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5995          assign( crbD, binop(Iop_Or32,
   5996                              mkexpr(crbA),
   5997                              unop(Iop_Not32, mkexpr(crbB))) );
   5998          break;
   5999       case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
   6000          DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   6001          assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
   6002          break;
   6003       default:
   6004          vex_printf("dis_cond_logic(ppc)(opc2)\n");
   6005          return False;
   6006       }
   6007 
   6008       putCRbit( crbD_addr, mkexpr(crbD) );
   6009    }
   6010    return True;
   6011 }
   6012 
   6013 
   6014 /*
   6015   Trap instructions
   6016 */
   6017 
   6018 /* Do the code generation for a trap.  Returned Bool is true iff
   6019    this is an unconditional trap.  If the two arg IRExpr*s are
   6020    Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
   6021    then they are 64-bit, and we must be disassembling 64-bit
   6022    instructions. */
   6023 static Bool do_trap ( UChar TO,
   6024                       IRExpr* argL0, IRExpr* argR0, Addr64 cia )
   6025 {
   6026    IRTemp argL, argR;
   6027    IRExpr *argLe, *argRe, *cond, *tmp;
   6028 
   6029    Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
   6030 
   6031    IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
   6032    IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
   6033    IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
   6034    IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
   6035    IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
   6036    IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
   6037    IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
   6038    IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
   6039    IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
   6040    IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
   6041 
   6042    const UChar b11100 = 0x1C;
   6043    const UChar b00111 = 0x07;
   6044 
   6045    if (is32bit) {
   6046       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
   6047       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
   6048    } else {
   6049       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
   6050       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
   6051       vassert( mode64 );
   6052    }
   6053 
   6054    if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
   6055       /* Unconditional trap.  Just do the exit without
   6056          testing the arguments. */
   6057       stmt( IRStmt_Exit(
   6058                binop(opCMPEQ, const0, const0),
   6059                Ijk_SigTRAP,
   6060                mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
   6061                OFFB_CIA
   6062       ));
   6063       return True; /* unconditional trap */
   6064    }
   6065 
   6066    if (is32bit) {
   6067       argL = newTemp(Ity_I32);
   6068       argR = newTemp(Ity_I32);
   6069    } else {
   6070       argL = newTemp(Ity_I64);
   6071       argR = newTemp(Ity_I64);
   6072    }
   6073 
   6074    assign( argL, argL0 );
   6075    assign( argR, argR0 );
   6076 
   6077    argLe = mkexpr(argL);
   6078    argRe = mkexpr(argR);
   6079 
   6080    cond = const0;
   6081    if (TO & 16) { // L <s R
   6082       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
   6083       cond = binop(opOR, tmp, cond);
   6084    }
   6085    if (TO & 8) { // L >s R
   6086       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
   6087       cond = binop(opOR, tmp, cond);
   6088    }
   6089    if (TO & 4) { // L == R
   6090       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
   6091       cond = binop(opOR, tmp, cond);
   6092    }
   6093    if (TO & 2) { // L <u R
   6094       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
   6095       cond = binop(opOR, tmp, cond);
   6096    }
   6097    if (TO & 1) { // L >u R
   6098       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
   6099       cond = binop(opOR, tmp, cond);
   6100    }
   6101    stmt( IRStmt_Exit(
   6102             binop(opCMPNE, cond, const0),
   6103             Ijk_SigTRAP,
   6104             mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
   6105             OFFB_CIA
   6106    ));
   6107    return False; /* not an unconditional trap */
   6108 }
   6109 
   6110 static Bool dis_trapi ( UInt theInstr,
   6111                         /*OUT*/DisResult* dres )
   6112 {
   6113    /* D-Form */
   6114    UChar  opc1    = ifieldOPC(theInstr);
   6115    UChar  TO      = ifieldRegDS(theInstr);
   6116    UChar  rA_addr = ifieldRegA(theInstr);
   6117    UInt   uimm16  = ifieldUIMM16(theInstr);
   6118    ULong  simm16  = extend_s_16to64(uimm16);
   6119    Addr64 cia     = guest_CIA_curr_instr;
   6120    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   6121    Bool   uncond  = False;
   6122 
   6123    switch (opc1) {
   6124    case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
   6125       uncond = do_trap( TO,
   6126                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   6127                                : getIReg(rA_addr),
   6128                         mkU32( (UInt)simm16 ),
   6129                         cia );
   6130       if (TO == 4) {
   6131          DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
   6132       } else {
   6133          DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
   6134       }
   6135       break;
   6136    case 0x02: // tdi
   6137       if (!mode64)
   6138          return False;
   6139       uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
   6140       if (TO == 4) {
   6141          DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
   6142       } else {
   6143          DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
   6144       }
   6145       break;
   6146    default:
   6147       return False;
   6148    }
   6149 
   6150    if (uncond) {
   6151       /* If the trap shows signs of being unconditional, don't
   6152          continue decoding past it. */
   6153       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
   6154       dres->jk_StopHere = Ijk_Boring;
   6155       dres->whatNext    = Dis_StopHere;
   6156    }
   6157 
   6158    return True;
   6159 }
   6160 
   6161 static Bool dis_trap ( UInt theInstr,
   6162                         /*OUT*/DisResult* dres )
   6163 {
   6164    /* X-Form */
   6165    UInt   opc2    = ifieldOPClo10(theInstr);
   6166    UChar  TO      = ifieldRegDS(theInstr);
   6167    UChar  rA_addr = ifieldRegA(theInstr);
   6168    UChar  rB_addr = ifieldRegB(theInstr);
   6169    Addr64 cia     = guest_CIA_curr_instr;
   6170    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   6171    Bool   uncond  = False;
   6172 
   6173    if (ifieldBIT0(theInstr) != 0)
   6174       return False;
   6175 
   6176    switch (opc2) {
   6177    case 0x004: // tw  (Trap Word, PPC64 p540)
   6178       uncond = do_trap( TO,
   6179                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   6180                                : getIReg(rA_addr),
   6181                         mode64 ? unop(Iop_64to32, getIReg(rB_addr))
   6182                                : getIReg(rB_addr),
   6183                         cia );
   6184       if (TO == 4) {
   6185          DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
   6186       } else {
   6187          DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
   6188       }
   6189       break;
   6190    case 0x044: // td (Trap Doubleword, PPC64 p534)
   6191       if (!mode64)
   6192          return False;
   6193       uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
   6194       if (TO == 4) {
   6195          DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
   6196       } else {
   6197          DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
   6198       }
   6199       break;
   6200    default:
   6201       return False;
   6202    }
   6203 
   6204    if (uncond) {
   6205       /* If the trap shows signs of being unconditional, don't
   6206          continue decoding past it. */
   6207       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
   6208       dres->jk_StopHere = Ijk_Boring;
   6209       dres->whatNext    = Dis_StopHere;
   6210    }
   6211 
   6212    return True;
   6213 }
   6214 
   6215 
   6216 /*
   6217   System Linkage Instructions
   6218 */
   6219 static Bool dis_syslink ( UInt theInstr,
   6220                           const VexAbiInfo* abiinfo, DisResult* dres )
   6221 {
   6222    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   6223 
   6224    if (theInstr != 0x44000002) {
   6225       vex_printf("dis_syslink(ppc)(theInstr)\n");
   6226       return False;
   6227    }
   6228 
   6229    // sc  (System Call, PPC32 p504)
   6230    DIP("sc\n");
   6231 
   6232    /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
   6233       Valgrind can back the guest up to this instruction if it needs
   6234       to restart the syscall. */
   6235    putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
   6236 
   6237    /* It's important that all ArchRegs carry their up-to-date value
   6238       at this point.  So we declare an end-of-block here, which
   6239       forces any TempRegs caching ArchRegs to be flushed. */
   6240    putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
   6241 
   6242    dres->whatNext    = Dis_StopHere;
   6243    dres->jk_StopHere = Ijk_Sys_syscall;
   6244    return True;
   6245 }
   6246 
   6247 
   6248 /*
   6249   Memory Synchronization Instructions
   6250 
   6251   Note on Reservations:
   6252   We rely on the assumption that V will in fact only allow one thread at
   6253   once to run.  In effect, a thread can make a reservation, but we don't
   6254   check any stores it does.  Instead, the reservation is cancelled when
   6255   the scheduler switches to another thread (run_thread_for_a_while()).
   6256 */
   6257 static Bool dis_memsync ( UInt theInstr )
   6258 {
   6259    /* X-Form, XL-Form */
   6260    UChar opc1    = ifieldOPC(theInstr);
   6261    UInt  b11to25 = IFIELD(theInstr, 11, 15);
   6262    UChar flag_L  = ifieldRegDS(theInstr);
   6263    UInt  b11to20 = IFIELD(theInstr, 11, 10);
   6264    UChar rD_addr = ifieldRegDS(theInstr);
   6265    UChar rS_addr = rD_addr;
   6266    UChar rA_addr = ifieldRegA(theInstr);
   6267    UChar rB_addr = ifieldRegB(theInstr);
   6268    UInt  opc2    = ifieldOPClo10(theInstr);
   6269    UChar b0      = ifieldBIT0(theInstr);
   6270 
   6271    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   6272    IRTemp EA     = newTemp(ty);
   6273 
   6274    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   6275 
   6276    switch (opc1) {
   6277    /* XL-Form */
   6278    case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
   6279       if (opc2 != 0x096) {
   6280          vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
   6281          return False;
   6282       }
   6283       if (b11to25 != 0 || b0 != 0) {
   6284          vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
   6285          return False;
   6286       }
   6287       DIP("isync\n");
   6288       stmt( IRStmt_MBE(Imbe_Fence) );
   6289       break;
   6290 
   6291    /* X-Form */
   6292    case 0x1F:
   6293       switch (opc2) {
   6294       case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394)
   6295          if (b11to25 != 0 || b0 != 0) {
   6296             vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n");
   6297             return False;
   6298          }
   6299          DIP("eieio\n");
   6300          /* Insert a memory fence, just to be on the safe side. */
   6301          stmt( IRStmt_MBE(Imbe_Fence) );
   6302          break;
   6303 
   6304       case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
   6305          IRTemp res;
   6306          /* According to the PowerPC ISA version 2.05, b0 (called EH
   6307             in the documentation) is merely a hint bit to the
   6308             hardware, I think as to whether or not contention is
   6309             likely.  So we can just ignore it. */
   6310          DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   6311 
   6312          // trap if misaligned
   6313          gen_SIGBUS_if_misaligned( EA, 4 );
   6314 
   6315          // and actually do the load
   6316          res = newTemp(Ity_I32);
   6317          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
   6318 
   6319          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
   6320          break;
   6321       }
   6322 
   6323       case 0x034: { // lbarx (Load Word and Reserve Indexed)
   6324          IRTemp res;
   6325          /* According to the PowerPC ISA version 2.05, b0 (called EH
   6326             in the documentation) is merely a hint bit to the
   6327             hardware, I think as to whether or not contention is
   6328             likely.  So we can just ignore it. */
   6329          DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   6330 
   6331          // and actually do the load
   6332          res = newTemp(Ity_I8);
   6333          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
   6334 
   6335          putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) );
   6336          break;
   6337      }
   6338 
   6339       case 0x074: { // lharx (Load Word and Reserve Indexed)
   6340          IRTemp res;
   6341          /* According to the PowerPC ISA version 2.05, b0 (called EH
   6342             in the documentation) is merely a hint bit to the
   6343             hardware, I think as to whether or not contention is
   6344             likely.  So we can just ignore it. */
   6345          DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   6346 
   6347          // trap if misaligned
   6348          gen_SIGBUS_if_misaligned( EA, 2 );
   6349 
   6350          // and actually do the load
   6351          res = newTemp(Ity_I16);
   6352          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
   6353 
   6354          putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) );
   6355          break;
   6356       }
   6357 
   6358       case 0x096: {
   6359          // stwcx. (Store Word Conditional Indexed, PPC32 p532)
   6360          // Note this has to handle stwcx. in both 32- and 64-bit modes,
   6361          // so isn't quite as straightforward as it might otherwise be.
   6362          IRTemp rS = newTemp(Ity_I32);
   6363          IRTemp resSC;
   6364          if (b0 != 1) {
   6365             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
   6366             return False;
   6367          }
   6368          DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6369 
   6370          // trap if misaligned
   6371          gen_SIGBUS_if_misaligned( EA, 4 );
   6372 
   6373          // Get the data to be stored, and narrow to 32 bits if necessary
   6374          assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
   6375 
   6376          // Do the store, and get success/failure bit into resSC
   6377          resSC = newTemp(Ity_I1);
   6378          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
   6379 
   6380          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6381          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6382          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   6383          putCR0(0, getXER_SO());
   6384 
   6385          /* Note:
   6386             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   6387             whether rS is stored is dependent on that value. */
   6388          /* So I guess we can just ignore this case? */
   6389          break;
   6390       }
   6391 
   6392       case 0x2B6: {
   6393          // stbcx. (Store Byte Conditional Indexed)
   6394          // Note this has to handle stbcx. in both 32- and 64-bit modes,
   6395          // so isn't quite as straightforward as it might otherwise be.
   6396          IRTemp rS = newTemp(Ity_I8);
   6397          IRTemp resSC;
   6398          if (b0 != 1) {
   6399             vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
   6400             return False;
   6401          }
   6402          DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6403 
   6404          // Get the data to be stored, and narrow to 32 bits if necessary
   6405          assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) );
   6406 
   6407          // Do the store, and get success/failure bit into resSC
   6408          resSC = newTemp(Ity_I1);
   6409          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
   6410 
   6411          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6412          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6413          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   6414          putCR0(0, getXER_SO());
   6415 
   6416          /* Note:
   6417             If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and
   6418             whether rS is stored is dependent on that value. */
   6419          /* So I guess we can just ignore this case? */
   6420          break;
   6421       }
   6422 
   6423       case 0x2D6: {
   6424          // sthcx. (Store Word Conditional Indexed, PPC32 p532)
   6425          // Note this has to handle sthcx. in both 32- and 64-bit modes,
   6426          // so isn't quite as straightforward as it might otherwise be.
   6427          IRTemp rS = newTemp(Ity_I16);
   6428          IRTemp resSC;
   6429          if (b0 != 1) {
   6430             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
   6431             return False;
   6432          }
   6433          DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6434 
   6435          // trap if misaligned
   6436          gen_SIGBUS_if_misaligned( EA, 2 );
   6437 
   6438          // Get the data to be stored, and narrow to 16 bits if necessary
   6439          assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) );
   6440 
   6441          // Do the store, and get success/failure bit into resSC
   6442          resSC = newTemp(Ity_I1);
   6443          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
   6444 
   6445          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6446          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6447          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   6448          putCR0(0, getXER_SO());
   6449 
   6450          /* Note:
   6451             If resaddr != lharx_resaddr, CR0[EQ] is undefined, and
   6452             whether rS is stored is dependent on that value. */
   6453          /* So I guess we can just ignore this case? */
   6454          break;
   6455       }
   6456 
   6457       case 0x256: // sync (Synchronize, PPC32 p543),
   6458                   // also lwsync (L==1), ptesync (L==2)
   6459          /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
   6460 
   6461             The PowerPC architecture used in IBM chips has expanded
   6462             the sync instruction into two variants: lightweight sync
   6463             and heavyweight sync.  The original sync instruction is
   6464             the new heavyweight sync and lightweight sync is a strict
   6465             subset of the heavyweight sync functionality. This allows
   6466             the programmer to specify a less expensive operation on
   6467             high-end systems when the full sync functionality is not
   6468             necessary.
   6469 
   6470             The basic "sync" mnemonic now utilizes an operand. "sync"
   6471             without an operand now becomes a extended mnemonic for
   6472             heavyweight sync.  Processors without the lwsync
   6473             instruction will not decode the L field and will perform a
   6474             heavyweight sync.  Everything is backward compatible.
   6475 
   6476             sync    =       sync 0
   6477             lwsync  =       sync 1
   6478             ptesync =       sync 2    *** TODO - not implemented ***
   6479          */
   6480          if (b11to20 != 0 || b0 != 0) {
   6481             vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
   6482             return False;
   6483          }
   6484          if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
   6485             vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
   6486             return False;
   6487          }
   6488          DIP("%ssync\n", flag_L == 1 ? "lw" : "");
   6489          /* Insert a memory fence.  It's sometimes important that these
   6490             are carried through to the generated code. */
   6491          stmt( IRStmt_MBE(Imbe_Fence) );
   6492          break;
   6493 
   6494       /* 64bit Memsync */
   6495       case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
   6496          IRTemp res;
   6497          /* According to the PowerPC ISA version 2.05, b0 (called EH
   6498             in the documentation) is merely a hint bit to the
   6499             hardware, I think as to whether or not contention is
   6500             likely.  So we can just ignore it. */
   6501          if (!mode64)
   6502             return False;
   6503          DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   6504 
   6505          // trap if misaligned
   6506          gen_SIGBUS_if_misaligned( EA, 8 );
   6507 
   6508          // and actually do the load
   6509          res = newTemp(Ity_I64);
   6510          stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) );
   6511 
   6512          putIReg( rD_addr, mkexpr(res) );
   6513          break;
   6514       }
   6515 
   6516       case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
   6517          // A marginally simplified version of the stwcx. case
   6518          IRTemp rS = newTemp(Ity_I64);
   6519          IRTemp resSC;
   6520          if (b0 != 1) {
   6521             vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
   6522             return False;
   6523          }
   6524          if (!mode64)
   6525             return False;
   6526          DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6527 
   6528          // trap if misaligned
   6529          gen_SIGBUS_if_misaligned( EA, 8 );
   6530 
   6531          // Get the data to be stored
   6532          assign( rS, getIReg(rS_addr) );
   6533 
   6534          // Do the store, and get success/failure bit into resSC
   6535          resSC = newTemp(Ity_I1);
   6536          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
   6537 
   6538          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6539          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6540          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   6541          putCR0(0, getXER_SO());
   6542 
   6543          /* Note:
   6544             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   6545             whether rS is stored is dependent on that value. */
   6546          /* So I guess we can just ignore this case? */
   6547          break;
   6548       }
   6549 
   6550       /* 128bit Memsync */
   6551       case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
   6552          IRTemp res_hi = newTemp(ty);
   6553          IRTemp res_lo = newTemp(ty);
   6554 
   6555          /* According to the PowerPC ISA version 2.07, b0 (called EH
   6556             in the documentation) is merely a hint bit to the
   6557             hardware, I think as to whether or not contention is
   6558             likely.  So we can just ignore it. */
   6559          DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   6560 
   6561          // trap if misaligned
   6562          gen_SIGBUS_if_misaligned( EA, 16 );
   6563 
   6564          // and actually do the load
   6565          if (mode64) {
   6566             if (host_endness == VexEndnessBE) {
   6567                stmt( stmt_load( res_hi,
   6568                                 mkexpr(EA), NULL/*this is a load*/) );
   6569                stmt( stmt_load( res_lo,
   6570                                 binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
   6571                                 NULL/*this is a load*/) );
   6572 	    } else {
   6573                stmt( stmt_load( res_lo,
   6574                                 mkexpr(EA), NULL/*this is a load*/) );
   6575                stmt( stmt_load( res_hi,
   6576                                 binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
   6577                                 NULL/*this is a load*/) );
   6578             }
   6579          } else {
   6580             stmt( stmt_load( res_hi,
   6581                              binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
   6582                              NULL/*this is a load*/) );
   6583             stmt( stmt_load( res_lo,
   6584                              binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
   6585                              NULL/*this is a load*/) );
   6586          }
   6587          putIReg( rD_addr,   mkexpr(res_hi) );
   6588          putIReg( rD_addr+1, mkexpr(res_lo) );
   6589          break;
   6590       }
   6591 
   6592       case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
   6593          // A marginally simplified version of the stwcx. case
   6594          IRTemp rS_hi = newTemp(ty);
   6595          IRTemp rS_lo = newTemp(ty);
   6596          IRTemp resSC;
   6597          if (b0 != 1) {
   6598             vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
   6599             return False;
   6600          }
   6601 
   6602          DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6603 
   6604          // trap if misaligned
   6605          gen_SIGBUS_if_misaligned( EA, 16 );
   6606          // Get the data to be stored
   6607          assign( rS_hi, getIReg(rS_addr) );
   6608          assign( rS_lo, getIReg(rS_addr+1) );
   6609 
   6610          // Do the store, and get success/failure bit into resSC
   6611          resSC = newTemp(Ity_I1);
   6612 
   6613          if (mode64) {
   6614             if (host_endness == VexEndnessBE) {
   6615                stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) );
   6616                store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
   6617                       mkexpr(rS_lo) );
   6618 	    } else {
   6619                stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) );
   6620                store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
   6621                       mkexpr(rS_hi) );
   6622 	    }
   6623          } else {
   6624             stmt( stmt_load( resSC, binop( Iop_Add32,
   6625                                            mkexpr(EA),
   6626                                            mkU32(4) ),
   6627                                            mkexpr(rS_hi) ) );
   6628             store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
   6629          }
   6630 
   6631          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6632          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6633          putCR321(0, binop( Iop_Shl8,
   6634                             unop(Iop_1Uto8, mkexpr(resSC) ),
   6635                             mkU8(1)));
   6636          putCR0(0, getXER_SO());
   6637          break;
   6638       }
   6639 
   6640       default:
   6641          vex_printf("dis_memsync(ppc)(opc2)\n");
   6642          return False;
   6643       }
   6644       break;
   6645 
   6646    default:
   6647       vex_printf("dis_memsync(ppc)(opc1)\n");
   6648       return False;
   6649    }
   6650    return True;
   6651 }
   6652 
   6653 
   6654 
   6655 /*
   6656   Integer Shift Instructions
   6657 */
   6658 static Bool dis_int_shift ( UInt theInstr )
   6659 {
   6660    /* X-Form, XS-Form */
   6661    UChar opc1    = ifieldOPC(theInstr);
   6662    UChar rS_addr = ifieldRegDS(theInstr);
   6663    UChar rA_addr = ifieldRegA(theInstr);
   6664    UChar rB_addr = ifieldRegB(theInstr);
   6665    UChar sh_imm  = rB_addr;
   6666    UInt  opc2    = ifieldOPClo10(theInstr);
   6667    UChar b1      = ifieldBIT1(theInstr);
   6668    UChar flag_rC = ifieldBIT0(theInstr);
   6669 
   6670    IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
   6671    IRTemp  rA         = newTemp(ty);
   6672    IRTemp  rS         = newTemp(ty);
   6673    IRTemp  rB         = newTemp(ty);
   6674    IRTemp  outofrange = newTemp(Ity_I1);
   6675    IRTemp  rS_lo32    = newTemp(Ity_I32);
   6676    IRTemp  rB_lo32    = newTemp(Ity_I32);
   6677    IRExpr* e_tmp;
   6678 
   6679    assign( rS, getIReg(rS_addr) );
   6680    assign( rB, getIReg(rB_addr) );
   6681    assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
   6682    assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
   6683 
   6684    if (opc1 == 0x1F) {
   6685       switch (opc2) {
   6686       case 0x018: { // slw (Shift Left Word, PPC32 p505)
   6687          DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6688              rA_addr, rS_addr, rB_addr);
   6689          /* rA = rS << rB */
   6690          /* ppc32 semantics are:
   6691             slw(x,y) = (x << (y & 31))         -- primary result
   6692                        & ~((y << 26) >>s 31)   -- make result 0
   6693                                                   for y in 32 .. 63
   6694          */
   6695          e_tmp =
   6696             binop( Iop_And32,
   6697                binop( Iop_Shl32,
   6698                       mkexpr(rS_lo32),
   6699                       unop( Iop_32to8,
   6700                             binop(Iop_And32,
   6701                                   mkexpr(rB_lo32), mkU32(31)))),
   6702                unop( Iop_Not32,
   6703                      binop( Iop_Sar32,
   6704                             binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
   6705                             mkU8(31))) );
   6706          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   6707          break;
   6708       }
   6709 
   6710       case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
   6711          IRTemp sh_amt = newTemp(Ity_I32);
   6712          DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6713              rA_addr, rS_addr, rB_addr);
   6714          /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
   6715             amt = rB & 63
   6716             rA = Sar32( rS, amt > 31 ? 31 : amt )
   6717             XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
   6718          */
   6719          assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
   6720                                           mkexpr(rB_lo32)) );
   6721          assign( outofrange,
   6722                  binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) );
   6723          e_tmp = binop( Iop_Sar32,
   6724                         mkexpr(rS_lo32),
   6725                         unop( Iop_32to8,
   6726                               IRExpr_ITE( mkexpr(outofrange),
   6727                                           mkU32(31),
   6728                                           mkexpr(sh_amt)) ) );
   6729          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
   6730 
   6731          set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
   6732                      mkexpr(rA),
   6733                      mkWidenFrom32(ty, mkexpr(rS_lo32), True),
   6734                      mkWidenFrom32(ty, mkexpr(sh_amt), True ),
   6735                      mkWidenFrom32(ty, getXER_CA32(), True) );
   6736          break;
   6737       }
   6738 
   6739       case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
   6740          DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   6741              rA_addr, rS_addr, sh_imm);
   6742          vassert(sh_imm < 32);
   6743          if (mode64) {
   6744             assign( rA, binop(Iop_Sar64,
   6745                               binop(Iop_Shl64, getIReg(rS_addr),
   6746                                                mkU8(32)),
   6747                               mkU8(32 + sh_imm)) );
   6748          } else {
   6749             assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
   6750                                          mkU8(sh_imm)) );
   6751          }
   6752 
   6753          set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
   6754                      mkexpr(rA),
   6755                      mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
   6756                      mkSzImm(ty, sh_imm),
   6757                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6758          break;
   6759 
   6760       case 0x218: // srw (Shift Right Word, PPC32 p508)
   6761          DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6762              rA_addr, rS_addr, rB_addr);
   6763          /* rA = rS >>u rB */
   6764          /* ppc32 semantics are:
   6765             srw(x,y) = (x >>u (y & 31))        -- primary result
   6766                        & ~((y << 26) >>s 31)   -- make result 0
   6767                                                   for y in 32 .. 63
   6768          */
   6769          e_tmp =
   6770             binop(
   6771                Iop_And32,
   6772                binop( Iop_Shr32,
   6773                       mkexpr(rS_lo32),
   6774                       unop( Iop_32to8,
   6775                             binop(Iop_And32, mkexpr(rB_lo32),
   6776                                              mkU32(31)))),
   6777                unop( Iop_Not32,
   6778                      binop( Iop_Sar32,
   6779                             binop(Iop_Shl32, mkexpr(rB_lo32),
   6780                                              mkU8(26)),
   6781                             mkU8(31))));
   6782          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   6783          break;
   6784 
   6785 
   6786       /* 64bit Shifts */
   6787       case 0x01B: // sld (Shift Left DWord, PPC64 p568)
   6788          DIP("sld%s r%u,r%u,r%u\n",
   6789              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6790          /* rA = rS << rB */
   6791          /* ppc64 semantics are:
   6792             slw(x,y) = (x << (y & 63))         -- primary result
   6793                        & ~((y << 57) >>s 63)   -- make result 0
   6794                                                   for y in 64 ..
   6795          */
   6796          assign( rA,
   6797             binop(
   6798                Iop_And64,
   6799                binop( Iop_Shl64,
   6800                       mkexpr(rS),
   6801                       unop( Iop_64to8,
   6802                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   6803                unop( Iop_Not64,
   6804                      binop( Iop_Sar64,
   6805                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   6806                             mkU8(63)))) );
   6807          break;
   6808 
   6809       case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
   6810          IRTemp sh_amt = newTemp(Ity_I64);
   6811          DIP("srad%s r%u,r%u,r%u\n",
   6812              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6813          /* amt = rB & 127
   6814             rA = Sar64( rS, amt > 63 ? 63 : amt )
   6815             XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
   6816          */
   6817          assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
   6818          assign( outofrange,
   6819                  binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) );
   6820          assign( rA,
   6821                  binop( Iop_Sar64,
   6822                         mkexpr(rS),
   6823                         unop( Iop_64to8,
   6824                               IRExpr_ITE( mkexpr(outofrange),
   6825                                           mkU64(63),
   6826                                           mkexpr(sh_amt)) ))
   6827                );
   6828          set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
   6829                      mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
   6830                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6831          break;
   6832       }
   6833 
   6834       case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
   6835          sh_imm |= b1<<5;
   6836          vassert(sh_imm < 64);
   6837          DIP("sradi%s r%u,r%u,%u\n",
   6838              flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   6839          assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
   6840 
   6841          set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
   6842                      mkexpr(rA),
   6843                      getIReg(rS_addr),
   6844                      mkU64(sh_imm),
   6845                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6846          break;
   6847 
   6848       case 0x21B: // srd (Shift Right DWord, PPC64 p574)
   6849          DIP("srd%s r%u,r%u,r%u\n",
   6850              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6851          /* rA = rS >>u rB */
   6852          /* ppc semantics are:
   6853             srw(x,y) = (x >>u (y & 63))        -- primary result
   6854                        & ~((y << 57) >>s 63)   -- make result 0
   6855                                                   for y in 64 .. 127
   6856          */
   6857          assign( rA,
   6858             binop(
   6859                Iop_And64,
   6860                binop( Iop_Shr64,
   6861                       mkexpr(rS),
   6862                       unop( Iop_64to8,
   6863                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   6864                unop( Iop_Not64,
   6865                      binop( Iop_Sar64,
   6866                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   6867                             mkU8(63)))) );
   6868          break;
   6869 
   6870       default:
   6871          vex_printf("dis_int_shift(ppc)(opc2)\n");
   6872          return False;
   6873       }
   6874    } else {
   6875       vex_printf("dis_int_shift(ppc)(opc1)\n");
   6876       return False;
   6877    }
   6878 
   6879    putIReg( rA_addr, mkexpr(rA) );
   6880 
   6881    if (flag_rC) {
   6882       set_CR0( mkexpr(rA) );
   6883    }
   6884    return True;
   6885 }
   6886 
   6887 
   6888 
   6889 /*
   6890   Integer Load/Store Reverse Instructions
   6891 */
   6892 /* Generates code to swap the byte order in an Ity_I32. */
   6893 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
   6894 {
   6895    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   6896    return
   6897       binop(Iop_Or32,
   6898          binop(Iop_Shl32, mkexpr(t), mkU8(24)),
   6899       binop(Iop_Or32,
   6900          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   6901                           mkU32(0x00FF0000)),
   6902       binop(Iop_Or32,
   6903          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   6904                           mkU32(0x0000FF00)),
   6905          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
   6906                           mkU32(0x000000FF) )
   6907       )));
   6908 }
   6909 
   6910 /* Generates code to swap the byte order in the lower half of an Ity_I32,
   6911    and zeroes the upper half. */
   6912 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
   6913 {
   6914    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   6915    return
   6916       binop(Iop_Or32,
   6917          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   6918                           mkU32(0x0000FF00)),
   6919          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   6920                           mkU32(0x000000FF))
   6921       );
   6922 }
   6923 
   6924 static Bool dis_int_ldst_rev ( UInt theInstr )
   6925 {
   6926    /* X-Form */
   6927    UChar opc1    = ifieldOPC(theInstr);
   6928    UChar rD_addr = ifieldRegDS(theInstr);
   6929    UChar rS_addr = rD_addr;
   6930    UChar rA_addr = ifieldRegA(theInstr);
   6931    UChar rB_addr = ifieldRegB(theInstr);
   6932    UInt  opc2    = ifieldOPClo10(theInstr);
   6933    UChar b0      = ifieldBIT0(theInstr);
   6934 
   6935    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   6936    IRTemp EA = newTemp(ty);
   6937    IRTemp w1 = newTemp(Ity_I32);
   6938    IRTemp w2 = newTemp(Ity_I32);
   6939 
   6940    if (opc1 != 0x1F || b0 != 0) {
   6941       vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
   6942       return False;
   6943    }
   6944 
   6945    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   6946 
   6947    switch (opc2) {
   6948 
   6949       case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
   6950          DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6951          assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) );
   6952          assign( w2, gen_byterev16(w1) );
   6953          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   6954                                          /* Signed */False) );
   6955          break;
   6956 
   6957       case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
   6958          DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6959          assign( w1, load(Ity_I32, mkexpr(EA)) );
   6960          assign( w2, gen_byterev32(w1) );
   6961          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   6962                                          /* Signed */False) );
   6963          break;
   6964 
   6965       case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
   6966       {
   6967          IRExpr * nextAddr;
   6968          IRTemp w3 = newTemp( Ity_I32 );
   6969          IRTemp w4 = newTemp( Ity_I32 );
   6970          DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6971          assign( w1, load( Ity_I32, mkexpr( EA ) ) );
   6972          assign( w2, gen_byterev32( w1 ) );
   6973          nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   6974                            ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
   6975          assign( w3, load( Ity_I32, nextAddr ) );
   6976          assign( w4, gen_byterev32( w3 ) );
   6977          if (host_endness == VexEndnessLE)
   6978             putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) );
   6979          else
   6980             putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
   6981          break;
   6982       }
   6983 
   6984       case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
   6985          DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6986          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   6987          store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
   6988          break;
   6989 
   6990       case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
   6991          DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6992          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   6993          store( mkexpr(EA), gen_byterev32(w1) );
   6994          break;
   6995 
   6996       case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
   6997       {
   6998          IRTemp lo = newTemp(Ity_I32);
   6999          IRTemp hi = newTemp(Ity_I32);
   7000          IRTemp rS = newTemp(Ity_I64);
   7001          assign( rS, getIReg( rS_addr ) );
   7002          DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   7003          assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
   7004          assign(hi, unop(Iop_64to32, mkexpr(rS)));
   7005          store( mkexpr( EA ),
   7006                 binop( Iop_32HLto64, gen_byterev32( hi ),
   7007                        gen_byterev32( lo ) ) );
   7008          break;
   7009       }
   7010 
   7011       default:
   7012          vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
   7013          return False;
   7014    }
   7015    return True;
   7016 }
   7017 
   7018 
   7019 
   7020 /*
   7021   Processor Control Instructions
   7022 */
   7023 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr )
   7024 {
   7025    UChar opc1     = ifieldOPC(theInstr);
   7026 
   7027    /* X-Form */
   7028    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   7029    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   7030    UChar rD_addr  = ifieldRegDS(theInstr);
   7031    UInt  b11to20  = IFIELD( theInstr, 11, 10 );
   7032 
   7033    /* XFX-Form */
   7034    UChar rS_addr  = rD_addr;
   7035    UInt  SPR      = b11to20;
   7036    UInt  TBR      = b11to20;
   7037    UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
   7038    UInt  CRM      = IFIELD( theInstr, 12, 8 );
   7039    UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
   7040 
   7041    UInt  opc2     = ifieldOPClo10(theInstr);
   7042    UChar b0       = ifieldBIT0(theInstr);
   7043 
   7044    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   7045    IRTemp rS = newTemp(ty);
   7046    assign( rS, getIReg(rS_addr) );
   7047 
   7048    /* Reorder SPR field as per PPC32 p470 */
   7049    SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
   7050    /* Reorder TBR field as per PPC32 p475 */
   7051    TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
   7052 
   7053    /* b0 = 0, inst is treated as floating point inst for reservation purposes
   7054     * b0 = 1, inst is treated as vector inst for reservation purposes
   7055     */
   7056    if (opc1 != 0x1F) {
   7057       vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0);
   7058       return False;
   7059    }
   7060 
   7061    switch (opc2) {
   7062    /* X-Form */
   7063    case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
   7064       if (b21to22 != 0 || b11to20 != 0) {
   7065          vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
   7066          return False;
   7067       }
   7068       DIP("mcrxr crf%d\n", crfD);
   7069       /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
   7070       putGST_field( PPC_GST_CR,
   7071                     getGST_field( PPC_GST_XER, 7 ),
   7072                     crfD );
   7073 
   7074       // Clear XER[0-3]
   7075       putXER_SO( mkU8(0) );
   7076       putXER_OV( mkU8(0) );
   7077       putXER_CA( mkU8(0) );
   7078       break;
   7079    }
   7080 
   7081    case 0x013:
   7082       // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
   7083       // b20==1 & b11==0: mfocrf (Move from One CR Field)
   7084       // However it seems that the 'mfcr' behaviour is an acceptable
   7085       // implementation of mfocr (from the 2.02 arch spec)
   7086       if (b11to20 == 0) {
   7087          DIP("mfcr r%u\n", rD_addr);
   7088          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   7089                                          /* Signed */False) );
   7090          break;
   7091       }
   7092       if (b20 == 1 && b11 == 0) {
   7093          DIP("mfocrf r%u,%u\n", rD_addr, CRM);
   7094          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   7095                                          /* Signed */False) );
   7096          break;
   7097       }
   7098       /* not decodable */
   7099       return False;
   7100 
   7101    /* XFX-Form */
   7102    case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
   7103 
   7104       switch (SPR) {  // Choose a register...
   7105       case 0x1:
   7106          DIP("mfxer r%u\n", rD_addr);
   7107          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
   7108                                          /* Signed */False) );
   7109          break;
   7110       case 0x8:
   7111          DIP("mflr r%u\n", rD_addr);
   7112          putIReg( rD_addr, getGST( PPC_GST_LR ) );
   7113          break;
   7114       case 0x9:
   7115          DIP("mfctr r%u\n", rD_addr);
   7116          putIReg( rD_addr, getGST( PPC_GST_CTR ) );
   7117          break;
   7118       case 0x80:  // 128
   7119          DIP("mfspr r%u (TFHAR)\n", rD_addr);
   7120          putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
   7121          break;
   7122       case 0x81:  // 129
   7123          DIP("mfspr r%u (TFIAR)\n", rD_addr);
   7124          putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
   7125          break;
   7126       case 0x82:  // 130
   7127          DIP("mfspr r%u (TEXASR)\n", rD_addr);
   7128          putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
   7129          break;
   7130       case 0x83:  // 131
   7131          DIP("mfspr r%u (TEXASRU)\n", rD_addr);
   7132          putIReg( rD_addr, getGST( PPC_GST_TEXASRU) );
   7133          break;
   7134       case 0x100:
   7135          DIP("mfvrsave r%u\n", rD_addr);
   7136          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
   7137                                          /* Signed */False) );
   7138          break;
   7139 
   7140       case 0x103:
   7141          DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
   7142          putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
   7143          break;
   7144 
   7145       /* Even a lowly PPC7400 can run the associated helper, so no
   7146          obvious need for feature testing at this point. */
   7147       case 268 /* 0x10C */:
   7148       case 269 /* 0x10D */: {
   7149          UInt     arg  = SPR==268 ? 0 : 1;
   7150          IRTemp   val  = newTemp(Ity_I32);
   7151          IRExpr** args = mkIRExprVec_1( mkU32(arg) );
   7152          IRDirty* d    = unsafeIRDirty_1_N(
   7153                             val,
   7154                             0/*regparms*/,
   7155                             "ppc32g_dirtyhelper_MFSPR_268_269",
   7156                             fnptr_to_fnentry
   7157                                (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
   7158                             args
   7159                          );
   7160          /* execute the dirty call, dumping the result in val. */
   7161          stmt( IRStmt_Dirty(d) );
   7162          putIReg( rD_addr,
   7163                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   7164          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
   7165          break;
   7166       }
   7167 
   7168       /* Again, runs natively on PPC7400 (7447, really).  Not
   7169          bothering with a feature test. */
   7170       case 287: /* 0x11F */ {
   7171          IRTemp   val  = newTemp(Ity_I32);
   7172          IRExpr** args = mkIRExprVec_0();
   7173          IRDirty* d    = unsafeIRDirty_1_N(
   7174                             val,
   7175                             0/*regparms*/,
   7176                             "ppc32g_dirtyhelper_MFSPR_287",
   7177                             fnptr_to_fnentry
   7178                                (vbi, &ppc32g_dirtyhelper_MFSPR_287),
   7179                             args
   7180                          );
   7181          /* execute the dirty call, dumping the result in val. */
   7182          stmt( IRStmt_Dirty(d) );
   7183          putIReg( rD_addr,
   7184                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   7185          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
   7186          break;
   7187       }
   7188 
   7189       default:
   7190          vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
   7191          return False;
   7192       }
   7193       break;
   7194 
   7195    case 0x173: { // mftb (Move from Time Base, PPC32 p475)
   7196       IRTemp   val  = newTemp(Ity_I64);
   7197       IRExpr** args = mkIRExprVec_0();
   7198       IRDirty* d    = unsafeIRDirty_1_N(
   7199                               val,
   7200                               0/*regparms*/,
   7201                               "ppcg_dirtyhelper_MFTB",
   7202                               fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
   7203                               args );
   7204       /* execute the dirty call, dumping the result in val. */
   7205       stmt( IRStmt_Dirty(d) );
   7206 
   7207       switch (TBR) {
   7208       case 269:
   7209          DIP("mftbu r%u", rD_addr);
   7210          putIReg( rD_addr,
   7211                   mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
   7212                                 /* Signed */False) );
   7213          break;
   7214       case 268:
   7215          DIP("mftb r%u", rD_addr);
   7216          putIReg( rD_addr, (mode64) ? mkexpr(val) :
   7217                                       unop(Iop_64to32, mkexpr(val)) );
   7218          break;
   7219       default:
   7220          return False; /* illegal instruction */
   7221       }
   7222       break;
   7223    }
   7224 
   7225    case 0x090: {
   7226       // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
   7227       // b20==1: mtocrf (Move to One Cond Reg Field)
   7228       Int   cr;
   7229       UChar shft;
   7230       if (b11 != 0)
   7231          return False;
   7232       if (b20 == 1) {
   7233          /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
   7234             1 field is written.  It seems more robust to decline to
   7235             decode the insn if so. */
   7236          switch (CRM) {
   7237             case 0x01: case 0x02: case 0x04: case 0x08:
   7238             case 0x10: case 0x20: case 0x40: case 0x80:
   7239                break;
   7240             default:
   7241                return False;
   7242          }
   7243       }
   7244       DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
   7245                            CRM, rS_addr);
   7246       /* Write to each field specified by CRM */
   7247       for (cr = 0; cr < 8; cr++) {
   7248          if ((CRM & (1 << (7-cr))) == 0)
   7249             continue;
   7250          shft = 4*(7-cr);
   7251          putGST_field( PPC_GST_CR,
   7252                        binop(Iop_Shr32,
   7253                              mkNarrowTo32(ty, mkexpr(rS)),
   7254                              mkU8(shft)), cr );
   7255       }
   7256       break;
   7257    }
   7258 
   7259    case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
   7260 
   7261       switch (SPR) {  // Choose a register...
   7262       case 0x1:
   7263          DIP("mtxer r%u\n", rS_addr);
   7264          putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
   7265          break;
   7266       case 0x8:
   7267          DIP("mtlr r%u\n", rS_addr);
   7268          putGST( PPC_GST_LR, mkexpr(rS) );
   7269          break;
   7270       case 0x9:
   7271          DIP("mtctr r%u\n", rS_addr);
   7272          putGST( PPC_GST_CTR, mkexpr(rS) );
   7273          break;
   7274       case 0x100:
   7275          DIP("mtvrsave r%u\n", rS_addr);
   7276          putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
   7277          break;
   7278       case 0x80:  // 128
   7279          DIP("mtspr r%u (TFHAR)\n", rS_addr);
   7280          putGST( PPC_GST_TFHAR, mkexpr(rS) );
   7281          break;
   7282       case 0x81:  // 129
   7283          DIP("mtspr r%u (TFIAR)\n", rS_addr);
   7284          putGST( PPC_GST_TFIAR, mkexpr(rS) );
   7285          break;
   7286       case 0x82:  // 130
   7287          DIP("mtspr r%u (TEXASR)\n", rS_addr);
   7288          putGST( PPC_GST_TEXASR, mkexpr(rS) );
   7289          break;
   7290       default:
   7291          vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
   7292          return False;
   7293       }
   7294       break;
   7295 
   7296    case 0x33:                // mfvsrd
   7297    {
   7298       UChar XS = ifieldRegXS( theInstr );
   7299       UChar rA_addr = ifieldRegA(theInstr);
   7300       IRExpr * high64;
   7301       IRTemp vS = newTemp( Ity_V128 );
   7302       DIP("mfvsrd r%u,vsr%d\n", rA_addr, (UInt)XS);
   7303 
   7304       /*  XS = SX || S
   7305        *  For SX=0, mfvsrd is treated as a Floating-Point
   7306        *            instruction in terms of resource availability.
   7307        *  For SX=1, mfvsrd is treated as a Vector instruction in
   7308        *            terms of resource availability.
   7309        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7310        */
   7311       assign( vS, getVSReg( XS ) );
   7312       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   7313       putIReg( rA_addr, (mode64) ? high64 :
   7314       unop( Iop_64to32, high64 ) );
   7315       break;
   7316    }
   7317 
   7318    case 0x73:                // mfvsrwz
   7319    {
   7320       UChar XS = ifieldRegXS( theInstr );
   7321       UChar rA_addr = ifieldRegA(theInstr);
   7322       IRExpr * high64;
   7323       IRTemp vS = newTemp( Ity_V128 );
   7324       DIP("mfvsrwz r%u,vsr%d\n", rA_addr, (UInt)XS);
   7325       /*  XS = SX || S
   7326        *  For SX=0, mfvsrwz is treated as a Floating-Point
   7327        *            instruction in terms of resource availability.
   7328        *  For SX=1, mfvsrwz is treated as a Vector instruction in
   7329        *            terms of resource availability.
   7330        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7331        */
   7332 
   7333       assign( vS, getVSReg( XS ) );
   7334       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   7335       /* move value to the destination setting the upper 32-bits to zero */
   7336       putIReg( rA_addr, (mode64) ?
   7337                                   binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) :
   7338                                   unop(  Iop_64to32,
   7339                                          binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
   7340       break;
   7341    }
   7342 
   7343    case 0xB3:                // mtvsrd
   7344    {
   7345       UChar XT = ifieldRegXT( theInstr );
   7346       UChar rA_addr = ifieldRegA(theInstr);
   7347       IRTemp rA = newTemp(ty);
   7348       DIP("mtvsrd vsr%d,r%u\n", (UInt)XT, rA_addr);
   7349       /*  XS = SX || S
   7350        *  For SX=0, mfvsrd is treated as a Floating-Point
   7351        *            instruction in terms of resource availability.
   7352        *  For SX=1, mfvsrd is treated as a Vector instruction in
   7353        *            terms of resource availability.
   7354        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7355        */
   7356       assign( rA, getIReg(rA_addr) );
   7357 
   7358       if (mode64)
   7359          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
   7360       else
   7361          putVSReg( XT, binop( Iop_64HLtoV128,
   7362                               binop( Iop_32HLto64,
   7363                                      mkU32( 0 ),
   7364                                      mkexpr( rA ) ),
   7365                                      mkU64( 0 ) ) );
   7366       break;
   7367    }
   7368 
   7369    case 0xD3:                // mtvsrwa
   7370    {
   7371       UChar XT = ifieldRegXT( theInstr );
   7372       UChar rA_addr = ifieldRegA(theInstr);
   7373       IRTemp rA = newTemp( Ity_I32 );
   7374       DIP("mtvsrwa vsr%d,r%u\n", (UInt)XT, rA_addr);
   7375       /*  XS = SX || S
   7376        *  For SX=0, mtvsrwa is treated as a Floating-Point
   7377        *            instruction in terms of resource availability.
   7378        *  For SX=1, mtvsrwa is treated as a Vector instruction in
   7379        *            terms of resource availability.
   7380        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7381        */
   7382       if (mode64)
   7383          assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
   7384       else
   7385          assign( rA, getIReg(rA_addr) );
   7386 
   7387       putVSReg( XT, binop( Iop_64HLtoV128,
   7388                            unop( Iop_32Sto64, mkexpr( rA ) ),
   7389                            mkU64( 0 ) ) );
   7390       break;
   7391    }
   7392 
   7393    case 0xF3:                // mtvsrwz
   7394       {
   7395          UChar XT = ifieldRegXT( theInstr );
   7396          UChar rA_addr = ifieldRegA(theInstr);
   7397          IRTemp rA = newTemp( Ity_I32 );
   7398          DIP("mtvsrwz vsr%d,r%u\n", rA_addr, (UInt)XT);
   7399          /*  XS = SX || S
   7400           *  For SX=0, mtvsrwz is treated as a Floating-Point
   7401           *            instruction in terms of resource availability.
   7402           *  For SX=1, mtvsrwz is treated as a Vector instruction in
   7403           *            terms of resource availability.
   7404           * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7405           */
   7406          if (mode64)
   7407              assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
   7408          else
   7409              assign( rA, getIReg(rA_addr) );
   7410 
   7411          putVSReg( XT, binop( Iop_64HLtoV128,
   7412                               binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
   7413                               mkU64( 0 ) ) );
   7414          break;
   7415       }
   7416 
   7417    default:
   7418       vex_printf("dis_proc_ctl(ppc)(opc2)\n");
   7419       return False;
   7420    }
   7421    return True;
   7422 }
   7423 
   7424 
   7425 /*
   7426   Cache Management Instructions
   7427 */
   7428 static Bool dis_cache_manage ( UInt         theInstr,
   7429                                DisResult*   dres,
   7430                                const VexArchInfo* guest_archinfo )
   7431 {
   7432    /* X-Form */
   7433    UChar opc1    = ifieldOPC(theInstr);
   7434    UChar b21to25 = ifieldRegDS(theInstr);
   7435    UChar rA_addr = ifieldRegA(theInstr);
   7436    UChar rB_addr = ifieldRegB(theInstr);
   7437    UInt  opc2    = ifieldOPClo10(theInstr);
   7438    UChar b0      = ifieldBIT0(theInstr);
   7439    UInt  lineszB = guest_archinfo->ppc_icache_line_szB;
   7440    Bool  is_dcbzl = False;
   7441 
   7442    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   7443 
   7444    // Check for valid hint values for dcbt and dcbtst as currently described in
   7445    // ISA 2.07.  If valid, then we simply set b21to25 to zero since we have no
   7446    // means of modeling the hint anyway.
   7447    if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) {
   7448       if (b21to25 == 0x10 || b21to25 < 0x10)
   7449          b21to25 = 0;
   7450    }
   7451    if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
   7452       b21to25 = 0;
   7453 
   7454    if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
   7455       if (b21to25 == 1) {
   7456          is_dcbzl = True;
   7457          b21to25 = 0;
   7458          if (!(guest_archinfo->ppc_dcbzl_szB)) {
   7459             vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
   7460             return False;
   7461          }
   7462       }
   7463    }
   7464 
   7465    if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
   7466       if (0) vex_printf("dis_cache_manage %d %d %d\n",
   7467                         (Int)opc1, (Int)b21to25, (Int)b0);
   7468       vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n");
   7469       return False;
   7470    }
   7471 
   7472    /* stay sane .. */
   7473    vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
   7474 
   7475    switch (opc2) {
   7476 //zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
   7477 //zz       vassert(0); /* AWAITING TEST CASE */
   7478 //zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
   7479 //zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
   7480 //zz       break;
   7481 
   7482    case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
   7483       DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
   7484       /* nop as far as vex is concerned */
   7485       break;
   7486 
   7487    case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
   7488       DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
   7489       /* nop as far as vex is concerned */
   7490       break;
   7491 
   7492    case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
   7493       DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
   7494       /* nop as far as vex is concerned */
   7495       break;
   7496 
   7497    case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
   7498       DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
   7499       /* nop as far as vex is concerned */
   7500       break;
   7501 
   7502    case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
   7503                  // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
   7504       /* Clear all bytes in cache block at (rA|0) + rB. */
   7505       IRTemp  EA   = newTemp(ty);
   7506       IRTemp  addr = newTemp(ty);
   7507       IRExpr* irx_addr;
   7508       UInt    i;
   7509       UInt clearszB;
   7510       if (is_dcbzl) {
   7511           clearszB = guest_archinfo->ppc_dcbzl_szB;
   7512           DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
   7513       }
   7514       else {
   7515           clearszB = guest_archinfo->ppc_dcbz_szB;
   7516           DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
   7517       }
   7518 
   7519       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7520 
   7521       if (mode64) {
   7522          /* Round EA down to the start of the containing block. */
   7523          assign( addr, binop( Iop_And64,
   7524                               mkexpr(EA),
   7525                               mkU64( ~((ULong)clearszB-1) )) );
   7526 
   7527          for (i = 0; i < clearszB / 8; i++) {
   7528             irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
   7529             store( irx_addr, mkU64(0) );
   7530          }
   7531       } else {
   7532          /* Round EA down to the start of the containing block. */
   7533          assign( addr, binop( Iop_And32,
   7534                               mkexpr(EA),
   7535                               mkU32( ~(clearszB-1) )) );
   7536 
   7537          for (i = 0; i < clearszB / 4; i++) {
   7538             irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
   7539             store( irx_addr, mkU32(0) );
   7540          }
   7541       }
   7542       break;
   7543    }
   7544 
   7545    case 0x3D6: {
   7546       // icbi (Instruction Cache Block Invalidate, PPC32 p431)
   7547       /* Invalidate all translations containing code from the cache
   7548          block at (rA|0) + rB. */
   7549       IRTemp EA   = newTemp(ty);
   7550       IRTemp addr = newTemp(ty);
   7551       DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
   7552       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7553 
   7554       /* Round EA down to the start of the containing block. */
   7555       assign( addr, binop( mkSzOp(ty, Iop_And8),
   7556                            mkexpr(EA),
   7557                            mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
   7558       putGST( PPC_GST_CMSTART, mkexpr(addr) );
   7559       putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) );
   7560 
   7561       /* be paranoid ... */
   7562       stmt( IRStmt_MBE(Imbe_Fence) );
   7563 
   7564       putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
   7565       dres->jk_StopHere = Ijk_InvalICache;
   7566       dres->whatNext    = Dis_StopHere;
   7567       break;
   7568    }
   7569 
   7570    default:
   7571       vex_printf("dis_cache_manage(ppc)(opc2)\n");
   7572       return False;
   7573    }
   7574    return True;
   7575 }
   7576 
   7577 
   7578 /*------------------------------------------------------------*/
   7579 /*--- Floating Point Helpers                               ---*/
   7580 /*------------------------------------------------------------*/
   7581 
   7582 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
   7583 /* Produces a value in 0 .. 3, which is encoded as per the type
   7584    IRRoundingMode.  PPCRoundingMode encoding is different to
   7585    IRRoundingMode, so need to map it.
   7586 */
   7587 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
   7588 {
   7589 /*
   7590    rounding mode | PPC | IR
   7591    ------------------------
   7592    to nearest    | 00  | 00
   7593    to zero       | 01  | 11
   7594    to +infinity  | 10  | 10
   7595    to -infinity  | 11  | 01
   7596 */
   7597    IRTemp rm_PPC32 = newTemp(Ity_I32);
   7598    assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
   7599 
   7600    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
   7601    return binop( Iop_Xor32,
   7602                  mkexpr(rm_PPC32),
   7603                  binop( Iop_And32,
   7604                         binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
   7605                         mkU32(2) ));
   7606 }
   7607 
   7608 /* The DFP IR rounding modes were chosen such that the existing PPC to IR
   7609  * mapping would still work with the extended three bit DFP rounding
   7610  * mode designator.
   7611 
   7612  *  rounding mode                     | PPC  |  IR
   7613  *  -----------------------------------------------
   7614  *  to nearest, ties to even          | 000  | 000
   7615  *  to zero                           | 001  | 011
   7616  *  to +infinity                      | 010  | 010
   7617  *  to -infinity                      | 011  | 001
   7618  *  to nearest, ties away from 0      | 100  | 100
   7619  *  to nearest, ties toward 0         | 101  | 111
   7620  *  to away from 0                    | 110  | 110
   7621  *  to prepare for shorter precision  | 111  | 101
   7622  */
   7623 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
   7624 {
   7625    IRTemp rm_PPC32 = newTemp( Ity_I32 );
   7626    assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
   7627 
   7628    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
   7629    return binop( Iop_Xor32,
   7630                  mkexpr( rm_PPC32 ),
   7631                  binop( Iop_And32,
   7632                         binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
   7633                         mkU32( 2 ) ) );
   7634 }
   7635 
   7636 #define NANmaskSingle   0x7F800000
   7637 #define NANmaskDouble   0x7FF00000
   7638 
   7639 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
   7640 {
   7641    IRTemp exp_zero  = newTemp(Ity_I8);
   7642    IRTemp frac_mask = newTemp(Ity_I32);
   7643    IRTemp frac_not_zero = newTemp(Ity_I8);
   7644 
   7645    /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
   7646     * The input value is always 64-bits, for single precision values, the
   7647     * lower 32 bits must be zero.
   7648     *
   7649     * Single Pricision
   7650     *  [62:54] exponent field is equal to 0xFF for NAN and Infinity.
   7651     *  [53:32] fraction field is zero for Infinity and non-zero for NAN
   7652     *  [31:0]  unused for single precision representation
   7653     *
   7654     * Double Pricision
   7655     *  [62:51] exponent field is equal to 0xFF for NAN and Infinity.
   7656     *  [50:0]  fraction field is zero for Infinity and non-zero for NAN
   7657     *
   7658     * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
   7659     */
   7660    assign( frac_mask, unop( Iop_Not32,
   7661                             binop( Iop_Or32,
   7662                                    mkU32( 0x80000000ULL ), Hi32Mask) ) );
   7663 
   7664    assign( exp_zero,
   7665            unop( Iop_1Sto8,
   7666                  binop( Iop_CmpEQ32,
   7667                         binop( Iop_And32,
   7668                                unop( Iop_64HIto32,
   7669                                      unop( Iop_ReinterpF64asI64,
   7670                                            value ) ),
   7671                                Hi32Mask ),
   7672                         Hi32Mask ) ) );
   7673    assign( frac_not_zero,
   7674            binop( Iop_Or8,
   7675                   unop( Iop_1Sto8,
   7676                         binop( Iop_CmpNE32,
   7677                                binop( Iop_And32,
   7678                                       unop( Iop_64HIto32,
   7679                                             unop( Iop_ReinterpF64asI64,
   7680                                                   value ) ),
   7681                                       mkexpr( frac_mask ) ),
   7682                                mkU32( 0x0 ) ) ),
   7683                   unop( Iop_1Sto8,
   7684                         binop( Iop_CmpNE32,
   7685                                binop( Iop_And32,
   7686                                       unop( Iop_64to32,
   7687                                             unop( Iop_ReinterpF64asI64,
   7688                                                   value ) ),
   7689                                       mkU32( 0xFFFFFFFF ) ),
   7690                                mkU32( 0x0 ) ) ) ) );
   7691    return unop( Iop_8Sto32,
   7692                 binop( Iop_And8,
   7693                        mkexpr( exp_zero ),
   7694                        mkexpr( frac_not_zero ) ) );
   7695 }
   7696 
   7697 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
   7698 {
   7699    /* This function will only complement the 64-bit floating point value if it
   7700     * is not Nan.  NaN is not a signed value.  Need to do computations using
   7701     * 32-bit operands to ensure it will run in 32-bit mode.
   7702     */
   7703    return  binop( Iop_32HLto64,
   7704                   binop( Iop_Or32,
   7705                          binop( Iop_And32,
   7706                                 nan_mask,
   7707                                 unop( Iop_64HIto32,
   7708                                       unop( Iop_ReinterpF64asI64,
   7709                                             value ) ) ),
   7710                          binop( Iop_And32,
   7711                                 unop( Iop_Not32,
   7712                                       nan_mask ),
   7713                                 unop( Iop_64HIto32,
   7714                                       unop( Iop_ReinterpF64asI64,
   7715                                             unop( Iop_NegF64,
   7716                                                   value ) ) ) ) ),
   7717                   unop( Iop_64to32,
   7718                         unop( Iop_ReinterpF64asI64, value ) ) );
   7719 }
   7720 
   7721 /*------------------------------------------------------------*/
   7722 /*--- Floating Point Instruction Translation               ---*/
   7723 /*------------------------------------------------------------*/
   7724 
   7725 /*
   7726   Floating Point Load Instructions
   7727 */
   7728 static Bool dis_fp_load ( UInt theInstr )
   7729 {
   7730    /* X-Form, D-Form */
   7731    UChar opc1      = ifieldOPC(theInstr);
   7732    UChar frD_addr  = ifieldRegDS(theInstr);
   7733    UChar rA_addr   = ifieldRegA(theInstr);
   7734    UChar rB_addr   = ifieldRegB(theInstr);
   7735    UInt  opc2      = ifieldOPClo10(theInstr);
   7736    UChar b0        = ifieldBIT0(theInstr);
   7737    UInt  uimm16    = ifieldUIMM16(theInstr);
   7738 
   7739    Int    simm16 = extend_s_16to32(uimm16);
   7740    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   7741    IRTemp EA     = newTemp(ty);
   7742    IRTemp rA     = newTemp(ty);
   7743    IRTemp rB     = newTemp(ty);
   7744    IRTemp iHi    = newTemp(Ity_I32);
   7745    IRTemp iLo    = newTemp(Ity_I32);
   7746 
   7747    assign( rA, getIReg(rA_addr) );
   7748    assign( rB, getIReg(rB_addr) );
   7749 
   7750    /* These are completely straightforward from a rounding and status
   7751       bits perspective: no rounding involved and no funny status or CR
   7752       bits affected. */
   7753 
   7754    switch (opc1) {
   7755    case 0x30: // lfs (Load Float Single, PPC32 p441)
   7756       DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7757       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7758       putFReg( frD_addr,
   7759                unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
   7760       break;
   7761 
   7762    case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
   7763       if (rA_addr == 0)
   7764          return False;
   7765       DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7766       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7767       putFReg( frD_addr,
   7768                unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
   7769       putIReg( rA_addr, mkexpr(EA) );
   7770       break;
   7771 
   7772    case 0x32: // lfd (Load Float Double, PPC32 p437)
   7773       DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7774       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7775       putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
   7776       break;
   7777 
   7778    case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
   7779       if (rA_addr == 0)
   7780          return False;
   7781       DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7782       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7783       putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
   7784       putIReg( rA_addr, mkexpr(EA) );
   7785       break;
   7786 
   7787    case 0x1F:
   7788       if (b0 != 0) {
   7789          vex_printf("dis_fp_load(ppc)(instr,b0)\n");
   7790          return False;
   7791       }
   7792 
   7793       switch(opc2) {
   7794       case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
   7795          DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7796          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7797          putFReg( frD_addr, unop( Iop_F32toF64,
   7798                                   load(Ity_F32, mkexpr(EA))) );
   7799          break;
   7800 
   7801       case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
   7802          if (rA_addr == 0)
   7803             return False;
   7804          DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7805          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7806          putFReg( frD_addr,
   7807                   unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
   7808          putIReg( rA_addr, mkexpr(EA) );
   7809          break;
   7810 
   7811       case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
   7812          DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7813          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7814          putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
   7815          break;
   7816 
   7817       case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
   7818          if (rA_addr == 0)
   7819             return False;
   7820          DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7821          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7822          putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
   7823          putIReg( rA_addr, mkexpr(EA) );
   7824          break;
   7825 
   7826       case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
   7827          DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7828          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   7829          assign( iLo, load(Ity_I32, mkexpr(EA)) );
   7830          assign( iHi, binop(Iop_Sub32,
   7831                             mkU32(0),
   7832                             binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
   7833          putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
   7834                                  binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
   7835          break;
   7836 
   7837       case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
   7838       {
   7839          IRTemp dw = newTemp( Ity_I64 );
   7840          DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7841          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   7842          assign( iLo, load(Ity_I32, mkexpr(EA)) );
   7843          assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
   7844          putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
   7845          break;
   7846       }
   7847 
   7848       default:
   7849          vex_printf("dis_fp_load(ppc)(opc2)\n");
   7850          return False;
   7851       }
   7852       break;
   7853 
   7854    default:
   7855       vex_printf("dis_fp_load(ppc)(opc1)\n");
   7856       return False;
   7857    }
   7858    return True;
   7859 }
   7860 
   7861 
   7862 
   7863 /*
   7864   Floating Point Store Instructions
   7865 */
   7866 static Bool dis_fp_store ( UInt theInstr )
   7867 {
   7868    /* X-Form, D-Form */
   7869    UChar opc1      = ifieldOPC(theInstr);
   7870    UChar frS_addr  = ifieldRegDS(theInstr);
   7871    UChar rA_addr   = ifieldRegA(theInstr);
   7872    UChar rB_addr   = ifieldRegB(theInstr);
   7873    UInt  opc2      = ifieldOPClo10(theInstr);
   7874    UChar b0        = ifieldBIT0(theInstr);
   7875    Int   uimm16    = ifieldUIMM16(theInstr);
   7876 
   7877    Int    simm16 = extend_s_16to32(uimm16);
   7878    IRTemp frS    = newTemp(Ity_F64);
   7879    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   7880    IRTemp EA     = newTemp(ty);
   7881    IRTemp rA     = newTemp(ty);
   7882    IRTemp rB     = newTemp(ty);
   7883 
   7884    assign( frS, getFReg(frS_addr) );
   7885    assign( rA,  getIReg(rA_addr) );
   7886    assign( rB,  getIReg(rB_addr) );
   7887 
   7888    /* These are straightforward from a status bits perspective: no
   7889       funny status or CR bits affected.  For single precision stores,
   7890       the values are truncated and denormalised (not rounded) to turn
   7891       them into single precision values. */
   7892 
   7893    switch (opc1) {
   7894 
   7895    case 0x34: // stfs (Store Float Single, PPC32 p518)
   7896       DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7897       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7898       /* Use Iop_TruncF64asF32 to truncate and possible denormalise
   7899          the value to be stored in the correct way, without any
   7900          rounding. */
   7901       store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7902       break;
   7903 
   7904    case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
   7905       if (rA_addr == 0)
   7906          return False;
   7907       DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7908       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7909       /* See comment for stfs */
   7910       store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7911       putIReg( rA_addr, mkexpr(EA) );
   7912       break;
   7913 
   7914    case 0x36: // stfd (Store Float Double, PPC32 p513)
   7915       DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7916       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7917       store( mkexpr(EA), mkexpr(frS) );
   7918       break;
   7919 
   7920    case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
   7921       if (rA_addr == 0)
   7922          return False;
   7923       DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7924       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7925       store( mkexpr(EA), mkexpr(frS) );
   7926       putIReg( rA_addr, mkexpr(EA) );
   7927       break;
   7928 
   7929    case 0x1F:
   7930       if (b0 != 0) {
   7931          vex_printf("dis_fp_store(ppc)(instr,b0)\n");
   7932          return False;
   7933       }
   7934       switch(opc2) {
   7935       case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
   7936          DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7937          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7938          /* See note for stfs */
   7939          store( mkexpr(EA),
   7940                 unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7941          break;
   7942 
   7943       case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
   7944          if (rA_addr == 0)
   7945             return False;
   7946          DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7947          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7948          /* See note for stfs */
   7949          store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7950          putIReg( rA_addr, mkexpr(EA) );
   7951          break;
   7952 
   7953       case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
   7954          DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7955          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7956          store( mkexpr(EA), mkexpr(frS) );
   7957          break;
   7958 
   7959       case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
   7960          if (rA_addr == 0)
   7961             return False;
   7962          DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7963          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7964          store( mkexpr(EA), mkexpr(frS) );
   7965          putIReg( rA_addr, mkexpr(EA) );
   7966          break;
   7967 
   7968       case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
   7969          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7970          DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7971          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7972          store( mkexpr(EA),
   7973                 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
   7974          break;
   7975 
   7976       default:
   7977          vex_printf("dis_fp_store(ppc)(opc2)\n");
   7978          return False;
   7979       }
   7980       break;
   7981 
   7982    default:
   7983       vex_printf("dis_fp_store(ppc)(opc1)\n");
   7984       return False;
   7985    }
   7986    return True;
   7987 }
   7988 
   7989 
   7990 
   7991 /*
   7992   Floating Point Arith Instructions
   7993 */
   7994 static Bool dis_fp_arith ( UInt theInstr )
   7995 {
   7996    /* A-Form */
   7997    UChar opc1     = ifieldOPC(theInstr);
   7998    UChar frD_addr = ifieldRegDS(theInstr);
   7999    UChar frA_addr = ifieldRegA(theInstr);
   8000    UChar frB_addr = ifieldRegB(theInstr);
   8001    UChar frC_addr = ifieldRegC(theInstr);
   8002    UChar opc2     = ifieldOPClo5(theInstr);
   8003    UChar flag_rC  = ifieldBIT0(theInstr);
   8004 
   8005    IRTemp  frD = newTemp(Ity_F64);
   8006    IRTemp  frA = newTemp(Ity_F64);
   8007    IRTemp  frB = newTemp(Ity_F64);
   8008    IRTemp  frC = newTemp(Ity_F64);
   8009    IRExpr* rm  = get_IR_roundingmode();
   8010 
   8011    /* By default, we will examine the results of the operation and set
   8012       fpscr[FPRF] accordingly. */
   8013    Bool set_FPRF = True;
   8014 
   8015    /* By default, if flag_RC is set, we will clear cr1 after the
   8016       operation.  In reality we should set cr1 to indicate the
   8017       exception status of the operation, but since we're not
   8018       simulating exceptions, the exception status will appear to be
   8019       zero.  Hence cr1 should be cleared if this is a . form insn. */
   8020    Bool clear_CR1 = True;
   8021 
   8022    assign( frA, getFReg(frA_addr));
   8023    assign( frB, getFReg(frB_addr));
   8024    assign( frC, getFReg(frC_addr));
   8025 
   8026    switch (opc1) {
   8027    case 0x3B:
   8028       switch (opc2) {
   8029       case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
   8030          if (frC_addr != 0)
   8031             return False;
   8032          DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8033              frD_addr, frA_addr, frB_addr);
   8034          assign( frD, triop( Iop_DivF64r32,
   8035                              rm, mkexpr(frA), mkexpr(frB) ));
   8036          break;
   8037 
   8038       case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
   8039          if (frC_addr != 0)
   8040             return False;
   8041          DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8042              frD_addr, frA_addr, frB_addr);
   8043          assign( frD, triop( Iop_SubF64r32,
   8044                              rm, mkexpr(frA), mkexpr(frB) ));
   8045          break;
   8046 
   8047       case 0x15: // fadds (Floating Add Single, PPC32 p401)
   8048          if (frC_addr != 0)
   8049             return False;
   8050          DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8051              frD_addr, frA_addr, frB_addr);
   8052          assign( frD, triop( Iop_AddF64r32,
   8053                              rm, mkexpr(frA), mkexpr(frB) ));
   8054          break;
   8055 
   8056       case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
   8057          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   8058          if (frA_addr != 0 || frC_addr != 0)
   8059             return False;
   8060          DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
   8061              frD_addr, frB_addr);
   8062          // however illogically, on ppc970 this insn behaves identically
   8063          // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
   8064          assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
   8065          break;
   8066 
   8067       case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
   8068          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   8069          if (frA_addr != 0 || frC_addr != 0)
   8070             return False;
   8071          DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
   8072              frD_addr, frB_addr);
   8073          { IRExpr* ieee_one
   8074               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   8075            assign( frD, triop( Iop_DivF64r32,
   8076                                rm,
   8077                                ieee_one, mkexpr(frB) ));
   8078          }
   8079          break;
   8080 
   8081       case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
   8082          if (frB_addr != 0)
   8083             return False;
   8084          DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8085              frD_addr, frA_addr, frC_addr);
   8086          assign( frD, triop( Iop_MulF64r32,
   8087                              rm, mkexpr(frA), mkexpr(frC) ));
   8088          break;
   8089 
   8090       case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
   8091          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   8092          // Undocumented instruction?
   8093          if (frA_addr != 0 || frC_addr != 0)
   8094             return False;
   8095          DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
   8096              frD_addr, frB_addr);
   8097          assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
   8098          break;
   8099 
   8100       default:
   8101          vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
   8102          return False;
   8103       }
   8104       break;
   8105 
   8106    case 0x3F:
   8107       switch (opc2) {
   8108       case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
   8109          if (frC_addr != 0)
   8110             return False;
   8111          DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8112              frD_addr, frA_addr, frB_addr);
   8113          assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
   8114          break;
   8115 
   8116       case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
   8117          if (frC_addr != 0)
   8118             return False;
   8119          DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8120              frD_addr, frA_addr, frB_addr);
   8121          assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
   8122          break;
   8123 
   8124       case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
   8125          if (frC_addr != 0)
   8126             return False;
   8127          DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8128              frD_addr, frA_addr, frB_addr);
   8129          assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
   8130          break;
   8131 
   8132       case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
   8133          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   8134          if (frA_addr != 0 || frC_addr != 0)
   8135             return False;
   8136          DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
   8137              frD_addr, frB_addr);
   8138          assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
   8139          break;
   8140 
   8141       case 0x17: { // fsel (Floating Select, PPC32 p426)
   8142          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   8143          IRTemp cc    = newTemp(Ity_I32);
   8144          IRTemp cc_b0 = newTemp(Ity_I32);
   8145 
   8146          DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8147              frD_addr, frA_addr, frC_addr, frB_addr);
   8148 
   8149          // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
   8150          // => GT|EQ == (cc & 0x1 == 0)
   8151          assign( cc, binop(Iop_CmpF64, mkexpr(frA),
   8152                                        IRExpr_Const(IRConst_F64(0))) );
   8153          assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
   8154 
   8155          // frD = (frA >= 0.0) ? frC : frB
   8156          //     = (cc_b0 == 0) ? frC : frB
   8157          assign( frD,
   8158                  IRExpr_ITE(
   8159                     binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
   8160                     mkexpr(frC),
   8161                     mkexpr(frB) ));
   8162 
   8163          /* One of the rare ones which don't mess with FPRF */
   8164          set_FPRF = False;
   8165          break;
   8166       }
   8167 
   8168       case 0x18: // fre (Floating Reciprocal Estimate)
   8169          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   8170          // Note: unclear whether this insn really exists or not
   8171          // ppc970 doesn't have it, but POWER5 does
   8172          if (frA_addr != 0 || frC_addr != 0)
   8173             return False;
   8174          DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
   8175              frD_addr, frB_addr);
   8176          { IRExpr* ieee_one
   8177               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   8178            assign( frD, triop( Iop_DivF64,
   8179                                rm,
   8180                                ieee_one, mkexpr(frB) ));
   8181          }
   8182          break;
   8183 
   8184       case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
   8185          if (frB_addr != 0)
   8186             vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
   8187          DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8188              frD_addr, frA_addr, frC_addr);
   8189          assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
   8190          break;
   8191 
   8192       case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
   8193          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   8194          if (frA_addr != 0 || frC_addr != 0)
   8195             return False;
   8196          DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
   8197              frD_addr, frB_addr);
   8198          assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
   8199          break;
   8200 
   8201       default:
   8202          vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
   8203          return False;
   8204       }
   8205       break;
   8206 
   8207    default:
   8208       vex_printf("dis_fp_arith(ppc)(opc1)\n");
   8209       return False;
   8210    }
   8211 
   8212    putFReg( frD_addr, mkexpr(frD) );
   8213 
   8214    if (set_FPRF) {
   8215       // XXX XXX XXX FIXME
   8216       // set FPRF from frD
   8217    }
   8218 
   8219    if (flag_rC && clear_CR1) {
   8220       putCR321( 1, mkU8(0) );
   8221       putCR0( 1, mkU8(0) );
   8222    }
   8223 
   8224    return True;
   8225 }
   8226 
   8227 
   8228 
   8229 /*
   8230   Floating Point Mult-Add Instructions
   8231 */
   8232 static Bool dis_fp_multadd ( UInt theInstr )
   8233 {
   8234    /* A-Form */
   8235    UChar opc1     = ifieldOPC(theInstr);
   8236    UChar frD_addr = ifieldRegDS(theInstr);
   8237    UChar frA_addr = ifieldRegA(theInstr);
   8238    UChar frB_addr = ifieldRegB(theInstr);
   8239    UChar frC_addr = ifieldRegC(theInstr);
   8240    UChar opc2     = ifieldOPClo5(theInstr);
   8241    UChar flag_rC  = ifieldBIT0(theInstr);
   8242 
   8243    IRTemp  frD = newTemp(Ity_F64);
   8244    IRTemp  frA = newTemp(Ity_F64);
   8245    IRTemp  frB = newTemp(Ity_F64);
   8246    IRTemp  frC = newTemp(Ity_F64);
   8247    IRTemp  rmt = newTemp(Ity_I32);
   8248    IRTemp  tmp = newTemp(Ity_F64);
   8249    IRTemp  sign_tmp = newTemp(Ity_I64);
   8250    IRTemp  nan_mask = newTemp(Ity_I32);
   8251    IRExpr* rm;
   8252 
   8253    /* By default, we will examine the results of the operation and set
   8254       fpscr[FPRF] accordingly. */
   8255    Bool set_FPRF = True;
   8256 
   8257    /* By default, if flag_RC is set, we will clear cr1 after the
   8258       operation.  In reality we should set cr1 to indicate the
   8259       exception status of the operation, but since we're not
   8260       simulating exceptions, the exception status will appear to be
   8261       zero.  Hence cr1 should be cleared if this is a . form insn. */
   8262    Bool clear_CR1 = True;
   8263 
   8264    /* Bind the rounding mode expression to a temp; there's no
   8265       point in creating gratuitous CSEs, as we know we'll need
   8266       to use it twice. */
   8267    assign( rmt, get_IR_roundingmode() );
   8268    rm = mkexpr(rmt);
   8269 
   8270    assign( frA, getFReg(frA_addr));
   8271    assign( frB, getFReg(frB_addr));
   8272    assign( frC, getFReg(frC_addr));
   8273 
   8274    /* The rounding in this is all a bit dodgy.  The idea is to only do
   8275       one rounding.  That clearly isn't achieveable without dedicated
   8276       four-input IR primops, although in the single precision case we
   8277       can sort-of simulate it by doing the inner multiply in double
   8278       precision.
   8279 
   8280       In the negated cases, the negation happens after rounding. */
   8281 
   8282    switch (opc1) {
   8283    case 0x3B:
   8284       switch (opc2) {
   8285       case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
   8286          DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8287              frD_addr, frA_addr, frC_addr, frB_addr);
   8288          assign( frD, qop( Iop_MSubF64r32, rm,
   8289                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8290          break;
   8291 
   8292       case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
   8293          DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8294              frD_addr, frA_addr, frC_addr, frB_addr);
   8295          assign( frD, qop( Iop_MAddF64r32, rm,
   8296                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8297          break;
   8298 
   8299       case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
   8300       case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
   8301 
   8302          if (opc2 == 0x1E) {
   8303             DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8304                      frD_addr, frA_addr, frC_addr, frB_addr);
   8305             assign( tmp, qop( Iop_MSubF64r32, rm,
   8306                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   8307          } else {
   8308             DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8309                      frD_addr, frA_addr, frC_addr, frB_addr);
   8310             assign( tmp, qop( Iop_MAddF64r32, rm,
   8311                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   8312          }
   8313 
   8314          assign( nan_mask, Check_NaN( mkexpr( tmp ),
   8315                                       mkU32( NANmaskSingle ) ) );
   8316          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
   8317                                                mkexpr( nan_mask ) ) );
   8318          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
   8319          break;
   8320 
   8321       default:
   8322          vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
   8323          return False;
   8324       }
   8325       break;
   8326 
   8327    case 0x3F:
   8328       switch (opc2) {
   8329       case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
   8330          DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8331              frD_addr, frA_addr, frC_addr, frB_addr);
   8332          assign( frD, qop( Iop_MSubF64, rm,
   8333                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8334          break;
   8335 
   8336       case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
   8337          DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8338              frD_addr, frA_addr, frC_addr, frB_addr);
   8339          assign( frD, qop( Iop_MAddF64, rm,
   8340                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8341          break;
   8342 
   8343       case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
   8344       case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
   8345 
   8346          if (opc2 == 0x1E) {
   8347             DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8348                      frD_addr, frA_addr, frC_addr, frB_addr);
   8349             assign( tmp, qop( Iop_MSubF64, rm,
   8350                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   8351          } else {
   8352             DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8353                      frD_addr, frA_addr, frC_addr, frB_addr);
   8354             assign( tmp, qop( Iop_MAddF64, rm,
   8355                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8356          }
   8357 
   8358          assign( nan_mask, Check_NaN( mkexpr( tmp ),
   8359                                       mkU32( NANmaskDouble ) ) );
   8360          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
   8361                                                mkexpr( nan_mask ) ) );
   8362          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
   8363          break;
   8364 
   8365       default:
   8366          vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
   8367          return False;
   8368       }
   8369       break;
   8370 
   8371    default:
   8372       vex_printf("dis_fp_multadd(ppc)(opc1)\n");
   8373       return False;
   8374    }
   8375 
   8376    putFReg( frD_addr, mkexpr(frD) );
   8377 
   8378    if (set_FPRF) {
   8379       // XXX XXX XXX FIXME
   8380       // set FPRF from frD
   8381    }
   8382 
   8383    if (flag_rC && clear_CR1) {
   8384       putCR321( 1, mkU8(0) );
   8385       putCR0( 1, mkU8(0) );
   8386    }
   8387 
   8388    return True;
   8389 }
   8390 
   8391 /*
   8392  * fe_flag is set to 1 if any of the following conditions occurs:
   8393  *  - The floating-point operand in register FRB is a Zero, a
   8394  *    NaN, an Infinity, or a negative value.
   8395  *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
   8396  *  Otherwise fe_flag is set to 0.
   8397  *
   8398  * fg_flag is set to 1 if either of the following conditions occurs.
   8399  *   - The floating-point operand in register FRB is a Zero, an
   8400  *     Infinity, or a denormalized value.
   8401  *  Otherwise fg_flag is set to 0.
   8402  *
   8403  */
   8404 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
   8405 {
   8406    // The following temps are for holding intermediate results
   8407    IRTemp e_b = newTemp(Ity_I32);
   8408    IRExpr * fe_flag,  * fg_flag;
   8409    IRTemp frB_exp_shR = newTemp(Ity_I32);
   8410    UInt bias = sp? 127 : 1023;
   8411    IRExpr * frbNaN, * frbDenorm, * frBNeg;
   8412    IRExpr * eb_LTE;
   8413    IRTemp  frbZero_tmp = newTemp(Ity_I1);
   8414    IRTemp  frbInf_tmp = newTemp(Ity_I1);
   8415    *fe_flag_tmp = newTemp(Ity_I32);
   8416    *fg_flag_tmp = newTemp(Ity_I32);
   8417    assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
   8418    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
   8419 
   8420    //////////////////  fe_flag tests BEGIN //////////////////////
   8421    /* We first do all tests that may result in setting fe_flag to '1'.
   8422     * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
   8423     * for details.)
   8424     */
   8425    frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
   8426    assign( frbInf_tmp, is_Inf(frB_Int, sp) );
   8427    assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
   8428    {
   8429       // Test_value = -970 for double precision
   8430       UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
   8431       eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
   8432    }
   8433    frBNeg = binop( Iop_CmpEQ32,
   8434                    binop( Iop_Shr32,
   8435                           sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
   8436                           mkU8( 31 ) ),
   8437                    mkU32( 1 ) );
   8438    //////////////////  fe_flag tests END //////////////////////
   8439 
   8440    //////////////////  fg_flag tests BEGIN //////////////////////
   8441    /*
   8442     * The following tests were already performed above in the fe_flag
   8443     * tests.  So these conditions will result in both fe_ and fg_ flags
   8444     * being set.
   8445     *   - Test if FRB is Zero
   8446     *   - Test if FRB is an Infinity
   8447     */
   8448 
   8449    /*
   8450     * Test if FRB holds a denormalized value.  A denormalized value is one where
   8451     * the exp is 0 and the fraction is non-zero.
   8452     */
   8453    if (sp) {
   8454       IRTemp frac_part = newTemp(Ity_I32);
   8455       assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
   8456       frbDenorm
   8457                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
   8458                          binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
   8459    } else {
   8460       IRExpr * hi32, * low32, * fraction_is_nonzero;
   8461       IRTemp frac_part = newTemp(Ity_I64);
   8462 
   8463       assign( frac_part, FP_FRAC_PART(frB_Int) );
   8464       hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   8465       low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   8466       fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   8467                                                 mkU32( 0 ) );
   8468       frbDenorm
   8469                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
   8470                          fraction_is_nonzero );
   8471    }
   8472    //////////////////  fg_flag tests END //////////////////////
   8473 
   8474    /////////////////////////
   8475    fe_flag = mkOR1( mkexpr( frbZero_tmp ),
   8476                     mkOR1( frbNaN,
   8477                            mkOR1( mkexpr( frbInf_tmp ),
   8478                                   mkOR1( frBNeg, eb_LTE ) ) ) );
   8479 
   8480    fe_flag = unop(Iop_1Uto32, fe_flag);
   8481 
   8482    fg_flag = mkOR1( mkexpr( frbZero_tmp ),
   8483                     mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
   8484    fg_flag = unop(Iop_1Uto32, fg_flag);
   8485    assign (*fg_flag_tmp, fg_flag);
   8486    assign (*fe_flag_tmp, fe_flag);
   8487 }
   8488 /*
   8489  * fe_flag is set to 1 if any of the following conditions occurs:
   8490  *  - The double-precision floating-point operand in register FRA is a NaN or an
   8491  *    Infinity.
   8492  *  - The double-precision floating-point operand in register FRB is a Zero, a
   8493  *    NaN, or an Infinity.
   8494  *  - e_b is less than or equal to -1022.
   8495  *  - e_b is greater than or equal to 1021.
   8496  *  - The double-precision floating-point operand in register FRA is not a zero
   8497  *    and the difference, e_a - e_b, is greater than or equal to 1023.
   8498  *  - The double-precision floating-point operand in register FRA is not a zero
   8499  *    and the difference, e_a - e_b, is less than or equal to -1021.
   8500  *  - The double-precision floating-point operand in register FRA is not a zero
   8501  *    and e_a is less than or equal to -970
   8502  *  Otherwise fe_flag is set to 0.
   8503  *
   8504  * fg_flag is set to 1 if either of the following conditions occurs.
   8505  *   - The double-precision floating-point operand in register FRA is an Infinity.
   8506  *   - The double-precision floating-point operand in register FRB is a Zero, an
   8507  *     Infinity, or a denormalized value.
   8508  *  Otherwise fg_flag is set to 0.
   8509  *
   8510  */
   8511 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
   8512 {
   8513    // The following temps are for holding intermediate results
   8514    IRTemp e_a = newTemp(Ity_I32);
   8515    IRTemp e_b = newTemp(Ity_I32);
   8516    IRTemp frA_exp_shR = newTemp(Ity_I32);
   8517    IRTemp frB_exp_shR = newTemp(Ity_I32);
   8518 
   8519    UInt bias = sp? 127 : 1023;
   8520    *fe_flag_tmp = newTemp(Ity_I32);
   8521    *fg_flag_tmp = newTemp(Ity_I32);
   8522 
   8523    /* The following variables hold boolean results from tests
   8524     * that are OR'ed together for setting the fe_ and fg_ flags.
   8525     * For some cases, the booleans are used more than once, so
   8526     * I make those IRTemp's instead of IRExpr's.
   8527     */
   8528    IRExpr * fraNaN, * frbNaN, * frbDenorm;
   8529    IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
   8530    IRTemp  fraInf_tmp = newTemp(Ity_I1);
   8531    IRTemp  frbZero_tmp = newTemp(Ity_I1);
   8532    IRTemp  frbInf_tmp = newTemp(Ity_I1);
   8533    IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
   8534 
   8535 /* The following are the flags that are set by OR'ing the results of
   8536  * all the tests done for tdiv.  These flags are the input to the specified CR.
   8537  */
   8538    IRExpr * fe_flag, * fg_flag;
   8539 
   8540    // Create temps that will be used throughout the following tests.
   8541    assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
   8542    assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
   8543    /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
   8544    assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
   8545    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
   8546 
   8547 
   8548    //////////////////  fe_flag tests BEGIN //////////////////////
   8549    /* We first do all tests that may result in setting fe_flag to '1'. */
   8550 
   8551    /*
   8552     * Test if the double-precision floating-point operand in register FRA is
   8553     * a NaN:
   8554     */
   8555    fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
   8556    /*
   8557     * Test if the double-precision floating-point operand in register FRA is
   8558     * an Infinity.
   8559     */
   8560    assign(fraInf_tmp, is_Inf(frA_int, sp));
   8561 
   8562    /*
   8563     * Test if the double-precision floating-point operand in register FRB is
   8564     * a NaN:
   8565     */
   8566    frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
   8567    /*
   8568     * Test if the double-precision floating-point operand in register FRB is
   8569     * an Infinity.
   8570     */
   8571    assign( frbInf_tmp, is_Inf(frB_int, sp) );
   8572    /*
   8573     * Test if the double-precision floating-point operand in register FRB is
   8574     * a Zero.
   8575     */
   8576    assign( frbZero_tmp, is_Zero(frB_int, sp) );
   8577 
   8578    /*
   8579     * Test if e_b <= -1022 for double precision;
   8580     * or e_b <= -126 for single precision
   8581     */
   8582    {
   8583       UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
   8584       eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
   8585    }
   8586 
   8587    /*
   8588     * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
   8589     * or e_b >= -125 (125 < e_b) for single precision
   8590     */
   8591    {
   8592       Int test_value = sp ? 125 : 1021;
   8593       eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
   8594    }
   8595 
   8596    /*
   8597     * Test if FRA != Zero and (e_a - e_b) >= bias
   8598     */
   8599    assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
   8600    ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
   8601                        binop( Iop_CmpLT32S, mkU32( bias ),
   8602                               binop( Iop_Sub32, mkexpr( e_a ),
   8603                                      mkexpr( e_b ) ) ) );
   8604 
   8605    /*
   8606     * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
   8607     */
   8608    {
   8609       UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
   8610 
   8611       ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
   8612                           binop( Iop_CmpLE32S,
   8613                                  binop( Iop_Sub32,
   8614                                         mkexpr( e_a ),
   8615                                         mkexpr( e_b ) ),
   8616                                         mkU32( test_value ) ) );
   8617    }
   8618 
   8619    /*
   8620     * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
   8621     */
   8622    {
   8623       UInt test_value = 0xfffffc36;  //Int test_value = -970;
   8624 
   8625       ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
   8626                                                         mkexpr( e_a ),
   8627                                                         mkU32( test_value ) ) );
   8628    }
   8629    //////////////////  fe_flag tests END //////////////////////
   8630 
   8631    //////////////////  fg_flag tests BEGIN //////////////////////
   8632    /*
   8633     * The following tests were already performed above in the fe_flag
   8634     * tests.  So these conditions will result in both fe_ and fg_ flags
   8635     * being set.
   8636     *   - Test if FRA is an Infinity
   8637     *   - Test if FRB ix Zero
   8638     *   - Test if FRB is an Infinity
   8639     */
   8640 
   8641    /*
   8642     * Test if FRB holds a denormalized value.  A denormalized value is one where
   8643     * the exp is 0 and the fraction is non-zero.
   8644     */
   8645    {
   8646       IRExpr * fraction_is_nonzero;
   8647 
   8648       if (sp) {
   8649          fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
   8650                                       mkU32( 0 ) );
   8651       } else {
   8652          IRExpr * hi32, * low32;
   8653          IRTemp frac_part = newTemp(Ity_I64);
   8654          assign( frac_part, FP_FRAC_PART(frB_int) );
   8655 
   8656          hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   8657          low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   8658          fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   8659                                       mkU32( 0 ) );
   8660       }
   8661       frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
   8662                                  mkU32( 0x0 ) ), fraction_is_nonzero );
   8663 
   8664    }
   8665    //////////////////  fg_flag tests END //////////////////////
   8666 
   8667    fe_flag
   8668    = mkOR1(
   8669             fraNaN,
   8670             mkOR1(
   8671                    mkexpr( fraInf_tmp ),
   8672                    mkOR1(
   8673                           mkexpr( frbZero_tmp ),
   8674                           mkOR1(
   8675                                  frbNaN,
   8676                                  mkOR1(
   8677                                         mkexpr( frbInf_tmp ),
   8678                                         mkOR1( eb_LTE,
   8679                                                mkOR1( eb_GTE,
   8680                                                       mkOR1( ea_eb_GTE,
   8681                                                              mkOR1( ea_eb_LTE,
   8682                                                                     ea_LTE ) ) ) ) ) ) ) ) );
   8683 
   8684    fe_flag = unop(Iop_1Uto32, fe_flag);
   8685 
   8686    fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
   8687                                                  mkOR1( mkexpr( frbInf_tmp ),
   8688                                                         frbDenorm ) ) );
   8689    fg_flag = unop(Iop_1Uto32, fg_flag);
   8690    assign(*fe_flag_tmp, fe_flag);
   8691    assign(*fg_flag_tmp, fg_flag);
   8692 }
   8693 
   8694 /* See description for _do_fp_tdiv() above. */
   8695 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
   8696 {
   8697    IRTemp  fe_flag, fg_flag;
   8698    /////////////////////////
   8699    /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   8700     * where fl_flag == 1 on ppc64.
   8701     */
   8702    IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
   8703    fe_flag = fg_flag = IRTemp_INVALID;
   8704    _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
   8705    return binop( Iop_Or32,
   8706                  binop( Iop_Or32,
   8707                         binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
   8708                         binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   8709                  binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
   8710 }
   8711 
   8712 static Bool dis_fp_tests ( UInt theInstr )
   8713 {
   8714    UChar opc1     = ifieldOPC(theInstr);
   8715    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   8716    UChar frB_addr = ifieldRegB(theInstr);
   8717    UChar b0       = ifieldBIT0(theInstr);
   8718    UInt  opc2     = ifieldOPClo10(theInstr);
   8719    IRTemp frB_I64     = newTemp(Ity_I64);
   8720 
   8721    if (opc1 != 0x3F || b0 != 0 ){
   8722       vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
   8723       return False;
   8724    }
   8725    assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
   8726 
   8727    switch (opc2) {
   8728       case 0x080: // ftdiv
   8729       {
   8730          UChar frA_addr = ifieldRegA(theInstr);
   8731          IRTemp frA_I64     = newTemp(Ity_I64);
   8732          UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   8733          if (b21to22 != 0 ) {
   8734             vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
   8735             return False;
   8736          }
   8737 
   8738          assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
   8739          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
   8740 
   8741          DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   8742          break;
   8743       }
   8744       case 0x0A0: // ftsqrt
   8745       {
   8746          IRTemp flags = newTemp(Ity_I32);
   8747          IRTemp  fe_flag, fg_flag;
   8748          fe_flag = fg_flag = IRTemp_INVALID;
   8749          UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
   8750          if ( b18to22 != 0) {
   8751             vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
   8752             return False;
   8753          }
   8754          DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
   8755          do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
   8756          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   8757           * where fl_flag == 1 on ppc64.
   8758           */
   8759          assign( flags,
   8760                  binop( Iop_Or32,
   8761                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   8762                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   8763                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
   8764          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
   8765          break;
   8766       }
   8767 
   8768       default:
   8769          vex_printf("dis_fp_tests(ppc)(opc2)\n");
   8770          return False;
   8771 
   8772    }
   8773    return True;
   8774 }
   8775 
   8776 /*
   8777   Floating Point Compare Instructions
   8778 */
   8779 static Bool dis_fp_cmp ( UInt theInstr )
   8780 {
   8781    /* X-Form */
   8782    UChar opc1     = ifieldOPC(theInstr);
   8783    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   8784    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   8785    UChar frA_addr = ifieldRegA(theInstr);
   8786    UChar frB_addr = ifieldRegB(theInstr);
   8787    UInt  opc2     = ifieldOPClo10(theInstr);
   8788    UChar b0       = ifieldBIT0(theInstr);
   8789 
   8790    IRTemp ccIR    = newTemp(Ity_I32);
   8791    IRTemp ccPPC32 = newTemp(Ity_I32);
   8792 
   8793    IRTemp frA     = newTemp(Ity_F64);
   8794    IRTemp frB     = newTemp(Ity_F64);
   8795 
   8796    if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
   8797       vex_printf("dis_fp_cmp(ppc)(instr)\n");
   8798       return False;
   8799    }
   8800 
   8801    assign( frA, getFReg(frA_addr));
   8802    assign( frB, getFReg(frB_addr));
   8803 
   8804    assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
   8805 
   8806    /* Map compare result from IR to PPC32 */
   8807    /*
   8808      FP cmp result | PPC | IR
   8809      --------------------------
   8810      UN            | 0x1 | 0x45
   8811      EQ            | 0x2 | 0x40
   8812      GT            | 0x4 | 0x00
   8813      LT            | 0x8 | 0x01
   8814    */
   8815 
   8816    // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
   8817    //                    | ((ccIR ^ (ccIR>>6)) & 1)
   8818    assign(
   8819       ccPPC32,
   8820       binop(
   8821          Iop_Shl32,
   8822          mkU32(1),
   8823          unop(
   8824             Iop_32to8,
   8825             binop(
   8826                Iop_Or32,
   8827                binop(
   8828                   Iop_And32,
   8829                   unop(
   8830                      Iop_Not32,
   8831                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
   8832                   ),
   8833                   mkU32(2)
   8834                ),
   8835                binop(
   8836                   Iop_And32,
   8837                   binop(
   8838                      Iop_Xor32,
   8839                      mkexpr(ccIR),
   8840                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
   8841                   ),
   8842                   mkU32(1)
   8843                )
   8844             )
   8845          )
   8846       )
   8847    );
   8848 
   8849    putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   8850 
   8851    /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
   8852       putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
   8853    */
   8854    // XXX XXX XXX FIXME
   8855    // Also write the result into FPRF (it's not entirely clear how)
   8856 
   8857    /* Note: Differences between fcmpu and fcmpo are only in exception
   8858       flag settings, which aren't supported anyway. */
   8859    switch (opc2) {
   8860    case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
   8861       DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   8862       break;
   8863    case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
   8864       DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   8865       break;
   8866    default:
   8867       vex_printf("dis_fp_cmp(ppc)(opc2)\n");
   8868       return False;
   8869    }
   8870    return True;
   8871 }
   8872 
   8873 
   8874 
   8875 /*
   8876   Floating Point Rounding/Conversion Instructions
   8877 */
   8878 static Bool dis_fp_round ( UInt theInstr )
   8879 {
   8880    /* X-Form */
   8881    UChar opc1     = ifieldOPC(theInstr);
   8882    UChar b16to20  = ifieldRegA(theInstr);
   8883    UChar frD_addr = ifieldRegDS(theInstr);
   8884    UChar frB_addr = ifieldRegB(theInstr);
   8885    UInt  opc2     = ifieldOPClo10(theInstr);
   8886    UChar flag_rC  = ifieldBIT0(theInstr);
   8887 
   8888    IRTemp  frD     = newTemp(Ity_F64);
   8889    IRTemp  frB     = newTemp(Ity_F64);
   8890    IRTemp  r_tmp32 = newTemp(Ity_I32);
   8891    IRTemp  r_tmp64 = newTemp(Ity_I64);
   8892    IRExpr* rm      = get_IR_roundingmode();
   8893 
   8894    /* By default, we will examine the results of the operation and set
   8895       fpscr[FPRF] accordingly. */
   8896    Bool set_FPRF = True;
   8897 
   8898    /* By default, if flag_RC is set, we will clear cr1 after the
   8899       operation.  In reality we should set cr1 to indicate the
   8900       exception status of the operation, but since we're not
   8901       simulating exceptions, the exception status will appear to be
   8902       zero.  Hence cr1 should be cleared if this is a . form insn. */
   8903    Bool clear_CR1 = True;
   8904    if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
   8905       vex_printf("dis_fp_round(ppc)(instr)\n");
   8906       return False;
   8907    }
   8908 
   8909    assign( frB, getFReg(frB_addr));
   8910    if (opc1 == 0x3B) {
   8911       /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
   8912        * they're very similar to the other instructions handled here, but have
   8913        * a different primary opcode.
   8914        */
   8915       switch (opc2) {
   8916          case 0x34E: // fcfids (Float convert from signed DWord to single precision)
   8917             DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8918             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   8919             assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
   8920                                                               mkexpr( r_tmp64 ) ) ) );
   8921             goto putFR;
   8922 
   8923          case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
   8924             DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8925             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   8926             assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
   8927             goto putFR;
   8928       }
   8929    }
   8930 
   8931 
   8932    switch (opc2) {
   8933    case 0x00C: // frsp (Float Round to Single, PPC32 p423)
   8934       DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8935       assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
   8936       break;
   8937 
   8938    case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
   8939       DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8940       assign( r_tmp32,
   8941               binop(Iop_F64toI32S, rm, mkexpr(frB)) );
   8942       assign( frD, unop( Iop_ReinterpI64asF64,
   8943                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   8944       /* FPRF is undefined after fctiw.  Leave unchanged. */
   8945       set_FPRF = False;
   8946       break;
   8947 
   8948    case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
   8949       DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8950       assign( r_tmp32,
   8951               binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
   8952       assign( frD, unop( Iop_ReinterpI64asF64,
   8953                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   8954       /* FPRF is undefined after fctiwz.  Leave unchanged. */
   8955       set_FPRF = False;
   8956       break;
   8957 
   8958    case 0x08F: case 0x08E: // fctiwu[z]
   8959       DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
   8960                flag_rC ? ".":"", frD_addr, frB_addr);
   8961       assign( r_tmp32,
   8962               binop( Iop_F64toI32U,
   8963                      opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
   8964                      mkexpr( frB ) ) );
   8965       assign( frD, unop( Iop_ReinterpI64asF64,
   8966                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   8967       /* FPRF is undefined after fctiwz.  Leave unchanged. */
   8968       set_FPRF = False;
   8969       break;
   8970 
   8971 
   8972    case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
   8973       DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8974       assign( r_tmp64,
   8975               binop(Iop_F64toI64S, rm, mkexpr(frB)) );
   8976       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   8977       /* FPRF is undefined after fctid.  Leave unchanged. */
   8978       set_FPRF = False;
   8979       break;
   8980 
   8981    case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
   8982       DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8983       assign( r_tmp64,
   8984               binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   8985       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   8986       /* FPRF is undefined after fctidz.  Leave unchanged. */
   8987       set_FPRF = False;
   8988       break;
   8989 
   8990    case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
   8991    {
   8992       DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
   8993                flag_rC ? ".":"", frD_addr, frB_addr);
   8994       assign( r_tmp64,
   8995               binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
   8996       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   8997       /* FPRF is undefined after fctidz.  Leave unchanged. */
   8998       set_FPRF = False;
   8999       break;
   9000    }
   9001    case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
   9002       DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9003       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   9004       assign( frD,
   9005               binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
   9006       break;
   9007 
   9008    case 0x3CE: // fcfidu (Float convert from unsigned DWord)
   9009       DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9010       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   9011       assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
   9012       break;
   9013 
   9014    case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
   9015       switch(opc2) {
   9016       case 0x188: // frin (Floating Round to Integer Nearest)
   9017          DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9018          assign( r_tmp64,
   9019                  binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
   9020          break;
   9021       case 0x1A8: // friz (Floating Round to Integer Toward Zero)
   9022          DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9023          assign( r_tmp64,
   9024                  binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   9025          break;
   9026       case 0x1C8: // frip (Floating Round to Integer Plus)
   9027          DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9028          assign( r_tmp64,
   9029                  binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
   9030          break;
   9031       case 0x1E8: // frim (Floating Round to Integer Minus)
   9032          DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9033          assign( r_tmp64,
   9034                  binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
   9035          break;
   9036       }
   9037 
   9038       /* don't use the rounded integer if frB is outside -9e18..9e18 */
   9039       /* F64 has only log10(2**52) significant digits anyway */
   9040       /* need to preserve sign of zero */
   9041       /*   frD = (fabs(frB) > 9e18) ? frB :
   9042                (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
   9043       assign(frD, IRExpr_ITE(
   9044                      binop(Iop_CmpNE8,
   9045                            unop(Iop_32to8,
   9046                                 binop(Iop_CmpF64,
   9047                                       IRExpr_Const(IRConst_F64(9e18)),
   9048                                       unop(Iop_AbsF64, mkexpr(frB)))),
   9049                            mkU8(0)),
   9050                      mkexpr(frB),
   9051                      IRExpr_ITE(
   9052                         binop(Iop_CmpNE32,
   9053                               binop(Iop_Shr32,
   9054                                     unop(Iop_64HIto32,
   9055                                          unop(Iop_ReinterpF64asI64,
   9056                                               mkexpr(frB))),
   9057                                     mkU8(31)),
   9058                               mkU32(0)),
   9059                         unop(Iop_NegF64,
   9060                              unop( Iop_AbsF64,
   9061                                    binop(Iop_I64StoF64, mkU32(0),
   9062                                          mkexpr(r_tmp64)) )),
   9063                         binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
   9064                      )
   9065       ));
   9066       break;
   9067 
   9068    default:
   9069       vex_printf("dis_fp_round(ppc)(opc2)\n");
   9070       return False;
   9071    }
   9072 putFR:
   9073    putFReg( frD_addr, mkexpr(frD) );
   9074 
   9075    if (set_FPRF) {
   9076       // XXX XXX XXX FIXME
   9077       // set FPRF from frD
   9078    }
   9079 
   9080    if (flag_rC && clear_CR1) {
   9081       putCR321( 1, mkU8(0) );
   9082       putCR0( 1, mkU8(0) );
   9083    }
   9084 
   9085    return True;
   9086 }
   9087 
   9088 /*
   9089   Floating Point Pair Instructions
   9090 */
   9091 static Bool dis_fp_pair ( UInt theInstr )
   9092 {
   9093    /* X-Form/DS-Form */
   9094    UChar  opc1         = ifieldOPC(theInstr);
   9095    UChar  frT_hi_addr  = ifieldRegDS(theInstr);
   9096    UChar  frT_lo_addr  = frT_hi_addr + 1;
   9097    UChar  rA_addr      = ifieldRegA(theInstr);
   9098    UChar  rB_addr      = ifieldRegB(theInstr);
   9099    UInt  uimm16        = ifieldUIMM16(theInstr);
   9100    Int    simm16       = extend_s_16to32(uimm16);
   9101    UInt   opc2         = ifieldOPClo10(theInstr);
   9102    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   9103    IRTemp EA_hi        = newTemp(ty);
   9104    IRTemp EA_lo        = newTemp(ty);
   9105    IRTemp frT_hi       = newTemp(Ity_F64);
   9106    IRTemp frT_lo       = newTemp(Ity_F64);
   9107    UChar b0            = ifieldBIT0(theInstr);
   9108    Bool is_load        = 0;
   9109 
   9110    if ((frT_hi_addr %2) != 0) {
   9111       vex_printf("dis_fp_pair(ppc) : odd frT register\n");
   9112       return False;
   9113    }
   9114 
   9115    switch (opc1) {
   9116    case 0x1F: // register offset
   9117       switch(opc2) {
   9118       case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
   9119          DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   9120          is_load = 1;
   9121          break;
   9122       case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
   9123          DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   9124          break;
   9125       default:
   9126          vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
   9127          return False;
   9128       }
   9129 
   9130       if (b0 != 0) {
   9131          vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
   9132          return False;
   9133       }
   9134       assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
   9135       break;
   9136    case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
   9137       DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   9138       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   9139       is_load = 1;
   9140       break;
   9141    case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
   9142       DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   9143       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   9144       break;
   9145    default:   // immediate offset
   9146       vex_printf("dis_fp_pair(ppc)(instr)\n");
   9147       return False;
   9148    }
   9149 
   9150    if (mode64)
   9151       assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
   9152    else
   9153       assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
   9154 
   9155    assign( frT_hi, getFReg(frT_hi_addr) );
   9156    assign( frT_lo, getFReg(frT_lo_addr) );
   9157 
   9158    if (is_load) {
   9159       putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) );
   9160       putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) );
   9161    } else {
   9162       store( mkexpr(EA_hi), mkexpr(frT_hi) );
   9163       store( mkexpr(EA_lo), mkexpr(frT_lo) );
   9164    }
   9165 
   9166    return True;
   9167 }
   9168 
   9169 
   9170 /*
   9171   Floating Point Merge Instructions
   9172 */
   9173 static Bool dis_fp_merge ( UInt theInstr )
   9174 {
   9175    /* X-Form */
   9176    UInt  opc2     = ifieldOPClo10(theInstr);
   9177    UChar frD_addr = ifieldRegDS(theInstr);
   9178    UChar frA_addr = ifieldRegA(theInstr);
   9179    UChar frB_addr = ifieldRegB(theInstr);
   9180 
   9181    IRTemp frD = newTemp(Ity_F64);
   9182    IRTemp frA = newTemp(Ity_F64);
   9183    IRTemp frB = newTemp(Ity_F64);
   9184 
   9185    assign( frA, getFReg(frA_addr));
   9186    assign( frB, getFReg(frB_addr));
   9187 
   9188    switch (opc2) {
   9189    case 0x3c6: // fmrgew floating merge even word
   9190       DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
   9191 
   9192       assign( frD, unop( Iop_ReinterpI64asF64,
   9193                          binop( Iop_32HLto64,
   9194                                 unop( Iop_64HIto32,
   9195                                       unop( Iop_ReinterpF64asI64,
   9196                                             mkexpr(frA) ) ),
   9197                                 unop( Iop_64HIto32,
   9198                                       unop( Iop_ReinterpF64asI64,
   9199                                             mkexpr(frB) ) ) ) ) );
   9200    break;
   9201 
   9202    case 0x346: // fmrgow floating merge odd word
   9203       DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
   9204 
   9205       assign( frD, unop( Iop_ReinterpI64asF64,
   9206                          binop( Iop_32HLto64,
   9207                                 unop( Iop_64to32,
   9208                                       unop( Iop_ReinterpF64asI64,
   9209                                             mkexpr(frA) ) ),
   9210                                 unop( Iop_64to32,
   9211                                       unop( Iop_ReinterpF64asI64,
   9212                                             mkexpr(frB) ) ) ) ) );
   9213    break;
   9214 
   9215    default:
   9216       vex_printf("dis_fp_merge(ppc)(opc2)\n");
   9217       return False;
   9218    }
   9219 
   9220    putFReg( frD_addr, mkexpr(frD) );
   9221    return True;
   9222 }
   9223 
   9224 /*
   9225   Floating Point Move Instructions
   9226 */
   9227 static Bool dis_fp_move ( UInt theInstr )
   9228 {
   9229    /* X-Form */
   9230    UChar opc1     = ifieldOPC(theInstr);
   9231    UChar frD_addr = ifieldRegDS(theInstr);
   9232    UChar frA_addr = ifieldRegA(theInstr);
   9233    UChar frB_addr = ifieldRegB(theInstr);
   9234    UInt  opc2     = ifieldOPClo10(theInstr);
   9235    UChar flag_rC  = ifieldBIT0(theInstr);
   9236 
   9237    IRTemp frD = newTemp(Ity_F64);
   9238    IRTemp frB = newTemp(Ity_F64);
   9239    IRTemp itmpB = newTemp(Ity_F64);
   9240    IRTemp frA;
   9241    IRTemp signA;
   9242    IRTemp hiD;
   9243 
   9244    if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
   9245       vex_printf("dis_fp_move(ppc)(instr)\n");
   9246       return False;
   9247    }
   9248 
   9249    assign( frB, getFReg(frB_addr));
   9250 
   9251    switch (opc2) {
   9252    case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
   9253       DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
   9254           frB_addr);
   9255       signA = newTemp(Ity_I32);
   9256       hiD = newTemp(Ity_I32);
   9257       itmpB = newTemp(Ity_I64);
   9258       frA = newTemp(Ity_F64);
   9259       assign( frA, getFReg(frA_addr) );
   9260 
   9261       /* get A's sign bit */
   9262       assign(signA, binop(Iop_And32,
   9263                           unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
   9264                                                   mkexpr(frA))),
   9265                           mkU32(0x80000000)) );
   9266 
   9267       assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
   9268 
   9269       /* mask off B's sign bit and or in A's sign bit */
   9270       assign(hiD, binop(Iop_Or32,
   9271                         binop(Iop_And32,
   9272                               unop(Iop_64HIto32,
   9273                                    mkexpr(itmpB)),  /* frB's high 32 bits */
   9274                               mkU32(0x7fffffff)),
   9275                         mkexpr(signA)) );
   9276 
   9277       /* combine hiD/loB into frD */
   9278       assign( frD, unop(Iop_ReinterpI64asF64,
   9279                         binop(Iop_32HLto64,
   9280                               mkexpr(hiD),
   9281                               unop(Iop_64to32,
   9282                                    mkexpr(itmpB)))) );   /* frB's low 32 bits */
   9283       break;
   9284 
   9285    case 0x028: // fneg (Floating Negate, PPC32 p416)
   9286       DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9287       assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
   9288       break;
   9289 
   9290    case 0x048: // fmr (Floating Move Register, PPC32 p410)
   9291       DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9292       assign( frD, mkexpr(frB) );
   9293       break;
   9294 
   9295    case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
   9296       DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9297       assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
   9298       break;
   9299 
   9300    case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
   9301       DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9302       assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
   9303       break;
   9304 
   9305    default:
   9306       vex_printf("dis_fp_move(ppc)(opc2)\n");
   9307       return False;
   9308    }
   9309 
   9310    putFReg( frD_addr, mkexpr(frD) );
   9311 
   9312    /* None of these change FPRF.  cr1 is set in the usual way though,
   9313       if flag_rC is set. */
   9314 
   9315    if (flag_rC) {
   9316       putCR321( 1, mkU8(0) );
   9317       putCR0( 1, mkU8(0) );
   9318    }
   9319 
   9320    return True;
   9321 }
   9322 
   9323 
   9324 
   9325 /*
   9326   Floating Point Status/Control Register Instructions
   9327 */
   9328 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
   9329 {
   9330    /* Many forms - see each switch case */
   9331    UChar opc1    = ifieldOPC(theInstr);
   9332    UInt  opc2    = ifieldOPClo10(theInstr);
   9333    UChar flag_rC = ifieldBIT0(theInstr);
   9334 
   9335    if (opc1 != 0x3F) {
   9336       vex_printf("dis_fp_scr(ppc)(instr)\n");
   9337       return False;
   9338    }
   9339 
   9340    switch (opc2) {
   9341    case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
   9342       // Bit crbD of the FPSCR is set.
   9343       UChar crbD    = ifieldRegDS(theInstr);
   9344       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   9345 
   9346       if (b11to20 != 0) {
   9347          vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
   9348          return False;
   9349       }
   9350       DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
   9351       putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
   9352 		     1ULL << ( 31 - crbD ) );
   9353       break;
   9354    }
   9355 
   9356    case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
   9357       UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   9358       UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
   9359       UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
   9360       UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
   9361       IRTemp  tmp     = newTemp(Ity_I32);
   9362       IRExpr* fpscr_all;
   9363       if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
   9364          vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
   9365          return False;
   9366       }
   9367       DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
   9368       vassert(crfD < 8);
   9369       vassert(crfS < 8);
   9370       fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   9371       assign( tmp, binop(Iop_And32,
   9372                          binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
   9373                         mkU32(0xF)) );
   9374       putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
   9375       break;
   9376    }
   9377 
   9378    case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
   9379       // Bit crbD of the FPSCR is cleared.
   9380       UChar crbD    = ifieldRegDS(theInstr);
   9381       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   9382 
   9383       if (b11to20 != 0) {
   9384          vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
   9385          return False;
   9386       }
   9387       DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
   9388       putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
   9389       break;
   9390    }
   9391 
   9392    case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
   9393       UInt crfD     = IFIELD( theInstr, 23, 3 );
   9394       UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
   9395       UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
   9396       UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
   9397       UChar Wbit;
   9398 
   9399       if (b16to22 != 0 || b11 != 0) {
   9400          vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
   9401          return False;
   9402       }
   9403       DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM);
   9404       if (GX_level) {
   9405          /* This implies that Decimal Floating Point is supported, and the
   9406           * FPSCR must be managed as a 64-bit register.
   9407           */
   9408          Wbit = toUChar( IFIELD(theInstr, 16, 1) );
   9409       } else {
   9410          Wbit = 0;
   9411       }
   9412       crfD = crfD + (8 * (1 - Wbit) );
   9413       putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
   9414       break;
   9415    }
   9416 
   9417    case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
   9418       UChar   frD_addr  = ifieldRegDS(theInstr);
   9419       UInt    b11to20   = IFIELD(theInstr, 11, 10);
   9420       IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   9421       IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR,
   9422                                                  MASK_FPSCR_DRN );
   9423 
   9424       if (b11to20 != 0) {
   9425          vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
   9426          return False;
   9427       }
   9428       DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
   9429       putFReg( frD_addr,
   9430           unop( Iop_ReinterpI64asF64,
   9431                 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
   9432       break;
   9433    }
   9434 
   9435    case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
   9436       UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
   9437       UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
   9438       UChar frB_addr = ifieldRegB(theInstr);
   9439       IRTemp frB   = newTemp(Ity_F64);
   9440       IRTemp rB_64 = newTemp( Ity_I64 );
   9441       Int i;
   9442       ULong mask;
   9443       UChar Wbit;
   9444 #define BFP_MASK_SEED 0x3000000000000000ULL
   9445 #define DFP_MASK_SEED 0x7000000000000000ULL
   9446 
   9447       if (GX_level) {
   9448          /* This implies that Decimal Floating Point is supported, and the
   9449           * FPSCR must be managed as a 64-bit register.
   9450           */
   9451          Wbit = toUChar( IFIELD(theInstr, 16, 1) );
   9452       } else {
   9453          Wbit = 0;
   9454       }
   9455 
   9456       if (b25 == 1) {
   9457          /* new 64 bit move variant for power 6.  If L field (bit 25) is
   9458           * a one do a full 64 bit move.  Note, the FPSCR is not really
   9459           * properly modeled.  This instruciton only changes the value of
   9460           * the rounding mode.  The HW exception bits do not get set in
   9461           * the simulator.  1/12/09
   9462           */
   9463          DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
   9464          mask = 0xFF;
   9465 
   9466       } else {
   9467          DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
   9468          // Build 32bit mask from FM:
   9469          mask = 0;
   9470          for (i=0; i<8; i++) {
   9471             if ((FM & (1<<(7-i))) == 1) {
   9472                /* FPSCR field k is set to the contents of the corresponding
   9473                 * field of register FRB, where k = i+8x(1-W).  In the Power
   9474                 * ISA, register field numbering is from left to right, so field
   9475                 * 15 is the least significant field in a 64-bit register.  To
   9476                 * generate the mask, we set all the appropriate rounding mode
   9477                 * bits in the highest order nibble (field 0) and shift right
   9478                 * 'k x nibble length'.
   9479                 */
   9480                if (Wbit)
   9481                   mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
   9482                else
   9483                   mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
   9484             }
   9485          }
   9486       }
   9487       assign( frB, getFReg(frB_addr));
   9488       assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
   9489       putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
   9490       break;
   9491    }
   9492 
   9493    default:
   9494       vex_printf("dis_fp_scr(ppc)(opc2)\n");
   9495       return False;
   9496    }
   9497    return True;
   9498 }
   9499 
   9500 /*------------------------------------------------------------*/
   9501 /*--- Decimal Floating Point (DFP)  Helper functions       ---*/
   9502 /*------------------------------------------------------------*/
   9503 #define DFP_LONG  1
   9504 #define DFP_EXTND 2
   9505 #define DFP_LONG_BIAS   398
   9506 #define DFP_LONG_ENCODED_FIELD_MASK  0x1F00
   9507 #define DFP_EXTND_BIAS  6176
   9508 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
   9509 #define DFP_LONG_EXP_MSK   0XFF
   9510 #define DFP_EXTND_EXP_MSK  0XFFF
   9511 
   9512 #define DFP_G_FIELD_LONG_MASK     0x7FFC0000  // upper 32-bits only
   9513 #define DFP_LONG_GFIELD_RT_SHIFT  (63 - 13 - 32) // adj for upper 32-bits
   9514 #define DFP_G_FIELD_EXTND_MASK    0x7FFFC000  // upper 32-bits only
   9515 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
   9516 #define DFP_T_FIELD_LONG_MASK     0x3FFFF  // mask for upper 32-bits
   9517 #define DFP_T_FIELD_EXTND_MASK    0x03FFFF // mask for upper 32-bits
   9518 #define DFP_LONG_EXP_MAX          369      // biased max
   9519 #define DFP_LONG_EXP_MIN          0        // biased min
   9520 #define DFP_EXTND_EXP_MAX         6111     // biased max
   9521 #define DFP_EXTND_EXP_MIN         0        // biased min
   9522 #define DFP_LONG_MAX_SIG_DIGITS   16
   9523 #define DFP_EXTND_MAX_SIG_DIGITS  34
   9524 #define MAX_DIGITS_IN_STRING      8
   9525 
   9526 
   9527 #define  AND(x, y) binop( Iop_And32, x, y )
   9528 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
   9529 #define   OR(x, y) binop( Iop_Or32,  x, y )
   9530 #define  OR3(x, y, z)    OR( x, OR( y, z ) )
   9531 #define  OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
   9532 #define  NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1,  mkexpr( x ) ) ) )
   9533 
   9534 #define  SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
   9535 #define  SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
   9536 
   9537 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
   9538    (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
   9539     ((_b1) << 1) | ((_b0) << 0))
   9540 
   9541 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
   9542 {
   9543    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
   9544    IRTemp lmd_8_mask    = newTemp( Ity_I32 );
   9545    IRTemp lmd_9_mask    = newTemp( Ity_I32 );
   9546    IRTemp lmexp_00_mask = newTemp( Ity_I32 );
   9547    IRTemp lmexp_01_mask = newTemp( Ity_I32 );
   9548    IRTemp lmexp_10_mask = newTemp( Ity_I32 );
   9549    IRTemp lmd_07_val    = newTemp( Ity_I32 );
   9550    IRTemp lmd_8_val     = newTemp( Ity_I32 );
   9551    IRTemp lmd_9_val     = newTemp( Ity_I32 );
   9552 
   9553    /* The encodig is as follows:
   9554     * lmd - left most digit
   9555     * lme - left most 2-bits of the exponent
   9556     *
   9557     *    lmd
   9558     *   0 - 7    (lmexp << 3) | lmd
   9559     *     8      0b11000 (24 decimal) if lme=0b00;
   9560     *            0b11010 (26 decimal) if lme=0b01;
   9561     *            0b11100 (28 decimal) if lme=0b10;
   9562     *     9      0b11001 (25 decimal) if lme=0b00;
   9563     *            0b11011 (27 decimal) if lme=0b01;
   9564     *            0b11101 (29 decimal) if lme=0b10;
   9565     */
   9566 
   9567    /* Generate the masks for each condition */
   9568    assign( lmd_07_mask,
   9569            unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
   9570    assign( lmd_8_mask,
   9571            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
   9572    assign( lmd_9_mask,
   9573            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
   9574    assign( lmexp_00_mask,
   9575            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
   9576    assign( lmexp_01_mask,
   9577            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
   9578    assign( lmexp_10_mask,
   9579            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
   9580 
   9581    /* Generate the values for each LMD condition, assuming the condition
   9582     * is TRUE.
   9583     */
   9584    assign( lmd_07_val,
   9585            binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
   9586    assign( lmd_8_val,
   9587            binop( Iop_Or32,
   9588                   binop( Iop_Or32,
   9589                          binop( Iop_And32,
   9590                                 mkexpr( lmexp_00_mask ),
   9591                                 mkU32( 24 ) ),
   9592                          binop( Iop_And32,
   9593                                 mkexpr( lmexp_01_mask ),
   9594                                 mkU32( 26 ) ) ),
   9595                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
   9596    assign( lmd_9_val,
   9597            binop( Iop_Or32,
   9598                   binop( Iop_Or32,
   9599                          binop( Iop_And32,
   9600                                 mkexpr( lmexp_00_mask ),
   9601                                 mkU32( 25 ) ),
   9602                          binop( Iop_And32,
   9603                                 mkexpr( lmexp_01_mask ),
   9604                                 mkU32( 27 ) ) ),
   9605                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
   9606 
   9607    /* generate the result from the possible LMD values */
   9608    return binop( Iop_Or32,
   9609                  binop( Iop_Or32,
   9610                         binop( Iop_And32,
   9611                                mkexpr( lmd_07_mask ),
   9612                                mkexpr( lmd_07_val ) ),
   9613                         binop( Iop_And32,
   9614                                mkexpr( lmd_8_mask ),
   9615                                mkexpr( lmd_8_val ) ) ),
   9616                  binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
   9617 }
   9618 
   9619 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
   9620 {
   9621    /* Extract the exponent and the left most digit of the mantissa
   9622     * from the G field bits [0:4].
   9623     */
   9624    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
   9625    IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
   9626    IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
   9627    IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
   9628    IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
   9629    IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
   9630    IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
   9631 
   9632    IRTemp lmd_07_val = newTemp( Ity_I32 );
   9633    IRTemp lmd_8_val  = newTemp( Ity_I32 );
   9634    IRTemp lmd_9_val  = newTemp( Ity_I32 );
   9635 
   9636    /* The left most digit (LMD) encoding is as follows:
   9637     *    lmd
   9638     *   0 - 7    (lmexp << 3) | lmd
   9639     *     8      0b11000 (24 decimal) if lme=0b00;
   9640     *            0b11010 (26 decimal) if lme=0b01;
   9641     *            0b11100 (28 decimal) if lme=0b10
   9642     *     9      0b11001 (25 decimal) if lme=0b00;
   9643     *            0b11011 (27 decimal) if lme=0b01;
   9644     *            0b11101 (29 decimal) if lme=0b10;
   9645     */
   9646 
   9647    /* Generate the masks for each condition of LMD and exponent bits */
   9648    assign( lmd_07_mask,
   9649            unop( Iop_1Sto32, binop( Iop_CmpLE32U,
   9650                                     gfield_0_4,
   9651                                     mkU32( BITS5(1,0,1,1,1) ) ) ) );
   9652    assign( lmd_8_00_mask,
   9653            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9654                                     gfield_0_4,
   9655                                     mkU32( BITS5(1,1,0,0,0) ) ) ) );
   9656    assign( lmd_8_01_mask,
   9657            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9658                                     gfield_0_4,
   9659                                     mkU32( BITS5(1,1,0,1,0) ) ) ) );
   9660    assign( lmd_8_10_mask,
   9661            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9662                                     gfield_0_4,
   9663                                     mkU32( BITS5(1,1,1,0,0) ) ) ) );
   9664    assign( lmd_9_00_mask,
   9665            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9666                                     gfield_0_4,
   9667                                     mkU32( BITS5(1,1,0,0,1) ) ) ) );
   9668    assign( lmd_9_01_mask,
   9669            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9670                                     gfield_0_4,
   9671                                     mkU32( BITS5(1,1,0,1,1) ) ) ) );
   9672    assign( lmd_9_10_mask,
   9673            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9674                                     gfield_0_4,
   9675                                     mkU32( BITS5(1,1,1,0,1) ) ) ) );
   9676 
   9677    /* Generate the values for each LMD condition, assuming the condition
   9678     * is TRUE.
   9679     */
   9680    assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
   9681    assign( lmd_8_val, mkU32( 0x8 ) );
   9682    assign( lmd_9_val, mkU32( 0x9 ) );
   9683 
   9684    assign( *lmd,
   9685            OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
   9686                      AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
   9687                      AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
   9688                      OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
   9689                           AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
   9690                           AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
   9691                           AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
   9692                      ) ) );
   9693 }
   9694 
   9695 #define DIGIT1_SHR 4    // shift digit 1 to bottom 4 bits
   9696 #define DIGIT2_SHR 8    // shift digit 2 to bottom 4 bits
   9697 #define DIGIT3_SHR 12
   9698 #define DIGIT4_SHR 16
   9699 #define DIGIT5_SHR 20
   9700 #define DIGIT6_SHR 24
   9701 #define DIGIT7_SHR 28
   9702 
   9703 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
   9704 {
   9705    /* 60-bit BCD string stored in two 32-bit values.  Check that each,
   9706     * digit is a valid BCD number, i.e. less then 9.
   9707     */
   9708    IRTemp valid = newTemp( Ity_I32 );
   9709 
   9710    assign( valid,
   9711            AND4( AND4 ( unop( Iop_1Sto32,
   9712                               binop( Iop_CmpLE32U,
   9713                                      binop( Iop_And32,
   9714                                             bcd_l,
   9715                                             mkU32 ( 0xF ) ),
   9716                                       mkU32( 0x9 ) ) ),
   9717                         unop( Iop_1Sto32,
   9718                               binop( Iop_CmpLE32U,
   9719                                      binop( Iop_And32,
   9720                                             binop( Iop_Shr32,
   9721                                                    bcd_l,
   9722                                                    mkU8 ( DIGIT1_SHR ) ),
   9723                                              mkU32 ( 0xF ) ),
   9724                                       mkU32( 0x9 ) ) ),
   9725                         unop( Iop_1Sto32,
   9726                               binop( Iop_CmpLE32U,
   9727                                      binop( Iop_And32,
   9728                                             binop( Iop_Shr32,
   9729                                                    bcd_l,
   9730                                                    mkU8 ( DIGIT2_SHR ) ),
   9731                                             mkU32 ( 0xF ) ),
   9732                                       mkU32( 0x9 ) ) ),
   9733                         unop( Iop_1Sto32,
   9734                               binop( Iop_CmpLE32U,
   9735                                      binop( Iop_And32,
   9736                                             binop( Iop_Shr32,
   9737                                                    bcd_l,
   9738                                                    mkU8 ( DIGIT3_SHR ) ),
   9739                                              mkU32 ( 0xF ) ),
   9740                                       mkU32( 0x9 ) ) ) ),
   9741                  AND4 ( unop( Iop_1Sto32,
   9742                               binop( Iop_CmpLE32U,
   9743                                      binop( Iop_And32,
   9744                                             binop( Iop_Shr32,
   9745                                                    bcd_l,
   9746                                                    mkU8 ( DIGIT4_SHR ) ),
   9747                                             mkU32 ( 0xF ) ),
   9748                                      mkU32( 0x9 ) ) ),
   9749                         unop( Iop_1Sto32,
   9750                               binop( Iop_CmpLE32U,
   9751                                      binop( Iop_And32,
   9752                                             binop( Iop_Shr32,
   9753                                                    bcd_l,
   9754                                                    mkU8 ( DIGIT5_SHR ) ),
   9755                                             mkU32 ( 0xF ) ),
   9756                                      mkU32( 0x9 ) ) ),
   9757                         unop( Iop_1Sto32,
   9758                               binop( Iop_CmpLE32U,
   9759                                      binop( Iop_And32,
   9760                                             binop( Iop_Shr32,
   9761                                                    bcd_l,
   9762                                                    mkU8 ( DIGIT6_SHR ) ),
   9763                                             mkU32 ( 0xF ) ),
   9764                                      mkU32( 0x9 ) ) ),
   9765                         unop( Iop_1Sto32,
   9766                               binop( Iop_CmpLE32U,
   9767                                      binop( Iop_And32,
   9768                                             binop( Iop_Shr32,
   9769                                                    bcd_l,
   9770                                                    mkU8 ( DIGIT7_SHR ) ),
   9771                                             mkU32 ( 0xF ) ),
   9772                                      mkU32( 0x9 ) ) ) ),
   9773                  AND4( unop( Iop_1Sto32,
   9774                              binop( Iop_CmpLE32U,
   9775                                     binop( Iop_And32,
   9776                                            bcd_u,
   9777                                            mkU32 ( 0xF ) ),
   9778                                     mkU32( 0x9 ) ) ),
   9779                        unop( Iop_1Sto32,
   9780                              binop( Iop_CmpLE32U,
   9781                                     binop( Iop_And32,
   9782                                            binop( Iop_Shr32,
   9783                                                   bcd_u,
   9784                                                   mkU8 ( DIGIT1_SHR ) ),
   9785                                            mkU32 ( 0xF ) ),
   9786                                     mkU32( 0x9 ) ) ),
   9787                        unop( Iop_1Sto32,
   9788                              binop( Iop_CmpLE32U,
   9789                                     binop( Iop_And32,
   9790                                            binop( Iop_Shr32,
   9791                                                   bcd_u,
   9792                                                   mkU8 ( DIGIT2_SHR ) ),
   9793                                            mkU32 ( 0xF ) ),
   9794                                     mkU32( 0x9 ) ) ),
   9795                        unop( Iop_1Sto32,
   9796                              binop( Iop_CmpLE32U,
   9797                                     binop( Iop_And32,
   9798                                            binop( Iop_Shr32,
   9799                                                   bcd_u,
   9800                                                   mkU8 ( DIGIT3_SHR ) ),
   9801                                            mkU32 ( 0xF ) ),
   9802                                     mkU32( 0x9 ) ) ) ),
   9803                  AND4( unop( Iop_1Sto32,
   9804                              binop( Iop_CmpLE32U,
   9805                                     binop( Iop_And32,
   9806                                            binop( Iop_Shr32,
   9807                                                   bcd_u,
   9808                                                   mkU8 ( DIGIT4_SHR ) ),
   9809                                            mkU32 ( 0xF ) ),
   9810                                     mkU32( 0x9 ) ) ),
   9811                        unop( Iop_1Sto32,
   9812                              binop( Iop_CmpLE32U,
   9813                                     binop( Iop_And32,
   9814                                            binop( Iop_Shr32,
   9815                                                   bcd_u,
   9816                                                   mkU8 ( DIGIT5_SHR ) ),
   9817                                            mkU32 ( 0xF ) ),
   9818                                     mkU32( 0x9 ) ) ),
   9819                        unop( Iop_1Sto32,
   9820                              binop( Iop_CmpLE32U,
   9821                                     binop( Iop_And32,
   9822                                            binop( Iop_Shr32,
   9823                                                   bcd_u,
   9824                                                   mkU8 ( DIGIT6_SHR ) ),
   9825                                            mkU32 ( 0xF ) ),
   9826                                     mkU32( 0x9 ) ) ),
   9827                        unop( Iop_1Sto32,
   9828                              binop( Iop_CmpLE32U,
   9829                                     binop( Iop_And32,
   9830                                            binop( Iop_Shr32,
   9831                                                   bcd_u,
   9832                                                   mkU8 ( DIGIT7_SHR ) ),
   9833                                            mkU32 ( 0xF ) ),
   9834                                     mkU32( 0x9 ) ) ) ) ) );
   9835 
   9836    return unop( Iop_Not32, mkexpr( valid ) );
   9837 }
   9838 #undef DIGIT1_SHR
   9839 #undef DIGIT2_SHR
   9840 #undef DIGIT3_SHR
   9841 #undef DIGIT4_SHR
   9842 #undef DIGIT5_SHR
   9843 #undef DIGIT6_SHR
   9844 #undef DIGIT7_SHR
   9845 
   9846 static IRExpr * Generate_neg_sign_mask( IRExpr * sign )
   9847 {
   9848    return binop( Iop_Or32,
   9849                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
   9850                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
   9851                );
   9852 }
   9853 
   9854 static IRExpr * Generate_pos_sign_mask( IRExpr * sign )
   9855 {
   9856    return binop( Iop_Or32,
   9857                  binop( Iop_Or32,
   9858                         unop( Iop_1Sto32,
   9859                               binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
   9860                         unop( Iop_1Sto32,
   9861                               binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
   9862                  binop( Iop_Or32,
   9863                         unop( Iop_1Sto32,
   9864                               binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
   9865                         unop( Iop_1Sto32,
   9866                               binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
   9867 }
   9868 
   9869 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
   9870                                    IRExpr * neg_sign_mask )
   9871 {
   9872    return binop( Iop_Or32,
   9873                  binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
   9874                  binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
   9875 }
   9876 
   9877 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
   9878                                    IRExpr * pos_sign_mask,
   9879                                    IRExpr * neg_sign_mask )
   9880 /* first argument is all 1's if the BCD string had an invalid digit in it. */
   9881 {
   9882    return binop( Iop_Or32,
   9883                  invalid_bcd_mask,
   9884                  unop( Iop_1Sto32,
   9885                        binop( Iop_CmpEQ32,
   9886                               binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
   9887                               mkU32( 0x0 ) ) ) );
   9888 }
   9889 
   9890 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
   9891                                          IRTemp * top_12_l, IRTemp * mid_60_u,
   9892                                          IRTemp * mid_60_l, IRTemp * low_60_u,
   9893                                          IRTemp * low_60_l)
   9894 {
   9895    IRTemp tmplow60 = newTemp( Ity_I64 );
   9896    IRTemp tmpmid60 = newTemp( Ity_I64 );
   9897    IRTemp tmptop12 = newTemp( Ity_I64 );
   9898    IRTemp low_50   = newTemp( Ity_I64 );
   9899    IRTemp mid_50   = newTemp( Ity_I64 );
   9900    IRTemp top_10   = newTemp( Ity_I64 );
   9901    IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
   9902 
   9903    /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
   9904 
   9905    /* low_50[49:0] = ((frBI64_lo[49:32]  << 14) | frBI64_lo[31:0]) */
   9906    assign( low_50,
   9907            binop( Iop_32HLto64,
   9908                   binop( Iop_And32,
   9909                          unop( Iop_64HIto32, frBI64_lo ),
   9910                          mkU32( 0x3FFFF ) ),
   9911                          unop( Iop_64to32, frBI64_lo ) ) );
   9912 
   9913    /* Convert the 50 bit densely packed BCD string to a 60 bit
   9914     * BCD string.
   9915     */
   9916    assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
   9917    assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
   9918    assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
   9919 
   9920    /* mid_50[49:0] =  ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
   9921     *                 ((frBI64_hi[17:0]  << 14) | frBI64_lo[63:50])
   9922     */
   9923    assign( mid_50,
   9924            binop( Iop_32HLto64,
   9925                   binop( Iop_Or32,
   9926                          binop( Iop_Shl32,
   9927                                 binop( Iop_And32,
   9928                                        unop( Iop_64HIto32, frBI64_hi ),
   9929                                        mkU32( 0xF ) ),
   9930                                 mkU8( 14 ) ),
   9931                          binop( Iop_Shr32,
   9932                                 unop( Iop_64to32, frBI64_hi ),
   9933                                 mkU8( 18 ) ) ),
   9934                   binop( Iop_Or32,
   9935                          binop( Iop_Shl32,
   9936                                 unop( Iop_64to32, frBI64_hi ),
   9937                                 mkU8( 14 ) ),
   9938                          binop( Iop_Shr32,
   9939                                 unop( Iop_64HIto32, frBI64_lo ),
   9940                                 mkU8( 18 ) ) ) ) );
   9941 
   9942    /* Convert the 50 bit densely packed BCD string to a 60 bit
   9943     * BCD string.
   9944     */
   9945    assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
   9946    assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
   9947    assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
   9948 
   9949    /* top_10[49:0] = frBI64_hi[45:36]) |  */
   9950    assign( top_10,
   9951            binop( Iop_32HLto64,
   9952                   mkU32( 0 ),
   9953                   binop( Iop_And32,
   9954                          binop( Iop_Shr32,
   9955                                 unop( Iop_64HIto32, frBI64_hi ),
   9956                                 mkU8( 4 ) ),
   9957                          mkU32( 0x3FF ) ) ) );
   9958 
   9959    /* Convert the 10 bit densely packed BCD string to a 12 bit
   9960     * BCD string.
   9961     */
   9962    assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
   9963    assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
   9964    assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
   9965 }
   9966 
   9967 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
   9968                          IRTemp * final_cnt, IRTemp * final_flag,
   9969                          IRExpr * string )
   9970 {
   9971    IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
   9972    int digits = MAX_DIGITS_IN_STRING;
   9973    int i;
   9974 
   9975    cnt[start-1] = newTemp( Ity_I8 );
   9976    flag[start-1] = newTemp( Ity_I8 );
   9977    assign( cnt[start-1], init_cnt);
   9978    assign( flag[start-1], init_flag);
   9979 
   9980    for ( i = start; i <= digits; i++) {
   9981       cnt[i] = newTemp( Ity_I8 );
   9982       flag[i] = newTemp( Ity_I8 );
   9983       assign( cnt[i],
   9984               binop( Iop_Add8,
   9985                      mkexpr( cnt[i-1] ),
   9986                      binop(Iop_And8,
   9987                            unop( Iop_1Uto8,
   9988                                  binop(Iop_CmpEQ32,
   9989                                        binop(Iop_And32,
   9990                                              string,
   9991                                              mkU32( 0xF <<
   9992                                                     ( ( digits - i ) * 4) ) ),
   9993                                        mkU32( 0 ) ) ),
   9994                            binop( Iop_Xor8, /* complement flag */
   9995                                   mkexpr( flag[i - 1] ),
   9996                                   mkU8( 0xFF ) ) ) ) );
   9997 
   9998       /* set flag to 1 if digit was not a zero */
   9999       assign( flag[i],
   10000               binop(Iop_Or8,
   10001                     unop( Iop_1Sto8,
   10002                           binop(Iop_CmpNE32,
   10003                                 binop(Iop_And32,
   10004                                       string,
   10005                                       mkU32( 0xF <<
   10006                                              ( (digits - i) * 4) ) ),
   10007                                 mkU32( 0 ) ) ),
   10008                     mkexpr( flag[i - 1] ) ) );
   10009    }
   10010 
   10011    *final_cnt = cnt[digits];
   10012    *final_flag = flag[digits];
   10013 }
   10014 
   10015 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
   10016                                         IRExpr * low_32 )
   10017 {
   10018    IRTemp num_lmd    = newTemp( Ity_I8 );
   10019    IRTemp num_upper  = newTemp( Ity_I8 );
   10020    IRTemp num_low    = newTemp( Ity_I8 );
   10021    IRTemp lmd_flag   = newTemp( Ity_I8 );
   10022    IRTemp upper_flag = newTemp( Ity_I8 );
   10023    IRTemp low_flag   = newTemp( Ity_I8 );
   10024 
   10025    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
   10026    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
   10027 
   10028    Count_zeros( 2,
   10029                 mkexpr( num_lmd ),
   10030                 mkexpr( lmd_flag ),
   10031                 &num_upper,
   10032                 &upper_flag,
   10033                 upper_28 );
   10034 
   10035    Count_zeros( 1,
   10036                 mkexpr( num_upper ),
   10037                 mkexpr( upper_flag ),
   10038                 &num_low,
   10039                 &low_flag,
   10040                 low_32 );
   10041 
   10042    return mkexpr( num_low );
   10043 }
   10044 
   10045 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
   10046                                          IRExpr * mid_60_u, IRExpr * mid_60_l,
   10047                                          IRExpr * low_60_u, IRExpr * low_60_l)
   10048 {
   10049    IRTemp num_lmd   = newTemp( Ity_I8 );
   10050    IRTemp num_top   = newTemp( Ity_I8 );
   10051    IRTemp num_mid_u = newTemp( Ity_I8 );
   10052    IRTemp num_mid_l = newTemp( Ity_I8 );
   10053    IRTemp num_low_u = newTemp( Ity_I8 );
   10054    IRTemp num_low_l = newTemp( Ity_I8 );
   10055 
   10056    IRTemp lmd_flag   = newTemp( Ity_I8 );
   10057    IRTemp top_flag   = newTemp( Ity_I8 );
   10058    IRTemp mid_u_flag = newTemp( Ity_I8 );
   10059    IRTemp mid_l_flag = newTemp( Ity_I8 );
   10060    IRTemp low_u_flag = newTemp( Ity_I8 );
   10061    IRTemp low_l_flag = newTemp( Ity_I8 );
   10062 
   10063    /* Check the LMD, digit 16, to see if it is zero. */
   10064    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
   10065 
   10066    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
   10067 
   10068    Count_zeros( 6,
   10069                 mkexpr( num_lmd ),
   10070                 mkexpr( lmd_flag ),
   10071                 &num_top,
   10072                 &top_flag,
   10073                 top_12_l );
   10074 
   10075    Count_zeros( 1,
   10076                 mkexpr( num_top ),
   10077                 mkexpr( top_flag ),
   10078                 &num_mid_u,
   10079                 &mid_u_flag,
   10080                 binop( Iop_Or32,
   10081                        binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
   10082                        binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
   10083 
   10084    Count_zeros( 2,
   10085                 mkexpr( num_mid_u ),
   10086                 mkexpr( mid_u_flag ),
   10087                 &num_mid_l,
   10088                 &mid_l_flag,
   10089                 mid_60_l );
   10090 
   10091    Count_zeros( 1,
   10092                 mkexpr( num_mid_l ),
   10093                 mkexpr( mid_l_flag ),
   10094                 &num_low_u,
   10095                 &low_u_flag,
   10096                 binop( Iop_Or32,
   10097                        binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
   10098                        binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
   10099 
   10100    Count_zeros( 2,
   10101                 mkexpr( num_low_u ),
   10102                 mkexpr( low_u_flag ),
   10103                 &num_low_l,
   10104                 &low_l_flag,
   10105                 low_60_l );
   10106 
   10107    return mkexpr( num_low_l );
   10108 }
   10109 
   10110 static IRExpr * Check_unordered(IRExpr * val)
   10111 {
   10112    IRTemp gfield0to5 = newTemp( Ity_I32 );
   10113 
   10114    /* Extract G[0:4] */
   10115    assign( gfield0to5,
   10116            binop( Iop_And32,
   10117                   binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
   10118                   mkU32( 0x1F ) ) );
   10119 
   10120    /* Check for unordered, return all 1'x if true */
   10121    return binop( Iop_Or32, /* QNaN check */
   10122                  unop( Iop_1Sto32,
   10123                        binop( Iop_CmpEQ32,
   10124                               mkexpr( gfield0to5 ),
   10125                               mkU32( 0x1E ) ) ),
   10126                               unop( Iop_1Sto32, /* SNaN check */
   10127                                     binop( Iop_CmpEQ32,
   10128                                            mkexpr( gfield0to5 ),
   10129                                            mkU32( 0x1F ) ) ) );
   10130 }
   10131 
   10132 #undef AND
   10133 #undef AND4
   10134 #undef OR
   10135 #undef OR3
   10136 #undef OR4
   10137 #undef NOT
   10138 #undef SHR
   10139 #undef SHL
   10140 #undef BITS5
   10141 
   10142 /*------------------------------------------------------------*/
   10143 /*--- Decimal Floating Point (DFP) instruction translation ---*/
   10144 /*------------------------------------------------------------*/
   10145 
   10146 /* DFP Arithmetic instructions */
   10147 static Bool dis_dfp_arith(UInt theInstr)
   10148 {
   10149    UInt opc2 = ifieldOPClo10( theInstr );
   10150    UChar frS_addr = ifieldRegDS( theInstr );
   10151    UChar frA_addr = ifieldRegA( theInstr );
   10152    UChar frB_addr = ifieldRegB( theInstr );
   10153    UChar flag_rC = ifieldBIT0( theInstr );
   10154 
   10155    IRTemp frA = newTemp( Ity_D64 );
   10156    IRTemp frB = newTemp( Ity_D64 );
   10157    IRTemp frS = newTemp( Ity_D64 );
   10158    IRExpr* round = get_IR_roundingmode_DFP();
   10159 
   10160    /* By default, if flag_RC is set, we will clear cr1 after the
   10161     * operation.  In reality we should set cr1 to indicate the
   10162     * exception status of the operation, but since we're not
   10163     * simulating exceptions, the exception status will appear to be
   10164     * zero.  Hence cr1 should be cleared if this is a . form insn.
   10165     */
   10166    Bool clear_CR1 = True;
   10167 
   10168    assign( frA, getDReg( frA_addr ) );
   10169    assign( frB, getDReg( frB_addr ) );
   10170 
   10171    switch (opc2) {
   10172    case 0x2: // dadd
   10173       DIP( "dadd%s fr%u,fr%u,fr%u\n",
   10174            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10175       assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   10176       break;
   10177    case 0x202: // dsub
   10178       DIP( "dsub%s fr%u,fr%u,fr%u\n",
   10179            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10180       assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   10181       break;
   10182    case 0x22: // dmul
   10183       DIP( "dmul%s fr%u,fr%u,fr%u\n",
   10184            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10185       assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   10186       break;
   10187    case 0x222: // ddiv
   10188       DIP( "ddiv%s fr%u,fr%u,fr%u\n",
   10189            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10190       assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   10191       break;
   10192    }
   10193 
   10194    putDReg( frS_addr, mkexpr( frS ) );
   10195 
   10196    if (flag_rC && clear_CR1) {
   10197       putCR321( 1, mkU8( 0 ) );
   10198       putCR0( 1, mkU8( 0 ) );
   10199    }
   10200 
   10201    return True;
   10202 }
   10203 
   10204 /* Quad DFP Arithmetic instructions */
   10205 static Bool dis_dfp_arithq(UInt theInstr)
   10206 {
   10207    UInt opc2 = ifieldOPClo10( theInstr );
   10208    UChar frS_addr = ifieldRegDS( theInstr );
   10209    UChar frA_addr = ifieldRegA( theInstr );
   10210    UChar frB_addr = ifieldRegB( theInstr );
   10211    UChar flag_rC = ifieldBIT0( theInstr );
   10212 
   10213    IRTemp frA = newTemp( Ity_D128 );
   10214    IRTemp frB = newTemp( Ity_D128 );
   10215    IRTemp frS = newTemp( Ity_D128 );
   10216    IRExpr* round = get_IR_roundingmode_DFP();
   10217 
   10218    /* By default, if flag_RC is set, we will clear cr1 after the
   10219     * operation.  In reality we should set cr1 to indicate the
   10220     * exception status of the operation, but since we're not
   10221     * simulating exceptions, the exception status will appear to be
   10222     * zero.  Hence cr1 should be cleared if this is a . form insn.
   10223     */
   10224    Bool clear_CR1 = True;
   10225 
   10226    assign( frA, getDReg_pair( frA_addr ) );
   10227    assign( frB, getDReg_pair( frB_addr ) );
   10228 
   10229    switch (opc2) {
   10230    case 0x2: // daddq
   10231       DIP( "daddq%s fr%u,fr%u,fr%u\n",
   10232            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10233       assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   10234       break;
   10235    case 0x202: // dsubq
   10236       DIP( "dsubq%s fr%u,fr%u,fr%u\n",
   10237            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10238       assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   10239       break;
   10240    case 0x22: // dmulq
   10241       DIP( "dmulq%s fr%u,fr%u,fr%u\n",
   10242            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10243       assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   10244       break;
   10245    case 0x222: // ddivq
   10246       DIP( "ddivq%s fr%u,fr%u,fr%u\n",
   10247            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10248       assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   10249       break;
   10250    }
   10251 
   10252    putDReg_pair( frS_addr, mkexpr( frS ) );
   10253 
   10254    if (flag_rC && clear_CR1) {
   10255       putCR321( 1, mkU8( 0 ) );
   10256       putCR0( 1, mkU8( 0 ) );
   10257    }
   10258 
   10259    return True;
   10260 }
   10261 
   10262 /* DFP 64-bit logical shift instructions  */
   10263 static Bool dis_dfp_shift(UInt theInstr) {
   10264    UInt opc2       = ifieldOPClo9( theInstr );
   10265    UChar frS_addr  = ifieldRegDS( theInstr );
   10266    UChar frA_addr  = ifieldRegA( theInstr );
   10267    UChar shift_val = IFIELD(theInstr, 10, 6);
   10268    UChar flag_rC   = ifieldBIT0( theInstr );
   10269 
   10270    IRTemp frA = newTemp( Ity_D64 );
   10271    IRTemp frS = newTemp( Ity_D64 );
   10272    Bool clear_CR1 = True;
   10273 
   10274    assign( frA, getDReg( frA_addr ) );
   10275 
   10276    switch (opc2) {
   10277    case 0x42: // dscli
   10278       DIP( "dscli%s fr%u,fr%u,%u\n",
   10279            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   10280       assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
   10281       break;
   10282    case 0x62: // dscri
   10283       DIP( "dscri%s fr%u,fr%u,%u\n",
   10284            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   10285       assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
   10286       break;
   10287    }
   10288 
   10289    putDReg( frS_addr, mkexpr( frS ) );
   10290 
   10291    if (flag_rC && clear_CR1) {
   10292       putCR321( 1, mkU8( 0 ) );
   10293       putCR0( 1, mkU8( 0 ) );
   10294    }
   10295 
   10296    return True;
   10297 }
   10298 
   10299 /* Quad DFP  logical shift instructions  */
   10300 static Bool dis_dfp_shiftq(UInt theInstr) {
   10301    UInt opc2       = ifieldOPClo9( theInstr );
   10302    UChar frS_addr  = ifieldRegDS( theInstr );
   10303    UChar frA_addr  = ifieldRegA( theInstr );
   10304    UChar shift_val = IFIELD(theInstr, 10, 6);
   10305    UChar flag_rC   = ifieldBIT0( theInstr );
   10306 
   10307    IRTemp frA = newTemp( Ity_D128 );
   10308    IRTemp frS = newTemp( Ity_D128 );
   10309    Bool clear_CR1 = True;
   10310 
   10311    assign( frA, getDReg_pair( frA_addr ) );
   10312 
   10313    switch (opc2) {
   10314    case 0x42: // dscliq
   10315       DIP( "dscliq%s fr%u,fr%u,%u\n",
   10316            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   10317       assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
   10318       break;
   10319    case 0x62: // dscriq
   10320       DIP( "dscriq%s fr%u,fr%u,%u\n",
   10321            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   10322       assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
   10323       break;
   10324    }
   10325 
   10326    putDReg_pair( frS_addr, mkexpr( frS ) );
   10327 
   10328    if (flag_rC && clear_CR1) {
   10329       putCR321( 1, mkU8( 0 ) );
   10330       putCR0( 1, mkU8( 0 ) );
   10331    }
   10332 
   10333    return True;
   10334 }
   10335 
   10336 /* DFP 64-bit format conversion instructions */
   10337 static Bool dis_dfp_fmt_conv(UInt theInstr) {
   10338    UInt opc2      = ifieldOPClo10( theInstr );
   10339    UChar frS_addr = ifieldRegDS( theInstr );
   10340    UChar frB_addr = ifieldRegB( theInstr );
   10341    IRExpr* round  = get_IR_roundingmode_DFP();
   10342    UChar flag_rC  = ifieldBIT0( theInstr );
   10343    IRTemp frB;
   10344    IRTemp frS;
   10345    Bool clear_CR1 = True;
   10346 
   10347    switch (opc2) {
   10348    case 0x102: //dctdp
   10349       DIP( "dctdp%s fr%u,fr%u\n",
   10350            flag_rC ? ".":"", frS_addr, frB_addr );
   10351 
   10352       frB = newTemp( Ity_D32 );
   10353       frS = newTemp( Ity_D64 );
   10354       assign( frB, getDReg32( frB_addr ) );
   10355       assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
   10356       putDReg( frS_addr, mkexpr( frS ) );
   10357       break;
   10358    case 0x302: // drsp
   10359       DIP( "drsp%s fr%u,fr%u\n",
   10360            flag_rC ? ".":"", frS_addr, frB_addr );
   10361       frB = newTemp( Ity_D64 );
   10362       frS = newTemp( Ity_D32 );
   10363       assign( frB, getDReg( frB_addr ) );
   10364       assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
   10365       putDReg32( frS_addr, mkexpr( frS ) );
   10366       break;
   10367    case 0x122: // dctfix
   10368       {
   10369          IRTemp tmp = newTemp( Ity_I64 );
   10370 
   10371          DIP( "dctfix%s fr%u,fr%u\n",
   10372               flag_rC ? ".":"", frS_addr, frB_addr );
   10373          frB = newTemp( Ity_D64 );
   10374          frS = newTemp( Ity_D64 );
   10375          assign( frB, getDReg( frB_addr ) );
   10376          assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
   10377          assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10378          putDReg( frS_addr, mkexpr( frS ) );
   10379       }
   10380       break;
   10381    case 0x322: // dcffix
   10382       DIP( "dcffix%s fr%u,fr%u\n",
   10383            flag_rC ? ".":"", frS_addr, frB_addr );
   10384       frB = newTemp( Ity_D64 );
   10385       frS = newTemp( Ity_D64 );
   10386       assign( frB, getDReg( frB_addr ) );
   10387       assign( frS, binop( Iop_I64StoD64,
   10388                           round,
   10389                           unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
   10390       putDReg( frS_addr, mkexpr( frS ) );
   10391       break;
   10392    }
   10393 
   10394    if (flag_rC && clear_CR1) {
   10395       putCR321( 1, mkU8( 0 ) );
   10396       putCR0( 1, mkU8( 0 ) );
   10397    }
   10398 
   10399    return True;
   10400 }
   10401 
   10402 /* Quad DFP format conversion instructions */
   10403 static Bool dis_dfp_fmt_convq(UInt theInstr) {
   10404    UInt opc2      = ifieldOPClo10( theInstr );
   10405    UChar frS_addr = ifieldRegDS( theInstr );
   10406    UChar frB_addr = ifieldRegB( theInstr );
   10407    IRExpr* round  = get_IR_roundingmode_DFP();
   10408    IRTemp frB64   = newTemp( Ity_D64 );
   10409    IRTemp frB128  = newTemp( Ity_D128 );
   10410    IRTemp frS64   = newTemp( Ity_D64 );
   10411    IRTemp frS128  = newTemp( Ity_D128 );
   10412    UChar flag_rC  = ifieldBIT0( theInstr );
   10413    Bool clear_CR1 = True;
   10414 
   10415    switch (opc2) {
   10416    case 0x102: // dctqpq
   10417       DIP( "dctqpq%s fr%u,fr%u\n",
   10418            flag_rC ? ".":"", frS_addr, frB_addr );
   10419       assign( frB64, getDReg( frB_addr ) );
   10420       assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
   10421       putDReg_pair( frS_addr, mkexpr( frS128 ) );
   10422       break;
   10423    case 0x122: // dctfixq
   10424       {
   10425          IRTemp tmp = newTemp( Ity_I64 );
   10426 
   10427          DIP( "dctfixq%s fr%u,fr%u\n",
   10428               flag_rC ? ".":"", frS_addr, frB_addr );
   10429          assign( frB128, getDReg_pair( frB_addr ) );
   10430          assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
   10431          assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10432          putDReg( frS_addr, mkexpr( frS64 ) );
   10433       }
   10434       break;
   10435    case 0x302: //drdpq
   10436       DIP( "drdpq%s fr%u,fr%u\n",
   10437            flag_rC ? ".":"", frS_addr, frB_addr );
   10438       assign( frB128, getDReg_pair( frB_addr ) );
   10439       assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
   10440       putDReg( frS_addr, mkexpr( frS64 ) );
   10441       break;
   10442    case 0x322: // dcffixq
   10443      {
   10444       /* Have to introduce an IOP for this instruction so it will work
   10445        * on POWER 6 because emulating the instruction requires a POWER 7
   10446        * DFP instruction in the emulation code.
   10447        */
   10448       DIP( "dcffixq%s fr%u,fr%u\n",
   10449            flag_rC ? ".":"", frS_addr, frB_addr );
   10450       assign( frB64, getDReg( frB_addr ) );
   10451       assign( frS128, unop( Iop_I64StoD128,
   10452                             unop( Iop_ReinterpD64asI64,
   10453                                   mkexpr( frB64 ) ) ) );
   10454       putDReg_pair( frS_addr, mkexpr( frS128 ) );
   10455       break;
   10456      }
   10457    }
   10458 
   10459    if (flag_rC && clear_CR1) {
   10460       putCR321( 1, mkU8( 0 ) );
   10461       putCR0( 1, mkU8( 0 ) );
   10462    }
   10463 
   10464    return True;
   10465 }
   10466 
   10467 static Bool dis_dfp_round( UInt theInstr ) {
   10468    UChar frS_addr = ifieldRegDS(theInstr);
   10469    UChar R        = IFIELD(theInstr, 16, 1);
   10470    UChar RMC      = IFIELD(theInstr, 9, 2);
   10471    UChar frB_addr = ifieldRegB( theInstr );
   10472    UChar flag_rC  = ifieldBIT0( theInstr );
   10473    IRTemp frB     = newTemp( Ity_D64 );
   10474    IRTemp frS     = newTemp( Ity_D64 );
   10475    UInt opc2      = ifieldOPClo8( theInstr );
   10476    Bool clear_CR1 = True;
   10477 
   10478    switch (opc2) {
   10479    /* drintn, is the same as drintx.  The only difference is this
   10480     * instruction does not generate an exception for an inexact operation.
   10481     * Currently not supporting inexact exceptions.
   10482     */
   10483    case 0x63: // drintx
   10484    case 0xE3: // drintn
   10485       DIP( "drintx/drintn%s fr%u,fr%u\n",
   10486            flag_rC ? ".":"", frS_addr, frB_addr );
   10487 
   10488       /* NOTE, this instruction takes a DFP value and rounds to the
   10489        * neares floating point integer value, i.e. fractional part
   10490        * is zero.  The result is a floating point number.
   10491        */
   10492       /* pass the value of R and RMC in the same field */
   10493       assign( frB, getDReg( frB_addr ) );
   10494       assign( frS, binop( Iop_RoundD64toInt,
   10495                           mkU32( ( R << 3 ) | RMC ),
   10496                           mkexpr( frB ) ) );
   10497       putDReg( frS_addr, mkexpr( frS ) );
   10498       break;
   10499    default:
   10500       vex_printf("dis_dfp_round(ppc)(opc2)\n");
   10501       return False;
   10502    }
   10503 
   10504    if (flag_rC && clear_CR1) {
   10505       putCR321( 1, mkU8( 0 ) );
   10506       putCR0( 1, mkU8( 0 ) );
   10507    }
   10508 
   10509    return True;
   10510 }
   10511 
   10512 static Bool dis_dfp_roundq(UInt theInstr) {
   10513    UChar frS_addr = ifieldRegDS( theInstr );
   10514    UChar frB_addr = ifieldRegB( theInstr );
   10515    UChar R = IFIELD(theInstr, 16, 1);
   10516    UChar RMC = IFIELD(theInstr, 9, 2);
   10517    UChar flag_rC = ifieldBIT0( theInstr );
   10518    IRTemp frB = newTemp( Ity_D128 );
   10519    IRTemp frS = newTemp( Ity_D128 );
   10520    Bool clear_CR1 = True;
   10521    UInt opc2 = ifieldOPClo8( theInstr );
   10522 
   10523    switch (opc2) {
   10524    /* drintnq, is the same as drintxq.  The only difference is this
   10525     * instruction does not generate an exception for an inexact operation.
   10526     * Currently not supporting inexact exceptions.
   10527     */
   10528    case 0x63: // drintxq
   10529    case 0xE3: // drintnq
   10530       DIP( "drintxq/drintnq%s fr%u,fr%u\n",
   10531            flag_rC ? ".":"", frS_addr, frB_addr );
   10532 
   10533       /* pass the value of R and RMC in the same field */
   10534       assign( frB, getDReg_pair( frB_addr ) );
   10535       assign( frS, binop( Iop_RoundD128toInt,
   10536                           mkU32( ( R << 3 ) | RMC ),
   10537                           mkexpr( frB ) ) );
   10538       putDReg_pair( frS_addr, mkexpr( frS ) );
   10539       break;
   10540    default:
   10541       vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
   10542       return False;
   10543    }
   10544 
   10545    if (flag_rC && clear_CR1) {
   10546       putCR321( 1, mkU8( 0 ) );
   10547       putCR0( 1, mkU8( 0 ) );
   10548    }
   10549 
   10550    return True;
   10551 }
   10552 
   10553 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
   10554    UInt opc2 = ifieldOPClo8( theInstr );
   10555    UChar frS_addr = ifieldRegDS( theInstr );
   10556    UChar frA_addr = ifieldRegA( theInstr );
   10557    UChar frB_addr = ifieldRegB( theInstr );
   10558    UChar flag_rC = ifieldBIT0( theInstr );
   10559    UInt TE_value = IFIELD(theInstr, 16, 4);
   10560    UInt TE_sign  = IFIELD(theInstr, 20, 1);
   10561    UInt RMC = IFIELD(theInstr, 9, 2);
   10562    IRTemp frA = newTemp( Ity_D64 );
   10563    IRTemp frB = newTemp( Ity_D64 );
   10564    IRTemp frS = newTemp( Ity_D64 );
   10565    Bool clear_CR1 = True;
   10566 
   10567    assign( frB, getDReg( frB_addr ) );
   10568 
   10569    switch (opc2) {
   10570    case 0x43: // dquai
   10571       DIP( "dquai%s fr%u,fr%u,fr%u\n",
   10572            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10573       IRTemp TE_I64 = newTemp( Ity_I64 );
   10574 
   10575       /* Generate a reference DFP value frA with the desired exponent
   10576        * given by TE using significand from frB.  Need to add the bias
   10577        * 398 to TE.  TE is stored as a 2's complement number.
   10578        */
   10579       if (TE_sign == 1) {
   10580          /* Take 2's complement of the 5-bit value and subtract from bias.
   10581           *  Bias is adjusted for the +1 required when taking 2's complement.
   10582           */
   10583          assign( TE_I64,
   10584                  unop( Iop_32Uto64,
   10585                        binop( Iop_Sub32, mkU32( 397 ),
   10586                               binop( Iop_And32, mkU32( 0xF ),
   10587                                      unop( Iop_Not32, mkU32( TE_value ) )
   10588                                      ) ) ) );
   10589 
   10590       } else {
   10591           assign( TE_I64,
   10592                   unop( Iop_32Uto64,
   10593                         binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
   10594                         ) );
   10595       }
   10596 
   10597       assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
   10598                           unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
   10599 
   10600       assign( frS, triop( Iop_QuantizeD64,
   10601                           mkU32( RMC ),
   10602                           mkexpr( frA ),
   10603                           mkexpr( frB ) ) );
   10604       break;
   10605 
   10606    case 0x3: // dqua
   10607       DIP( "dqua%s fr%u,fr%u,fr%u\n",
   10608            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10609       assign( frA, getDReg( frA_addr ) );
   10610       assign( frS, triop( Iop_QuantizeD64,
   10611                           mkU32( RMC ),
   10612                           mkexpr( frA ),
   10613                           mkexpr( frB ) ) );
   10614       break;
   10615    case 0x23: // drrnd
   10616       {
   10617          IRTemp tmp = newTemp( Ity_I8 );
   10618 
   10619          DIP( "drrnd%s fr%u,fr%u,fr%u\n",
   10620               flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10621          assign( frA, getDReg( frA_addr ) );
   10622          /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
   10623          assign( tmp, unop( Iop_32to8,
   10624                             unop( Iop_64to32,
   10625                                   unop( Iop_ReinterpD64asI64,
   10626                                         mkexpr( frA ) ) ) ) );
   10627          assign( frS, triop( Iop_SignificanceRoundD64,
   10628                              mkU32( RMC ),
   10629                              mkexpr( tmp ),
   10630                              mkexpr( frB ) ) );
   10631       }
   10632       break;
   10633    default:
   10634       vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
   10635       return False;
   10636    }
   10637    putDReg( frS_addr, mkexpr( frS ) );
   10638 
   10639    if (flag_rC && clear_CR1) {
   10640       putCR321( 1, mkU8( 0 ) );
   10641       putCR0( 1, mkU8( 0 ) );
   10642    }
   10643 
   10644    return True;
   10645 }
   10646 
   10647 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
   10648    UInt opc2 = ifieldOPClo8( theInstr );
   10649    UChar frS_addr = ifieldRegDS( theInstr );
   10650    UChar frA_addr = ifieldRegA( theInstr );
   10651    UChar frB_addr = ifieldRegB( theInstr );
   10652    UChar flag_rC = ifieldBIT0( theInstr );
   10653    UInt TE_value = IFIELD(theInstr, 16, 4);
   10654    UInt TE_sign  = IFIELD(theInstr, 20, 1);
   10655    UInt RMC = IFIELD(theInstr, 9, 2);
   10656    IRTemp frA = newTemp( Ity_D128 );
   10657    IRTemp frB = newTemp( Ity_D128 );
   10658    IRTemp frS = newTemp( Ity_D128 );
   10659    Bool clear_CR1 = True;
   10660 
   10661    assign( frB, getDReg_pair( frB_addr ) );
   10662 
   10663    switch (opc2) {
   10664    case 0x43: // dquaiq
   10665       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
   10666            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10667       IRTemp TE_I64 = newTemp( Ity_I64 );
   10668 
   10669       /* Generate a reference DFP value frA with the desired exponent
   10670        * given by TE using significand of 1.  Need to add the bias
   10671        * 6176 to TE.
   10672        */
   10673       if (TE_sign == 1) {
   10674          /* Take 2's complement of the 5-bit value and subtract from bias.
   10675           *  Bias adjusted for the +1 required when taking 2's complement.
   10676           */
   10677          assign( TE_I64,
   10678                  unop( Iop_32Uto64,
   10679                        binop( Iop_Sub32, mkU32( 6175 ),
   10680                               binop( Iop_And32, mkU32( 0xF ),
   10681                                      unop( Iop_Not32, mkU32( TE_value ) )
   10682                                      ) ) ) );
   10683 
   10684       } else {
   10685          assign( TE_I64,
   10686                  unop( Iop_32Uto64,
   10687                        binop( Iop_Add32,
   10688                              mkU32( 6176 ),
   10689                              mkU32( TE_value ) ) ) );
   10690       }
   10691 
   10692       assign( frA,
   10693               binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
   10694                      unop( Iop_D64toD128,
   10695                            unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
   10696       assign( frS, triop( Iop_QuantizeD128,
   10697                           mkU32( RMC ),
   10698                           mkexpr( frA ),
   10699                           mkexpr( frB ) ) );
   10700       break;
   10701    case 0x3: // dquaq
   10702       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
   10703            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10704       assign( frA, getDReg_pair( frA_addr ) );
   10705       assign( frS, triop( Iop_QuantizeD128,
   10706                           mkU32( RMC ),
   10707                           mkexpr( frA ),
   10708                           mkexpr( frB ) ) );
   10709       break;
   10710    case 0x23: // drrndq
   10711       {
   10712          IRTemp tmp = newTemp( Ity_I8 );
   10713 
   10714          DIP( "drrndq%s fr%u,fr%u,fr%u\n",
   10715               flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10716          assign( frA, getDReg_pair( frA_addr ) );
   10717          assign( tmp, unop( Iop_32to8,
   10718                             unop( Iop_64to32,
   10719                                   unop( Iop_ReinterpD64asI64,
   10720                                         unop( Iop_D128HItoD64,
   10721                                               mkexpr( frA ) ) ) ) ) );
   10722          assign( frS, triop( Iop_SignificanceRoundD128,
   10723                              mkU32( RMC ),
   10724                              mkexpr( tmp ),
   10725                              mkexpr( frB ) ) );
   10726       }
   10727       break;
   10728    default:
   10729       vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
   10730       return False;
   10731    }
   10732    putDReg_pair( frS_addr, mkexpr( frS ) );
   10733 
   10734    if (flag_rC && clear_CR1) {
   10735       putCR321( 1, mkU8( 0 ) );
   10736       putCR0( 1, mkU8( 0 ) );
   10737    }
   10738 
   10739    return True;
   10740 }
   10741 
   10742 static Bool dis_dfp_extract_insert(UInt theInstr) {
   10743    UInt opc2 = ifieldOPClo10( theInstr );
   10744    UChar frS_addr = ifieldRegDS( theInstr );
   10745    UChar frA_addr = ifieldRegA( theInstr );
   10746    UChar frB_addr = ifieldRegB( theInstr );
   10747    UChar flag_rC = ifieldBIT0( theInstr );
   10748    Bool clear_CR1 = True;
   10749 
   10750    IRTemp frA = newTemp( Ity_D64 );
   10751    IRTemp frB = newTemp( Ity_D64 );
   10752    IRTemp frS = newTemp( Ity_D64 );
   10753    IRTemp tmp = newTemp( Ity_I64 );
   10754 
   10755    assign( frA, getDReg( frA_addr ) );
   10756    assign( frB, getDReg( frB_addr ) );
   10757 
   10758    switch (opc2) {
   10759    case 0x162: // dxex
   10760       DIP( "dxex%s fr%u,fr%u,fr%u\n",
   10761            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10762       assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
   10763       assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10764       break;
   10765    case 0x362: // diex
   10766       DIP( "diex%s fr%u,fr%u,fr%u\n",
   10767            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10768       assign( frS, binop( Iop_InsertExpD64,
   10769                           unop( Iop_ReinterpD64asI64,
   10770                                 mkexpr( frA ) ),
   10771                           mkexpr( frB ) ) );
   10772       break;
   10773    default:
   10774       vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
   10775       return False;
   10776    }
   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_extract_insertq(UInt theInstr) {
   10789    UInt opc2 = ifieldOPClo10( 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 
   10795    IRTemp frA   = newTemp( Ity_D64 );
   10796    IRTemp frB   = newTemp( Ity_D128 );
   10797    IRTemp frS64 = newTemp( Ity_D64 );
   10798    IRTemp frS   = newTemp( Ity_D128 );
   10799    IRTemp tmp   = newTemp( Ity_I64 );
   10800    Bool clear_CR1 = True;
   10801 
   10802    assign( frB, getDReg_pair( frB_addr ) );
   10803 
   10804    switch (opc2) {
   10805    case 0x162:  // dxexq
   10806       DIP( "dxexq%s fr%u,fr%u\n",
   10807            flag_rC ? ".":"", frS_addr,  frB_addr );
   10808       /* Instruction actually returns a 64-bit result.  So as to be
   10809        * consistent and not have to add a new struct, the emulation returns
   10810        * the 64-bit result in the upper and lower register.
   10811        */
   10812       assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
   10813       assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10814       putDReg( frS_addr, mkexpr( frS64 ) );
   10815       break;
   10816    case 0x362:  // diexq
   10817       DIP( "diexq%s fr%u,fr%u,fr%u\n",
   10818            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10819       assign( frA, getDReg( frA_addr ) );
   10820       assign( frS, binop( Iop_InsertExpD128,
   10821                           unop( Iop_ReinterpD64asI64, mkexpr( frA ) ),
   10822                           mkexpr( frB ) ) );
   10823       putDReg_pair( frS_addr, mkexpr( frS ) );
   10824       break;
   10825    default:
   10826       vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
   10827       return False;
   10828    }
   10829 
   10830    if (flag_rC && clear_CR1) {
   10831       putCR321( 1, mkU8( 0 ) );
   10832       putCR0( 1, mkU8( 0 ) );
   10833    }
   10834 
   10835    return True;
   10836 }
   10837 
   10838 /* DFP 64-bit comparison instructions */
   10839 static Bool dis_dfp_compare(UInt theInstr) {
   10840    /* X-Form */
   10841    UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
   10842    UChar frA_addr = ifieldRegA( theInstr );
   10843    UChar frB_addr = ifieldRegB( theInstr );
   10844    UInt opc1 = ifieldOPC( theInstr );
   10845    IRTemp frA;
   10846    IRTemp frB;
   10847 
   10848    IRTemp ccIR = newTemp( Ity_I32 );
   10849    IRTemp ccPPC32 = newTemp( Ity_I32 );
   10850 
   10851 
   10852    /* Note: Differences between dcmpu and dcmpo are only in exception
   10853     flag settings, which aren't supported anyway. */
   10854    switch (opc1) {
   10855    case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
   10856       DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
   10857       frA = newTemp( Ity_D64 );
   10858       frB = newTemp( Ity_D64 );
   10859 
   10860       assign( frA, getDReg( frA_addr ) );
   10861       assign( frB, getDReg( frB_addr ) );
   10862 
   10863       assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
   10864       break;
   10865    case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
   10866       DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
   10867       frA = newTemp( Ity_D128 );
   10868       frB = newTemp( Ity_D128 );
   10869 
   10870       assign( frA, getDReg_pair( frA_addr ) );
   10871       assign( frB, getDReg_pair( frB_addr ) );
   10872       assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
   10873       break;
   10874    default:
   10875       vex_printf("dis_dfp_compare(ppc)(opc2)\n");
   10876       return False;
   10877    }
   10878 
   10879    /* Map compare result from IR to PPC32 */
   10880    /*
   10881     FP cmp result | PPC | IR
   10882     --------------------------
   10883     UN            | 0x1 | 0x45
   10884     EQ            | 0x2 | 0x40
   10885     GT            | 0x4 | 0x00
   10886     LT            | 0x8 | 0x01
   10887     */
   10888 
   10889    assign( ccPPC32,
   10890            binop( Iop_Shl32,
   10891                   mkU32( 1 ),
   10892                   unop( Iop_32to8,
   10893                         binop( Iop_Or32,
   10894                                binop( Iop_And32,
   10895                                       unop( Iop_Not32,
   10896                                             binop( Iop_Shr32,
   10897                                                    mkexpr( ccIR ),
   10898                                                    mkU8( 5 ) ) ),
   10899                                       mkU32( 2 ) ),
   10900                                binop( Iop_And32,
   10901                                       binop( Iop_Xor32,
   10902                                              mkexpr( ccIR ),
   10903                                              binop( Iop_Shr32,
   10904                                                     mkexpr( ccIR ),
   10905                                                     mkU8( 6 ) ) ),
   10906                                       mkU32( 1 ) ) ) ) ) );
   10907 
   10908    putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
   10909    return True;
   10910 }
   10911 
   10912 /* Test class/group/exponent/significance instructions. */
   10913 static Bool dis_dfp_exponent_test ( UInt theInstr )
   10914 {
   10915    UChar frA_addr   = ifieldRegA( theInstr );
   10916    UChar frB_addr   = ifieldRegB( theInstr );
   10917    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );
   10918    IRTemp frA       = newTemp( Ity_D64 );
   10919    IRTemp frB       = newTemp( Ity_D64 );
   10920    IRTemp frA128    = newTemp( Ity_D128 );
   10921    IRTemp frB128    = newTemp( Ity_D128 );
   10922    UInt opc1        = ifieldOPC( theInstr );
   10923    IRTemp gfield_A  = newTemp( Ity_I32 );
   10924    IRTemp gfield_B  = newTemp( Ity_I32 );
   10925    IRTemp gfield_mask   = newTemp( Ity_I32 );
   10926    IRTemp exponent_A    = newTemp( Ity_I32 );
   10927    IRTemp exponent_B    = newTemp( Ity_I32 );
   10928    IRTemp A_NaN_true    = newTemp( Ity_I32 );
   10929    IRTemp B_NaN_true    = newTemp( Ity_I32 );
   10930    IRTemp A_inf_true    = newTemp( Ity_I32 );
   10931    IRTemp B_inf_true    = newTemp( Ity_I32 );
   10932    IRTemp A_equals_B    = newTemp( Ity_I32 );
   10933    IRTemp finite_number = newTemp( Ity_I32 );
   10934    IRTemp cc0 = newTemp( Ity_I32 );
   10935    IRTemp cc1 = newTemp( Ity_I32 );
   10936    IRTemp cc2 = newTemp( Ity_I32 );
   10937    IRTemp cc3 = newTemp( Ity_I32 );
   10938 
   10939    /* The dtstex and dtstexg instructions only differ in the size of the
   10940     * exponent field.  The following switch statement takes care of the size
   10941     * specific setup.  Once the value of the exponents, the G-field shift
   10942     * and mask is setup the remaining code is identical.
   10943     */
   10944    switch (opc1) {
   10945    case 0x3b: // dtstex       Extended instruction setup
   10946       DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
   10947       assign( frA, getDReg( frA_addr ) );
   10948       assign( frB, getDReg( frB_addr ) );
   10949       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
   10950       assign(exponent_A, unop( Iop_64to32,
   10951                                unop( Iop_ExtractExpD64,
   10952                                      mkexpr( frA ) ) ) );
   10953       assign(exponent_B, unop( Iop_64to32,
   10954                                unop( Iop_ExtractExpD64,
   10955                                      mkexpr( frB ) ) ) );
   10956       break;
   10957 
   10958    case 0x3F: //  dtstexq      Quad instruction setup
   10959       DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
   10960       assign( frA128, getDReg_pair( frA_addr ) );
   10961       assign( frB128, getDReg_pair( frB_addr ) );
   10962       assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
   10963       assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
   10964       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
   10965       assign( exponent_A, unop( Iop_64to32,
   10966                                 unop( Iop_ExtractExpD128,
   10967                                       mkexpr( frA128 ) ) ) );
   10968       assign( exponent_B, unop( Iop_64to32,
   10969                                 unop( Iop_ExtractExpD128,
   10970                                       mkexpr( frB128 ) ) ) );
   10971       break;
   10972    default:
   10973       vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
   10974       return False;
   10975    }
   10976 
   10977    /* Extract the Gfield */
   10978    assign( gfield_A, binop( Iop_And32,
   10979                             mkexpr( gfield_mask ),
   10980                             unop( Iop_64HIto32,
   10981                                   unop( Iop_ReinterpD64asI64,
   10982                                         mkexpr(frA) ) ) ) );
   10983 
   10984    assign( gfield_B, binop( Iop_And32,
   10985                             mkexpr( gfield_mask ),
   10986                             unop( Iop_64HIto32,
   10987                                   unop( Iop_ReinterpD64asI64,
   10988                                         mkexpr(frB) ) ) ) );
   10989 
   10990    /* check for NAN */
   10991    assign( A_NaN_true, binop(Iop_Or32,
   10992                              unop( Iop_1Sto32,
   10993                                    binop( Iop_CmpEQ32,
   10994                                           mkexpr( gfield_A ),
   10995                                           mkU32( 0x7C000000 ) ) ),
   10996                              unop( Iop_1Sto32,
   10997                                    binop( Iop_CmpEQ32,
   10998                                           mkexpr( gfield_A ),
   10999                                           mkU32( 0x7E000000 ) )
   11000                                    ) ) );
   11001    assign( B_NaN_true, binop(Iop_Or32,
   11002                              unop( Iop_1Sto32,
   11003                                    binop( Iop_CmpEQ32,
   11004                                           mkexpr( gfield_B ),
   11005                                           mkU32( 0x7C000000 ) ) ),
   11006                              unop( Iop_1Sto32,
   11007                                    binop( Iop_CmpEQ32,
   11008                                           mkexpr( gfield_B ),
   11009                                           mkU32( 0x7E000000 ) )
   11010                              ) ) );
   11011 
   11012    /* check for infinity */
   11013    assign( A_inf_true,
   11014            unop( Iop_1Sto32,
   11015                  binop( Iop_CmpEQ32,
   11016                         mkexpr( gfield_A ),
   11017                         mkU32( 0x78000000 ) ) ) );
   11018 
   11019    assign( B_inf_true,
   11020            unop( Iop_1Sto32,
   11021                  binop( Iop_CmpEQ32,
   11022                         mkexpr( gfield_B ),
   11023                         mkU32( 0x78000000 ) ) ) );
   11024 
   11025    assign( finite_number,
   11026            unop( Iop_Not32,
   11027                  binop( Iop_Or32,
   11028                         binop( Iop_Or32,
   11029                                mkexpr( A_NaN_true ),
   11030                                mkexpr( B_NaN_true ) ),
   11031                         binop( Iop_Or32,
   11032                                mkexpr( A_inf_true ),
   11033                                mkexpr( B_inf_true ) ) ) ) );
   11034 
   11035    /* Calculate the condition code bits
   11036     * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
   11037     * regardless of the value of the comparisons and cc3 is 1.  Otherwise,
   11038     * cc0, cc1 and cc0 reflect the results of the comparisons.
   11039     */
   11040    assign( A_equals_B,
   11041            binop( Iop_Or32,
   11042                   unop( Iop_1Uto32,
   11043                   binop( Iop_CmpEQ32,
   11044                          mkexpr( exponent_A ),
   11045                          mkexpr( exponent_B ) ) ),
   11046                   binop( Iop_Or32,
   11047                          binop( Iop_And32,
   11048                                 mkexpr( A_inf_true ),
   11049                                 mkexpr( B_inf_true ) ),
   11050                          binop( Iop_And32,
   11051                                 mkexpr( A_NaN_true ),
   11052                                 mkexpr( B_NaN_true ) ) ) ) );
   11053 
   11054    assign( cc0, binop( Iop_And32,
   11055                        mkexpr( finite_number ),
   11056                        binop( Iop_Shl32,
   11057                               unop( Iop_1Uto32,
   11058                                     binop( Iop_CmpLT32U,
   11059                                            mkexpr( exponent_A ),
   11060                                            mkexpr( exponent_B ) ) ),
   11061                                            mkU8( 3 ) ) ) );
   11062 
   11063    assign( cc1, binop( Iop_And32,
   11064                        mkexpr( finite_number ),
   11065                        binop( Iop_Shl32,
   11066                               unop( Iop_1Uto32,
   11067                                     binop( Iop_CmpLT32U,
   11068                                            mkexpr( exponent_B ),
   11069                                            mkexpr( exponent_A ) ) ),
   11070                                            mkU8( 2 ) ) ) );
   11071 
   11072    assign( cc2, binop( Iop_Shl32,
   11073                        binop( Iop_And32,
   11074                               mkexpr( A_equals_B ),
   11075                               mkU32( 1 ) ),
   11076                               mkU8( 1 ) ) );
   11077 
   11078    assign( cc3, binop( Iop_And32,
   11079                        unop( Iop_Not32, mkexpr( A_equals_B ) ),
   11080                        binop( Iop_And32,
   11081                               mkU32( 0x1 ),
   11082                               binop( Iop_Or32,
   11083                                      binop( Iop_Or32,
   11084                                             mkexpr ( A_inf_true ),
   11085                                             mkexpr ( B_inf_true ) ),
   11086                                             binop( Iop_Or32,
   11087                                                    mkexpr ( A_NaN_true ),
   11088                                                    mkexpr ( B_NaN_true ) ) )
   11089                               ) ) );
   11090 
   11091    /* store the condition code */
   11092    putGST_field( PPC_GST_CR,
   11093                  binop( Iop_Or32,
   11094                         mkexpr( cc0 ),
   11095                         binop( Iop_Or32,
   11096                                mkexpr( cc1 ),
   11097                                binop( Iop_Or32,
   11098                                       mkexpr( cc2 ),
   11099                                       mkexpr( cc3 ) ) ) ),
   11100                  crfD );
   11101    return True;
   11102 }
   11103 
   11104 /* Test class/group/exponent/significance instructions. */
   11105 static Bool dis_dfp_class_test ( UInt theInstr )
   11106 {
   11107    UChar frA_addr   = ifieldRegA( theInstr );
   11108    IRTemp frA       = newTemp( Ity_D64 );
   11109    IRTemp abs_frA   = newTemp( Ity_D64 );
   11110    IRTemp frAI64_hi = newTemp( Ity_I64 );
   11111    IRTemp frAI64_lo = newTemp( Ity_I64 );
   11112    UInt opc1        = ifieldOPC( theInstr );
   11113    UInt opc2        = ifieldOPClo9( theInstr );
   11114    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );  // AKA BF
   11115    UInt DCM         = IFIELD( theInstr, 10, 6 );
   11116    IRTemp DCM_calc  = newTemp( Ity_I32 );
   11117    UInt max_exp     = 0;
   11118    UInt min_exp     = 0;
   11119    IRTemp min_subnormalD64  = newTemp( Ity_D64 );
   11120    IRTemp min_subnormalD128 = newTemp( Ity_D128 );
   11121    IRTemp significand64  = newTemp( Ity_D64 );
   11122    IRTemp significand128 = newTemp( Ity_D128 );
   11123    IRTemp exp_min_normal = newTemp( Ity_I64 );
   11124    IRTemp exponent       = newTemp( Ity_I32 );
   11125 
   11126    IRTemp infinity_true  = newTemp( Ity_I32 );
   11127    IRTemp SNaN_true      = newTemp( Ity_I32 );
   11128    IRTemp QNaN_true      = newTemp( Ity_I32 );
   11129    IRTemp subnormal_true = newTemp( Ity_I32 );
   11130    IRTemp normal_true    = newTemp( Ity_I32 );
   11131    IRTemp extreme_true   = newTemp( Ity_I32 );
   11132    IRTemp lmd            = newTemp( Ity_I32 );
   11133    IRTemp lmd_zero_true  = newTemp( Ity_I32 );
   11134    IRTemp zero_true      = newTemp( Ity_I32 );
   11135    IRTemp sign           = newTemp( Ity_I32 );
   11136    IRTemp field          = newTemp( Ity_I32 );
   11137    IRTemp ccIR_zero      = newTemp( Ity_I32 );
   11138    IRTemp ccIR_subnormal = newTemp( Ity_I32 );
   11139 
   11140    /* UInt size     = DFP_LONG;  JRS:unused */
   11141    IRTemp gfield = newTemp( Ity_I32 );
   11142    IRTemp gfield_0_4_shift  = newTemp( Ity_I8 );
   11143    IRTemp gfield_mask       = newTemp( Ity_I32 );
   11144    IRTemp dcm0 = newTemp( Ity_I32 );
   11145    IRTemp dcm1 = newTemp( Ity_I32 );
   11146    IRTemp dcm2 = newTemp( Ity_I32 );
   11147    IRTemp dcm3 = newTemp( Ity_I32 );
   11148    IRTemp dcm4 = newTemp( Ity_I32 );
   11149    IRTemp dcm5 = newTemp( Ity_I32 );
   11150 
   11151    /* The only difference between the dtstdc and dtstdcq instructions is
   11152     * size of the T and G fields.  The calculation of the 4 bit field
   11153     * is the same.  Setup the parameters and values that are DFP size
   11154     * specific.  The rest of the code is independent of the DFP size.
   11155     *
   11156     * The Io_CmpD64 is used below.  The instruction sets the ccIR values.
   11157     * The interpretation of the ccIR values is as follows:
   11158     *
   11159     *    DFP cmp result | IR
   11160     * --------------------------
   11161     *	 UN             | 0x45
   11162     *	 EQ             | 0x40
   11163     *	 GT             | 0x00
   11164     *	 LT             | 0x01
   11165     */
   11166 
   11167    assign( frA, getDReg( frA_addr ) );
   11168    assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
   11169 
   11170    assign( abs_frA, unop( Iop_ReinterpI64asD64,
   11171                           binop( Iop_And64,
   11172                                  unop( Iop_ReinterpD64asI64,
   11173                                        mkexpr( frA ) ),
   11174                                  mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
   11175    assign( gfield_0_4_shift, mkU8( 31 - 5 ) );  // G-field[0:4]
   11176    switch (opc1) {
   11177    case 0x3b: // dtstdc, dtstdg
   11178       DIP("dtstd%s %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g",
   11179                crfD, frA_addr, DCM);
   11180       /* setup the parameters for the long format of the two instructions */
   11181       assign( frAI64_lo, mkU64( 0 ) );
   11182       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
   11183       max_exp = DFP_LONG_EXP_MAX;
   11184       min_exp = DFP_LONG_EXP_MIN;
   11185 
   11186       assign( exponent, unop( Iop_64to32,
   11187                               unop( Iop_ExtractExpD64,
   11188                                     mkexpr( frA ) ) ) );
   11189       assign( significand64,
   11190               unop( Iop_ReinterpI64asD64,
   11191                     mkU64( 0x2234000000000001ULL ) ) );  // dfp 1.0
   11192       assign( exp_min_normal,mkU64( 398 - 383 ) );
   11193       assign( min_subnormalD64,
   11194               binop( Iop_InsertExpD64,
   11195                      mkexpr( exp_min_normal ),
   11196                      mkexpr( significand64 ) ) );
   11197 
   11198       assign( ccIR_subnormal,
   11199               binop( Iop_CmpD64,
   11200                      mkexpr( abs_frA ),
   11201                      mkexpr( min_subnormalD64 ) ) );
   11202 
   11203       /* compare absolute value of frA with zero */
   11204       assign( ccIR_zero,
   11205               binop( Iop_CmpD64,
   11206                      mkexpr( abs_frA ),
   11207                      unop( Iop_ReinterpI64asD64,
   11208                            mkU64( 0x2238000000000000ULL ) ) ) );
   11209 
   11210       /* size = DFP_LONG; JRS: unused */
   11211       break;
   11212 
   11213    case 0x3F:   // dtstdcq, dtstdgq
   11214       DIP("dtstd%sq %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g",
   11215                crfD, frA_addr, DCM);
   11216       /* setup the parameters for the extended format of the
   11217        * two instructions
   11218        */
   11219       assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
   11220                                getDReg( frA_addr+1 ) ) );
   11221 
   11222       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
   11223       max_exp = DFP_EXTND_EXP_MAX;
   11224       min_exp = DFP_EXTND_EXP_MIN;
   11225       assign( exponent, unop( Iop_64to32,
   11226                               unop( Iop_ExtractExpD128,
   11227                                     getDReg_pair( frA_addr) ) ) );
   11228 
   11229       /* create quand exponent for minimum normal number */
   11230       assign( exp_min_normal, mkU64( 6176 - 6143 ) );
   11231       assign( significand128,
   11232               unop( Iop_D64toD128,
   11233                     unop( Iop_ReinterpI64asD64,
   11234                           mkU64( 0x2234000000000001ULL ) ) ) );  // dfp 1.0
   11235 
   11236       assign( min_subnormalD128,
   11237               binop( Iop_InsertExpD128,
   11238                      mkexpr( exp_min_normal ),
   11239                      mkexpr( significand128 ) ) );
   11240 
   11241       assign( ccIR_subnormal,
   11242               binop( Iop_CmpD128,
   11243                      binop( Iop_D64HLtoD128,
   11244                             unop( Iop_ReinterpI64asD64,
   11245                                   binop( Iop_And64,
   11246                                          unop( Iop_ReinterpD64asI64,
   11247                                                mkexpr( frA ) ),
   11248                                          mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
   11249                             getDReg( frA_addr+1 ) ),
   11250                      mkexpr( min_subnormalD128 ) ) );
   11251       assign( ccIR_zero,
   11252               binop( Iop_CmpD128,
   11253                      binop( Iop_D64HLtoD128,
   11254                             mkexpr( abs_frA ),
   11255                             getDReg( frA_addr+1 ) ),
   11256                      unop( Iop_D64toD128,
   11257                            unop( Iop_ReinterpI64asD64,
   11258                                  mkU64( 0x0ULL ) ) ) ) );
   11259 
   11260       /* size = DFP_EXTND; JRS:unused */
   11261       break;
   11262    default:
   11263       vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
   11264       return False;
   11265    }
   11266 
   11267    /* The G-field is in the upper 32-bits.  The I64 logical operations
   11268     * do not seem to be supported in 32-bit mode so keep things as 32-bit
   11269     * operations.
   11270     */
   11271    assign( gfield, binop( Iop_And32,
   11272                           mkexpr( gfield_mask ),
   11273                           unop( Iop_64HIto32,
   11274                                 mkexpr(frAI64_hi) ) ) );
   11275 
   11276    /* There is a lot of code that is the same to do the class and group
   11277     * instructions.  Later there is an if statement to handle the specific
   11278     * instruction.
   11279     *
   11280     * Will be using I32 values, compares, shifts and logical operations for
   11281     * this code as the 64-bit compare, shifts, logical operations are not
   11282     * supported in 32-bit mode.
   11283     */
   11284 
   11285    /* Check the bits for Infinity, QNaN or Signaling NaN */
   11286    assign( infinity_true,
   11287            unop( Iop_1Sto32,
   11288                  binop( Iop_CmpEQ32,
   11289                         binop( Iop_And32,
   11290                                mkU32( 0x7C000000 ),
   11291                                mkexpr( gfield ) ),
   11292                         mkU32( 0x78000000 ) ) ) );
   11293 
   11294    assign( SNaN_true,
   11295            unop( Iop_1Sto32,
   11296                  binop( Iop_CmpEQ32,
   11297                         binop( Iop_And32,
   11298                                mkU32( 0x7E000000 ),
   11299                                mkexpr( gfield ) ),
   11300                         mkU32( 0x7E000000 ) ) ) );
   11301 
   11302    assign( QNaN_true,
   11303            binop( Iop_And32,
   11304                   unop( Iop_1Sto32,
   11305                        binop( Iop_CmpEQ32,
   11306                               binop( Iop_And32,
   11307                                      mkU32( 0x7E000000 ),
   11308                                      mkexpr( gfield ) ),
   11309                               mkU32( 0x7C000000 ) ) ),
   11310                   unop( Iop_Not32,
   11311                         mkexpr( SNaN_true ) ) ) );
   11312 
   11313    assign( zero_true,
   11314            binop( Iop_And32,
   11315                   unop(Iop_1Sto32,
   11316                        binop( Iop_CmpEQ32,
   11317                               mkexpr( ccIR_zero ),
   11318                               mkU32( 0x40 ) ) ),  // ccIR code for Equal
   11319                   unop( Iop_Not32,
   11320                         binop( Iop_Or32,
   11321                                mkexpr( infinity_true ),
   11322                                binop( Iop_Or32,
   11323                                       mkexpr( QNaN_true ),
   11324                                       mkexpr( SNaN_true ) ) ) ) ) );
   11325 
   11326    /* Do compare of frA the minimum normal value.  Comparison is size
   11327     * depenent and was done above to get the ccIR value.
   11328     */
   11329    assign( subnormal_true,
   11330            binop( Iop_And32,
   11331                   binop( Iop_Or32,
   11332                          unop( Iop_1Sto32,
   11333                                binop( Iop_CmpEQ32,
   11334                                       mkexpr( ccIR_subnormal ),
   11335                                       mkU32( 0x40 ) ) ), // ccIR code for Equal
   11336                          unop( Iop_1Sto32,
   11337                                binop( Iop_CmpEQ32,
   11338                                       mkexpr( ccIR_subnormal ),
   11339                                       mkU32( 0x1 ) ) ) ), // ccIR code for LT
   11340            unop( Iop_Not32,
   11341                  binop( Iop_Or32,
   11342                         binop( Iop_Or32,
   11343                                mkexpr( infinity_true ),
   11344                                mkexpr( zero_true) ),
   11345                         binop( Iop_Or32,
   11346                                mkexpr( QNaN_true ),
   11347                                mkexpr( SNaN_true ) ) ) ) ) );
   11348 
   11349    /* Normal number is not subnormal, infinity, NaN or Zero */
   11350    assign( normal_true,
   11351            unop( Iop_Not32,
   11352                  binop( Iop_Or32,
   11353                         binop( Iop_Or32,
   11354                                mkexpr( infinity_true ),
   11355                                mkexpr( zero_true ) ),
   11356                         binop( Iop_Or32,
   11357                                mkexpr( subnormal_true ),
   11358                                binop( Iop_Or32,
   11359                                       mkexpr( QNaN_true ),
   11360                                       mkexpr( SNaN_true ) ) ) ) ) );
   11361 
   11362    /* Calculate the DCM bit field based on the tests for the specific
   11363     * instruction
   11364     */
   11365    if (opc2 == 0xC2) {    // dtstdc, dtstdcq
   11366       /* DCM[0:5] Bit   Data Class definition
   11367        *   0   Zero
   11368        *   1   Subnormal
   11369        *   2   Normal
   11370        *   3   Infinity
   11371        *   4   Quiet NaN
   11372        *   5   Signaling NaN
   11373        */
   11374 
   11375       assign( dcm0, binop( Iop_Shl32,
   11376                            mkexpr( zero_true ),
   11377                            mkU8( 5 ) ) );
   11378       assign( dcm1, binop( Iop_Shl32,
   11379                            binop( Iop_And32,
   11380                                   mkexpr( subnormal_true ),
   11381                                   mkU32( 1 ) ),
   11382                            mkU8( 4 ) ) );
   11383       assign( dcm2, binop( Iop_Shl32,
   11384                            binop( Iop_And32,
   11385                                   mkexpr( normal_true ),
   11386                                   mkU32( 1 ) ),
   11387                            mkU8( 3 ) ) );
   11388       assign( dcm3, binop( Iop_Shl32,
   11389                            binop( Iop_And32,
   11390                                   mkexpr( infinity_true),
   11391                                   mkU32( 1 ) ),
   11392                            mkU8( 2 ) ) );
   11393       assign( dcm4, binop( Iop_Shl32,
   11394                            binop( Iop_And32,
   11395                                   mkexpr( QNaN_true ),
   11396                                   mkU32( 1 ) ),
   11397                            mkU8( 1 ) ) );
   11398       assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
   11399 
   11400    } else if (opc2 == 0xE2) {   // dtstdg, dtstdgq
   11401       /* check if the exponent is extreme */
   11402       assign( extreme_true, binop( Iop_Or32,
   11403                                    unop( Iop_1Sto32,
   11404                                          binop( Iop_CmpEQ32,
   11405                                                 mkexpr( exponent ),
   11406                                                 mkU32( max_exp ) ) ),
   11407                                    unop( Iop_1Sto32,
   11408                                          binop( Iop_CmpEQ32,
   11409                                                 mkexpr( exponent ),
   11410                                                 mkU32( min_exp ) ) ) ) );
   11411 
   11412       /* Check if LMD is zero */
   11413       Get_lmd( &lmd, binop( Iop_Shr32,
   11414                             mkexpr( gfield ), mkU8( 31 - 5 ) ) );
   11415 
   11416       assign( lmd_zero_true, unop( Iop_1Sto32,
   11417                                    binop( Iop_CmpEQ32,
   11418                                           mkexpr( lmd ),
   11419                                           mkU32( 0 ) ) ) );
   11420 
   11421       /* DCM[0:5] Bit   Data Class definition
   11422        *  0   Zero with non-extreme exponent
   11423        *  1   Zero with extreme exponent
   11424        *  2   Subnormal or (Normal with extreme exponent)
   11425        *  3   Normal with non-extreme exponent and
   11426        *      leftmost zero digit in significand
   11427        *  4   Normal with non-extreme exponent and
   11428        *      leftmost nonzero digit in significand
   11429        *  5   Special symbol (Infinity, QNaN, or SNaN)
   11430        */
   11431       assign( dcm0, binop( Iop_Shl32,
   11432                            binop( Iop_And32,
   11433                                   binop( Iop_And32,
   11434                                          unop( Iop_Not32,
   11435                                                mkexpr( extreme_true ) ),
   11436                                          mkexpr( zero_true ) ),
   11437                                   mkU32( 0x1 ) ),
   11438                            mkU8( 5 ) ) );
   11439 
   11440       assign( dcm1, binop( Iop_Shl32,
   11441                            binop( Iop_And32,
   11442                                   binop( Iop_And32,
   11443                                          mkexpr( extreme_true ),
   11444                                          mkexpr( zero_true ) ),
   11445                                   mkU32( 0x1 ) ),
   11446                            mkU8( 4 ) ) );
   11447 
   11448       assign( dcm2, binop( Iop_Shl32,
   11449                            binop( Iop_And32,
   11450                                   binop( Iop_Or32,
   11451                                          binop( Iop_And32,
   11452                                                 mkexpr( extreme_true ),
   11453                                                 mkexpr( normal_true ) ),
   11454                                          mkexpr( subnormal_true ) ),
   11455                                   mkU32( 0x1 ) ),
   11456                            mkU8( 3 ) ) );
   11457 
   11458       assign( dcm3, binop( Iop_Shl32,
   11459                            binop( Iop_And32,
   11460                                   binop( Iop_And32,
   11461                                          binop( Iop_And32,
   11462                                                 unop( Iop_Not32,
   11463                                                       mkexpr( extreme_true ) ),
   11464                                                       mkexpr( normal_true ) ),
   11465                                          unop( Iop_1Sto32,
   11466                                                binop( Iop_CmpEQ32,
   11467                                                       mkexpr( lmd ),
   11468                                                       mkU32( 0 ) ) ) ),
   11469                                   mkU32( 0x1 ) ),
   11470                            mkU8( 2 ) ) );
   11471 
   11472       assign( dcm4, binop( Iop_Shl32,
   11473                            binop( Iop_And32,
   11474                                   binop( Iop_And32,
   11475                                          binop( Iop_And32,
   11476                                                 unop( Iop_Not32,
   11477                                                       mkexpr( extreme_true ) ),
   11478                                                 mkexpr( normal_true ) ),
   11479                                           unop( Iop_1Sto32,
   11480                                                 binop( Iop_CmpNE32,
   11481                                                        mkexpr( lmd ),
   11482                                                        mkU32( 0 ) ) ) ),
   11483                                   mkU32( 0x1 ) ),
   11484                            mkU8( 1 ) ) );
   11485 
   11486       assign( dcm5, binop( Iop_And32,
   11487                            binop( Iop_Or32,
   11488                                   mkexpr( SNaN_true),
   11489                                   binop( Iop_Or32,
   11490                                          mkexpr( QNaN_true),
   11491                                          mkexpr( infinity_true) ) ),
   11492                            mkU32( 0x1 ) ) );
   11493    }
   11494 
   11495    /* create DCM field */
   11496    assign( DCM_calc,
   11497            binop( Iop_Or32,
   11498                   mkexpr( dcm0 ),
   11499                   binop( Iop_Or32,
   11500                          mkexpr( dcm1 ),
   11501                          binop( Iop_Or32,
   11502                                 mkexpr( dcm2 ),
   11503                                 binop( Iop_Or32,
   11504                                        mkexpr( dcm3 ),
   11505                                        binop( Iop_Or32,
   11506                                               mkexpr( dcm4 ),
   11507                                               mkexpr( dcm5 ) ) ) ) ) ) );
   11508 
   11509    /* Get the sign of the DFP number, ignore sign for QNaN */
   11510    assign( sign,
   11511            unop( Iop_1Uto32,
   11512                  binop( Iop_CmpEQ32,
   11513                         binop( Iop_Shr32,
   11514                                unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
   11515                                mkU8( 63 - 32 ) ),
   11516                         mkU32( 1 ) ) ) );
   11517 
   11518    /* This instruction generates a four bit field to be stored in the
   11519     * condition code register.  The condition code register consists of 7
   11520     * fields.  The field to be written to is specified by the BF (AKA crfD)
   11521     * field.
   11522     *
   11523     * The field layout is as follows:
   11524     *
   11525     *      Field          Meaning
   11526     *      0000           Operand positive with no match
   11527     *      0100           Operand positive with at least one match
   11528     *      0001           Operand negative with no match
   11529     *      0101           Operand negative with at least one match
   11530     */
   11531    assign( field, binop( Iop_Or32,
   11532                          binop( Iop_Shl32,
   11533                                 mkexpr( sign ),
   11534                                 mkU8( 3 ) ),
   11535                                 binop( Iop_Shl32,
   11536                                        unop( Iop_1Uto32,
   11537                                              binop( Iop_CmpNE32,
   11538                                                     binop( Iop_And32,
   11539                                                            mkU32( DCM ),
   11540                                                            mkexpr( DCM_calc ) ),
   11541                                                      mkU32( 0 ) ) ),
   11542                                        mkU8( 1 ) ) ) );
   11543 
   11544    putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
   11545    return True;
   11546 }
   11547 
   11548 static Bool dis_dfp_bcd(UInt theInstr) {
   11549    UInt opc2        = ifieldOPClo10( theInstr );
   11550    ULong sp         = IFIELD(theInstr, 19, 2);
   11551    ULong s          = IFIELD(theInstr, 20, 1);
   11552    UChar frT_addr   = ifieldRegDS( theInstr );
   11553    UChar frB_addr   = ifieldRegB( theInstr );
   11554    IRTemp frB       = newTemp( Ity_D64 );
   11555    IRTemp frBI64    = newTemp( Ity_I64 );
   11556    IRTemp result    = newTemp( Ity_I64 );
   11557    IRTemp resultD64 = newTemp( Ity_D64 );
   11558    IRTemp bcd64     = newTemp( Ity_I64 );
   11559    IRTemp bcd_u     = newTemp( Ity_I32 );
   11560    IRTemp bcd_l     = newTemp( Ity_I32 );
   11561    IRTemp dbcd_u    = newTemp( Ity_I32 );
   11562    IRTemp dbcd_l    = newTemp( Ity_I32 );
   11563    IRTemp lmd       = newTemp( Ity_I32 );
   11564 
   11565    assign( frB, getDReg( frB_addr ) );
   11566    assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
   11567 
   11568    switch ( opc2 ) {
   11569    case 0x142: // ddedpd   DFP Decode DPD to BCD
   11570       DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
   11571 
   11572          assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
   11573          assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
   11574          assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
   11575 
   11576       if ( ( sp == 0 ) || ( sp == 1 ) ) {
   11577          /* Unsigned BCD string */
   11578          Get_lmd( &lmd,
   11579                   binop( Iop_Shr32,
   11580                          unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11581                          mkU8( 31 - 5 ) ) ); // G-field[0:4]
   11582 
   11583          assign( result,
   11584                  binop( Iop_32HLto64,
   11585                         binop( Iop_Or32,
   11586                                binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
   11587                                mkexpr( bcd_u ) ),
   11588                         mkexpr( bcd_l ) ) );
   11589 
   11590       } else {
   11591          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
   11592           * the positive and negative values are encoded in the least
   11593           * significant bits.
   11594           */
   11595          IRTemp sign = newTemp( Ity_I32 );
   11596 
   11597          if (sp == 2) {
   11598             /* Positive sign = 0xC, negative sign = 0xD */
   11599 
   11600             assign( sign,
   11601                     binop( Iop_Or32,
   11602                            binop( Iop_Shr32,
   11603                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11604                                   mkU8( 31 ) ),
   11605                            mkU32( 0xC ) ) );
   11606 
   11607          } else if ( sp == 3 ) {
   11608             /* Positive sign = 0xF, negative sign = 0xD */
   11609             IRTemp tmp32 = newTemp( Ity_I32 );
   11610 
   11611             /* Complement sign bit then OR into bit position 1 */
   11612             assign( tmp32,
   11613                     binop( Iop_Xor32,
   11614                            binop( Iop_Shr32,
   11615                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11616                                   mkU8( 30 ) ),
   11617                            mkU32( 0x2 ) ) );
   11618 
   11619             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
   11620 
   11621          } else {
   11622             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
   11623          }
   11624 
   11625          /* Put sign in bottom 4 bits, move most significant 4-bits from
   11626           * bcd_l to bcd_u.
   11627           */
   11628          assign( result,
   11629                  binop( Iop_32HLto64,
   11630                         binop( Iop_Or32,
   11631                                binop( Iop_Shr32,
   11632                                       mkexpr( bcd_l ),
   11633                                       mkU8( 28 ) ),
   11634                                binop( Iop_Shl32,
   11635                                       mkexpr( bcd_u ),
   11636                                       mkU8( 4 ) ) ),
   11637                         binop( Iop_Or32,
   11638                                       mkexpr( sign ),
   11639                                binop( Iop_Shl32,
   11640                                       mkexpr( bcd_l ),
   11641                                       mkU8( 4 ) ) ) ) );
   11642       }
   11643 
   11644       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
   11645       break;
   11646 
   11647    case 0x342: // denbcd   DFP Encode BCD to DPD
   11648    {
   11649       IRTemp valid_mask   = newTemp( Ity_I32 );
   11650       IRTemp invalid_mask = newTemp( Ity_I32 );
   11651       IRTemp without_lmd  = newTemp( Ity_I64 );
   11652       IRTemp tmp64        = newTemp( Ity_I64 );
   11653       IRTemp dbcd64       = newTemp( Ity_I64 );
   11654       IRTemp left_exp     = newTemp( Ity_I32 );
   11655       IRTemp g0_4         = newTemp( Ity_I32 );
   11656 
   11657       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
   11658 
   11659       if ( s == 0 ) {
   11660          /* Unsigned BCD string */
   11661          assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
   11662          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
   11663          assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
   11664 
   11665          assign( lmd,
   11666                  binop( Iop_Shr32,
   11667                         binop( Iop_And32,
   11668                                unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11669                                mkU32( 0xF0000000 ) ),
   11670                         mkU8( 28 ) ) );
   11671 
   11672          assign( invalid_mask,
   11673                  bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11674                                   unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
   11675          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   11676 
   11677          assign( without_lmd,
   11678                  unop( Iop_ReinterpD64asI64,
   11679                        binop( Iop_InsertExpD64,
   11680                               mkU64( DFP_LONG_BIAS ),
   11681                               unop( Iop_ReinterpI64asD64,
   11682                                     binop( Iop_32HLto64,
   11683                                            mkexpr( dbcd_u ),
   11684                                            mkexpr( dbcd_l ) ) ) ) ) );
   11685          assign( left_exp,
   11686                  binop( Iop_Shr32,
   11687                         binop( Iop_And32,
   11688                                unop( Iop_64HIto32, mkexpr( without_lmd ) ),
   11689                                mkU32( 0x60000000 ) ),
   11690                         mkU8( 29 ) ) );
   11691 
   11692          assign( g0_4,
   11693                  binop( Iop_Shl32,
   11694                         Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
   11695                         mkU8( 26 ) ) );
   11696 
   11697          assign( tmp64,
   11698                  binop( Iop_32HLto64,
   11699                         binop( Iop_Or32,
   11700                                binop( Iop_And32,
   11701                                       unop( Iop_64HIto32,
   11702                                             mkexpr( without_lmd ) ),
   11703                                       mkU32( 0x83FFFFFF ) ),
   11704                                mkexpr( g0_4 ) ),
   11705                         unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
   11706 
   11707       } else if ( s == 1 ) {
   11708          IRTemp sign = newTemp( Ity_I32 );
   11709          IRTemp sign_bit = newTemp( Ity_I32 );
   11710          IRTemp pos_sign_mask = newTemp( Ity_I32 );
   11711          IRTemp neg_sign_mask = newTemp( Ity_I32 );
   11712          IRTemp tmp = newTemp( Ity_I64 );
   11713 
   11714          /* Signed BCD string, least significant 4 bits are sign bits
   11715           * positive sign = 0xC, negative sign = 0xD
   11716           */
   11717          assign( tmp, unop( Iop_BCDtoDPB,
   11718                             binop( Iop_32HLto64,
   11719                                    binop( Iop_Shr32,
   11720                                           unop( Iop_64HIto32,
   11721                                                 mkexpr( frBI64 ) ),
   11722                                                 mkU8( 4 ) ),
   11723                                    binop( Iop_Or32,
   11724                                           binop( Iop_Shr32,
   11725                                                  unop( Iop_64to32,
   11726                                                        mkexpr( frBI64 ) ),
   11727                                                   mkU8( 4 ) ),
   11728                                           binop( Iop_Shl32,
   11729                                                  unop( Iop_64HIto32,
   11730                                                        mkexpr( frBI64 ) ),
   11731                                                        mkU8( 28 ) ) ) ) ) );
   11732 
   11733          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
   11734          assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
   11735 
   11736          /* Get the sign of the BCD string. */
   11737          assign( sign,
   11738                  binop( Iop_And32,
   11739                         unop( Iop_64to32, mkexpr( frBI64 ) ),
   11740                         mkU32( 0xF ) ) );
   11741 
   11742          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
   11743          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
   11744          assign( sign_bit,
   11745                  Generate_sign_bit( mkexpr( pos_sign_mask ),
   11746                                     mkexpr( neg_sign_mask ) ) );
   11747 
   11748          /* Check for invalid sign and BCD digit.  Don't check the bottom
   11749           * four bits of bcd_l as that is the sign value.
   11750           */
   11751          assign( invalid_mask,
   11752                  Generate_inv_mask(
   11753                                    bcd_digit_inval( unop( Iop_64HIto32,
   11754                                                           mkexpr( frBI64 ) ),
   11755                                                     binop( Iop_Shr32,
   11756                                                            unop( Iop_64to32,
   11757                                                                  mkexpr( frBI64 ) ),
   11758                                                            mkU8( 4 ) ) ),
   11759                                    mkexpr( pos_sign_mask ),
   11760                                    mkexpr( neg_sign_mask ) ) );
   11761 
   11762          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   11763 
   11764          /* Generate the result assuming the sign value was valid. */
   11765          assign( tmp64,
   11766                  unop( Iop_ReinterpD64asI64,
   11767                        binop( Iop_InsertExpD64,
   11768                               mkU64( DFP_LONG_BIAS ),
   11769                               unop( Iop_ReinterpI64asD64,
   11770                                     binop( Iop_32HLto64,
   11771                                            binop( Iop_Or32,
   11772                                                   mkexpr( dbcd_u ),
   11773                                                   mkexpr( sign_bit ) ),
   11774                                            mkexpr( dbcd_l ) ) ) ) ) );
   11775       }
   11776 
   11777       /* Generate the value to store depending on the validity of the
   11778        * sign value and the validity of the BCD digits.
   11779        */
   11780       assign( resultD64,
   11781               unop( Iop_ReinterpI64asD64,
   11782                     binop( Iop_32HLto64,
   11783                            binop( Iop_Or32,
   11784                                   binop( Iop_And32,
   11785                                          mkexpr( valid_mask ),
   11786                                          unop( Iop_64HIto32,
   11787                                                mkexpr( tmp64 ) ) ),
   11788                                   binop( Iop_And32,
   11789                                          mkU32( 0x7C000000 ),
   11790                                          mkexpr( invalid_mask ) ) ),
   11791                            binop( Iop_Or32,
   11792                                   binop( Iop_And32,
   11793                                          mkexpr( valid_mask ),
   11794                                          unop( Iop_64to32, mkexpr( tmp64 ) ) ),
   11795                                   binop( Iop_And32,
   11796                                          mkU32( 0x0 ),
   11797                                          mkexpr( invalid_mask ) ) ) ) ) );
   11798       putDReg( frT_addr, mkexpr( resultD64 ) );
   11799    }
   11800    break;
   11801    default:
   11802       vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
   11803       return False;
   11804    }
   11805    return True;
   11806 }
   11807 
   11808 static Bool dis_dfp_bcdq( UInt theInstr )
   11809 {
   11810    UInt opc2        = ifieldOPClo10( theInstr );
   11811    ULong sp         = IFIELD(theInstr, 19, 2);
   11812    ULong s          = IFIELD(theInstr, 20, 1);
   11813    IRTemp frB_hi    = newTemp( Ity_D64 );
   11814    IRTemp frB_lo    = newTemp( Ity_D64 );
   11815    IRTemp frBI64_hi = newTemp( Ity_I64 );
   11816    IRTemp frBI64_lo = newTemp( Ity_I64 );
   11817    UChar frT_addr   = ifieldRegDS( theInstr );
   11818    UChar frB_addr   = ifieldRegB( theInstr );
   11819 
   11820    IRTemp lmd       = newTemp( Ity_I32 );
   11821    IRTemp result_hi = newTemp( Ity_I64 );
   11822    IRTemp result_lo = newTemp( Ity_I64 );
   11823 
   11824    assign( frB_hi, getDReg( frB_addr ) );
   11825    assign( frB_lo, getDReg( frB_addr + 1 ) );
   11826    assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
   11827    assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
   11828 
   11829    switch ( opc2 ) {
   11830    case 0x142: // ddedpdq   DFP Decode DPD to BCD
   11831    {
   11832       IRTemp low_60_u = newTemp( Ity_I32 );
   11833       IRTemp low_60_l = newTemp( Ity_I32 );
   11834       IRTemp mid_60_u = newTemp( Ity_I32 );
   11835       IRTemp mid_60_l = newTemp( Ity_I32 );
   11836       IRTemp top_12_l = newTemp( Ity_I32 );
   11837 
   11838       DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
   11839 
   11840       /* Note, instruction only stores the lower 32 BCD digits in
   11841        * the result
   11842        */
   11843       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
   11844                                    mkexpr( frBI64_lo ),
   11845                                    &top_12_l,
   11846                                    &mid_60_u,
   11847                                    &mid_60_l,
   11848                                    &low_60_u,
   11849                                    &low_60_l );
   11850 
   11851       if ( ( sp == 0 ) || ( sp == 1 ) ) {
   11852          /* Unsigned BCD string */
   11853          assign( result_hi,
   11854                  binop( Iop_32HLto64,
   11855                         binop( Iop_Or32,
   11856                                binop( Iop_Shl32,
   11857                                       mkexpr( top_12_l ),
   11858                                       mkU8( 24 ) ),
   11859                                binop( Iop_Shr32,
   11860                                       mkexpr( mid_60_u ),
   11861                                       mkU8( 4 ) ) ),
   11862                         binop( Iop_Or32,
   11863                                binop( Iop_Shl32,
   11864                                       mkexpr( mid_60_u ),
   11865                                       mkU8( 28 ) ),
   11866                                binop( Iop_Shr32,
   11867                                       mkexpr( mid_60_l ),
   11868                                       mkU8( 4 ) ) ) ) );
   11869 
   11870          assign( result_lo,
   11871                  binop( Iop_32HLto64,
   11872                         binop( Iop_Or32,
   11873                                binop( Iop_Shl32,
   11874                                       mkexpr( mid_60_l ),
   11875                                       mkU8( 28 ) ),
   11876                                mkexpr( low_60_u ) ),
   11877                         mkexpr( low_60_l ) ) );
   11878 
   11879       } else {
   11880          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
   11881           * the positive and negative values are encoded in the least
   11882           * significant bits.
   11883           */
   11884          IRTemp sign = newTemp( Ity_I32 );
   11885 
   11886          if ( sp == 2 ) {
   11887             /* Positive sign = 0xC, negative sign = 0xD */
   11888             assign( sign,
   11889                     binop( Iop_Or32,
   11890                            binop( Iop_Shr32,
   11891                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   11892                                   mkU8( 31 ) ),
   11893                            mkU32( 0xC ) ) );
   11894 
   11895          } else if ( sp == 3 ) {
   11896             IRTemp tmp32 = newTemp( Ity_I32 );
   11897 
   11898             /* Positive sign = 0xF, negative sign = 0xD.
   11899              * Need to complement sign bit then OR into bit position 1.
   11900              */
   11901             assign( tmp32,
   11902                     binop( Iop_Xor32,
   11903                            binop( Iop_Shr32,
   11904                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   11905                                   mkU8( 30 ) ),
   11906                            mkU32( 0x2 ) ) );
   11907 
   11908             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
   11909 
   11910          } else {
   11911             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
   11912          }
   11913 
   11914          assign( result_hi,
   11915                  binop( Iop_32HLto64,
   11916                         binop( Iop_Or32,
   11917                                binop( Iop_Shl32,
   11918                                       mkexpr( top_12_l ),
   11919                                       mkU8( 28 ) ),
   11920                                mkexpr( mid_60_u ) ),
   11921                         mkexpr( mid_60_l ) ) );
   11922 
   11923          assign( result_lo,
   11924                  binop( Iop_32HLto64,
   11925                         binop( Iop_Or32,
   11926                                binop( Iop_Shl32,
   11927                                       mkexpr( low_60_u ),
   11928                                       mkU8( 4 ) ),
   11929                                binop( Iop_Shr32,
   11930                                       mkexpr( low_60_l ),
   11931                                       mkU8( 28 ) ) ),
   11932                         binop( Iop_Or32,
   11933                                binop( Iop_Shl32,
   11934                                       mkexpr( low_60_l ),
   11935                                       mkU8( 4 ) ),
   11936                                mkexpr( sign ) ) ) );
   11937       }
   11938 
   11939       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
   11940       putDReg( frT_addr + 1,
   11941                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
   11942    }
   11943    break;
   11944    case 0x342: // denbcdq   DFP Encode BCD to DPD
   11945    {
   11946       IRTemp valid_mask      = newTemp( Ity_I32 );
   11947       IRTemp invalid_mask    = newTemp( Ity_I32 );
   11948       IRTemp result128       = newTemp( Ity_D128 );
   11949       IRTemp dfp_significand = newTemp( Ity_D128 );
   11950       IRTemp tmp_hi          = newTemp( Ity_I64 );
   11951       IRTemp tmp_lo          = newTemp( Ity_I64 );
   11952       IRTemp dbcd_top_l      = newTemp( Ity_I32 );
   11953       IRTemp dbcd_mid_u      = newTemp( Ity_I32 );
   11954       IRTemp dbcd_mid_l      = newTemp( Ity_I32 );
   11955       IRTemp dbcd_low_u      = newTemp( Ity_I32 );
   11956       IRTemp dbcd_low_l      = newTemp( Ity_I32 );
   11957       IRTemp bcd_top_8       = newTemp( Ity_I64 );
   11958       IRTemp bcd_mid_60      = newTemp( Ity_I64 );
   11959       IRTemp bcd_low_60      = newTemp( Ity_I64 );
   11960       IRTemp sign_bit        = newTemp( Ity_I32 );
   11961       IRTemp tmptop10        = newTemp( Ity_I64 );
   11962       IRTemp tmpmid50        = newTemp( Ity_I64 );
   11963       IRTemp tmplow50        = newTemp( Ity_I64 );
   11964       IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
   11965 
   11966       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
   11967 
   11968       if ( s == 0 ) {
   11969          /* Unsigned BCD string */
   11970          assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
   11971 
   11972          assign( bcd_top_8,
   11973                  binop( Iop_32HLto64,
   11974                         mkU32( 0 ),
   11975                         binop( Iop_And32,
   11976                                binop( Iop_Shr32,
   11977                                       unop( Iop_64HIto32,
   11978                                             mkexpr( frBI64_hi ) ),
   11979                                       mkU8( 24 ) ),
   11980                                mkU32( 0xFF ) ) ) );
   11981          assign( bcd_mid_60,
   11982                  binop( Iop_32HLto64,
   11983                         binop( Iop_Or32,
   11984                                binop( Iop_Shr32,
   11985                                       unop( Iop_64to32,
   11986                                             mkexpr( frBI64_hi ) ),
   11987                                       mkU8( 28 ) ),
   11988                                binop( Iop_Shl32,
   11989                                       unop( Iop_64HIto32,
   11990                                             mkexpr( frBI64_hi ) ),
   11991                                       mkU8( 4 ) ) ),
   11992                         binop( Iop_Or32,
   11993                                binop( Iop_Shl32,
   11994                                       unop( Iop_64to32,
   11995                                             mkexpr( frBI64_hi ) ),
   11996                                       mkU8( 4 ) ),
   11997                                binop( Iop_Shr32,
   11998                                       unop( Iop_64HIto32,
   11999                                             mkexpr( frBI64_lo ) ),
   12000                                       mkU8( 28 ) ) ) ) );
   12001 
   12002          /* Note, the various helper functions ignores top 4-bits */
   12003          assign( bcd_low_60, mkexpr( frBI64_lo ) );
   12004 
   12005          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
   12006          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
   12007 
   12008          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
   12009          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
   12010          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
   12011 
   12012          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
   12013          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
   12014          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
   12015 
   12016          /* The entire BCD string fits in lower 110-bits.  The LMD = 0,
   12017           * value is not part of the final result. Only the right most
   12018           * BCD digits are stored.
   12019           */
   12020          assign( lmd, mkU32( 0 ) );
   12021 
   12022          assign( invalid_mask,
   12023                  binop( Iop_Or32,
   12024                         bcd_digit_inval( mkU32( 0 ),
   12025                                          unop( Iop_64to32,
   12026                                                mkexpr( bcd_top_8 ) ) ),
   12027                         binop( Iop_Or32,
   12028                                bcd_digit_inval( unop( Iop_64HIto32,
   12029                                                       mkexpr( bcd_mid_60 ) ),
   12030                                                 unop( Iop_64to32,
   12031                                                       mkexpr( bcd_mid_60 ) ) ),
   12032                                bcd_digit_inval( unop( Iop_64HIto32,
   12033                                                       mkexpr( bcd_low_60 ) ),
   12034                                                 unop( Iop_64to32,
   12035                                                       mkexpr( bcd_low_60 ) )
   12036                                                 ) ) ) );
   12037 
   12038       } else if ( s == 1 ) {
   12039          IRTemp sign          = newTemp( Ity_I32 );
   12040          IRTemp zero          = newTemp( Ity_I32 );
   12041          IRTemp pos_sign_mask = newTemp( Ity_I32 );
   12042          IRTemp neg_sign_mask = newTemp( Ity_I32 );
   12043 
   12044          /* The sign of the BCD string is stored in lower 4 bits */
   12045          assign( sign,
   12046                  binop( Iop_And32,
   12047                         unop( Iop_64to32, mkexpr( frBI64_lo ) ),
   12048                         mkU32( 0xF ) ) );
   12049          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
   12050          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
   12051          assign( sign_bit,
   12052                  Generate_sign_bit( mkexpr( pos_sign_mask ),
   12053                                     mkexpr( neg_sign_mask ) ) );
   12054 
   12055          /* Generate the value assuminig the sign and BCD digits are vaild */
   12056          assign( bcd_top_8,
   12057                  binop( Iop_32HLto64,
   12058                         mkU32( 0x0 ),
   12059                         binop( Iop_Shr32,
   12060                                unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   12061                                mkU8( 28 ) ) ) );
   12062 
   12063          /* The various helper routines ignore the upper 4-bits */
   12064          assign( bcd_mid_60, mkexpr( frBI64_hi ) );
   12065 
   12066          /* Remove bottom four sign bits */
   12067          assign( bcd_low_60,
   12068                  binop( Iop_32HLto64,
   12069                         binop( Iop_Shr32,
   12070                                unop( Iop_64HIto32,
   12071                                      mkexpr( frBI64_lo ) ),
   12072                                mkU8( 4 ) ),
   12073                                binop( Iop_Or32,
   12074                                       binop( Iop_Shl32,
   12075                                              unop( Iop_64HIto32,
   12076                                                    mkexpr( frBI64_lo ) ),
   12077                                              mkU8( 28 ) ),
   12078                                       binop( Iop_Shr32,
   12079                                              unop( Iop_64to32,
   12080                                                    mkexpr( frBI64_lo ) ),
   12081                                              mkU8( 4 ) ) ) ) );
   12082          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
   12083          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
   12084 
   12085          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
   12086          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
   12087          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
   12088 
   12089          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
   12090          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
   12091          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
   12092 
   12093          /* The entire BCD string fits in lower 110-bits.  The LMD value
   12094           * is not stored in the final result for the DFP Long instruction.
   12095           */
   12096          assign( lmd, mkU32( 0 ) );
   12097 
   12098          /* Check for invalid sign and invalid BCD digit.  Don't check the
   12099           *  bottom four bits of frBI64_lo as that is the sign value.
   12100           */
   12101          assign( zero, mkU32( 0 ) );
   12102          assign( inval_bcd_digit_mask,
   12103                  binop( Iop_Or32,
   12104                         bcd_digit_inval( mkexpr( zero ),
   12105                                          unop( Iop_64to32,
   12106                                                mkexpr( bcd_top_8 ) ) ),
   12107                         binop( Iop_Or32,
   12108                                bcd_digit_inval( unop( Iop_64HIto32,
   12109                                                      mkexpr( bcd_mid_60 ) ),
   12110                                                unop( Iop_64to32,
   12111                                                      mkexpr( bcd_mid_60 ) ) ),
   12112                                bcd_digit_inval( unop( Iop_64HIto32,
   12113                                                      mkexpr( frBI64_lo ) ),
   12114                                                binop( Iop_Shr32,
   12115                                                       unop( Iop_64to32,
   12116                                                             mkexpr( frBI64_lo ) ),
   12117                                                         mkU8( 4 ) ) ) ) ) );
   12118          assign( invalid_mask,
   12119                  Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
   12120                                     mkexpr( pos_sign_mask ),
   12121                                     mkexpr( neg_sign_mask ) ) );
   12122 
   12123       }
   12124 
   12125       assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   12126 
   12127       /* Calculate the value of the result assuming sign and BCD digits
   12128        * are all valid.
   12129        */
   12130       assign( dfp_significand,
   12131               binop( Iop_D64HLtoD128,
   12132                      unop( Iop_ReinterpI64asD64,
   12133                            binop( Iop_32HLto64,
   12134                                   binop( Iop_Or32,
   12135                                          mkexpr( sign_bit ),
   12136                                          mkexpr( dbcd_top_l ) ),
   12137                                   binop( Iop_Or32,
   12138                                          binop( Iop_Shl32,
   12139                                                 mkexpr( dbcd_mid_u ),
   12140                                                 mkU8( 18 ) ),
   12141                                          binop( Iop_Shr32,
   12142                                                 mkexpr( dbcd_mid_l ),
   12143                                                 mkU8( 14 ) ) ) ) ),
   12144                      unop( Iop_ReinterpI64asD64,
   12145                            binop( Iop_32HLto64,
   12146                                   binop( Iop_Or32,
   12147                                          mkexpr( dbcd_low_u ),
   12148                                          binop( Iop_Shl32,
   12149                                                 mkexpr( dbcd_mid_l ),
   12150                                                 mkU8( 18 ) ) ),
   12151                                   mkexpr( dbcd_low_l ) ) ) ) );
   12152 
   12153       /* Break the result back down to 32-bit chunks and replace chunks.
   12154        * If there was an invalid BCD digit or invalid sign value, replace
   12155        * the calculated result with the invalid bit string.
   12156        */
   12157       assign( result128,
   12158               binop( Iop_InsertExpD128,
   12159                      mkU64( DFP_EXTND_BIAS ),
   12160                      mkexpr( dfp_significand ) ) );
   12161 
   12162       assign( tmp_hi,
   12163               unop( Iop_ReinterpD64asI64,
   12164                     unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
   12165 
   12166       assign( tmp_lo,
   12167               unop( Iop_ReinterpD64asI64,
   12168                     unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
   12169 
   12170       assign( result_hi,
   12171               binop( Iop_32HLto64,
   12172                      binop( Iop_Or32,
   12173                             binop( Iop_And32,
   12174                                    mkexpr( valid_mask ),
   12175                                    unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
   12176                             binop( Iop_And32,
   12177                                    mkU32( 0x7C000000 ),
   12178                                    mkexpr( invalid_mask ) ) ),
   12179                      binop( Iop_Or32,
   12180                             binop( Iop_And32,
   12181                                    mkexpr( valid_mask ),
   12182                                    unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
   12183                             binop( Iop_And32,
   12184                                    mkU32( 0x0 ),
   12185                                    mkexpr( invalid_mask ) ) ) ) );
   12186 
   12187       assign( result_lo,
   12188               binop( Iop_32HLto64,
   12189                      binop( Iop_Or32,
   12190                             binop( Iop_And32,
   12191                                    mkexpr( valid_mask ),
   12192                                    unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
   12193                             binop( Iop_And32,
   12194                                    mkU32( 0x0 ),
   12195                                    mkexpr( invalid_mask ) ) ),
   12196                      binop( Iop_Or32,
   12197                             binop( Iop_And32,
   12198                                    mkexpr( valid_mask ),
   12199                                    unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
   12200                             binop( Iop_And32,
   12201                                    mkU32( 0x0 ),
   12202                                    mkexpr( invalid_mask ) ) ) ) );
   12203 
   12204       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
   12205       putDReg( frT_addr + 1,
   12206                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
   12207 
   12208    }
   12209    break;
   12210    default:
   12211       vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
   12212       break;
   12213    }
   12214    return True;
   12215 }
   12216 
   12217 static Bool dis_dfp_significant_digits( UInt theInstr )
   12218 {
   12219    UChar frA_addr = ifieldRegA( theInstr );
   12220    UChar frB_addr = ifieldRegB( theInstr );
   12221    IRTemp frA     = newTemp( Ity_D64 );
   12222    UInt opc1      = ifieldOPC( theInstr );
   12223    IRTemp B_sig   = newTemp( Ity_I8 );
   12224    IRTemp K       = newTemp( Ity_I8 );
   12225    IRTemp lmd_B   = newTemp( Ity_I32 );
   12226    IRTemp field   = newTemp( Ity_I32 );
   12227    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
   12228    IRTemp Unordered_true     = newTemp( Ity_I32 );
   12229    IRTemp Eq_true_mask       = newTemp( Ity_I32 );
   12230    IRTemp Lt_true_mask       = newTemp( Ity_I32 );
   12231    IRTemp Gt_true_mask       = newTemp( Ity_I32 );
   12232    IRTemp KisZero_true_mask  = newTemp( Ity_I32 );
   12233    IRTemp KisZero_false_mask = newTemp( Ity_I32 );
   12234 
   12235    /* Get the reference singificance stored in frA */
   12236    assign( frA, getDReg( frA_addr ) );
   12237 
   12238    /* Convert from 64 bit to 8 bits in two steps.  The Iop_64to8 is not
   12239     * supported in 32-bit mode.
   12240     */
   12241    assign( K, unop( Iop_32to8,
   12242                     binop( Iop_And32,
   12243                            unop( Iop_64to32,
   12244                                  unop( Iop_ReinterpD64asI64,
   12245                                        mkexpr( frA ) ) ),
   12246                            mkU32( 0x3F ) ) ) );
   12247 
   12248    switch ( opc1 ) {
   12249    case 0x3b: // dtstsf   DFP Test Significance
   12250    {
   12251       IRTemp frB     = newTemp( Ity_D64 );
   12252       IRTemp frBI64  = newTemp( Ity_I64 );
   12253       IRTemp B_bcd_u = newTemp( Ity_I32 );
   12254       IRTemp B_bcd_l = newTemp( Ity_I32 );
   12255       IRTemp tmp64   = newTemp( Ity_I64 );
   12256 
   12257       DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
   12258 
   12259       assign( frB, getDReg( frB_addr ) );
   12260       assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
   12261 
   12262       /* Get the BCD string for the value stored in a series of I32 values.
   12263        * Count the number of leading zeros.  Subtract the number of leading
   12264        * zeros from 16 (maximum number of significant digits in DFP
   12265        * Long).
   12266        */
   12267       Get_lmd( &lmd_B,
   12268                binop( Iop_Shr32,
   12269                       unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   12270                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
   12271 
   12272       assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
   12273       assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
   12274       assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
   12275 
   12276       assign( B_sig,
   12277               binop( Iop_Sub8,
   12278                      mkU8( DFP_LONG_MAX_SIG_DIGITS ),
   12279                      Count_leading_zeros_60( mkexpr( lmd_B ),
   12280                                              mkexpr( B_bcd_u ),
   12281                                              mkexpr( B_bcd_l ) ) ) );
   12282       assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) );
   12283    }
   12284    break;
   12285    case 0x3F: // dtstsfq     DFP Test Significance
   12286    {
   12287       IRTemp frB_hi     = newTemp( Ity_D64 );
   12288       IRTemp frB_lo     = newTemp( Ity_D64 );
   12289       IRTemp frBI64_hi  = newTemp( Ity_I64 );
   12290       IRTemp frBI64_lo  = newTemp( Ity_I64 );
   12291       IRTemp B_low_60_u = newTemp( Ity_I32 );
   12292       IRTemp B_low_60_l = newTemp( Ity_I32 );
   12293       IRTemp B_mid_60_u = newTemp( Ity_I32 );
   12294       IRTemp B_mid_60_l = newTemp( Ity_I32 );
   12295       IRTemp B_top_12_l = newTemp( Ity_I32 );
   12296 
   12297       DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
   12298 
   12299       assign( frB_hi, getDReg( frB_addr ) );
   12300       assign( frB_lo, getDReg( frB_addr + 1 ) );
   12301 
   12302       assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
   12303       assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
   12304 
   12305       /* Get the BCD string for the value stored in a series of I32 values.
   12306        * Count the number of leading zeros.  Subtract the number of leading
   12307        * zeros from 32 (maximum number of significant digits in DFP
   12308        * extended).
   12309        */
   12310       Get_lmd( &lmd_B,
   12311                binop( Iop_Shr32,
   12312                       unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   12313                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
   12314 
   12315       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
   12316                                    mkexpr( frBI64_lo ),
   12317                                    &B_top_12_l,
   12318                                    &B_mid_60_u,
   12319                                    &B_mid_60_l,
   12320                                    &B_low_60_u,
   12321                                    &B_low_60_l );
   12322 
   12323       assign( B_sig,
   12324               binop( Iop_Sub8,
   12325                      mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
   12326                      Count_leading_zeros_128( mkexpr( lmd_B ),
   12327                                               mkexpr( B_top_12_l ),
   12328                                               mkexpr( B_mid_60_u ),
   12329                                               mkexpr( B_mid_60_l ),
   12330                                               mkexpr( B_low_60_u ),
   12331                                               mkexpr( B_low_60_l ) ) ) );
   12332 
   12333       assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) );
   12334    }
   12335    break;
   12336    }
   12337 
   12338    /* Compare (16 - cnt[0]) against K and set the condition code field
   12339     * accordingly.
   12340     *
   12341     * The field layout is as follows:
   12342     *
   12343     * bit[3:0]    Description
   12344     *    3     K != 0 and K < Number of significant digits if FRB
   12345     *    2     K != 0 and K > Number of significant digits if FRB OR K = 0
   12346     *    1     K != 0 and K = Number of significant digits if FRB
   12347     *    0     K ? Number of significant digits if FRB
   12348     */
   12349    assign( Eq_true_mask,
   12350            unop( Iop_1Sto32,
   12351                  binop( Iop_CmpEQ32,
   12352                         unop( Iop_8Uto32, mkexpr( K ) ),
   12353                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
   12354    assign( Lt_true_mask,
   12355            unop( Iop_1Sto32,
   12356                  binop( Iop_CmpLT32U,
   12357                         unop( Iop_8Uto32, mkexpr( K ) ),
   12358                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
   12359    assign( Gt_true_mask,
   12360            unop( Iop_1Sto32,
   12361                  binop( Iop_CmpLT32U,
   12362                         unop( Iop_8Uto32, mkexpr( B_sig ) ),
   12363                         unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
   12364 
   12365    assign( KisZero_true_mask,
   12366            unop( Iop_1Sto32,
   12367                  binop( Iop_CmpEQ32,
   12368                         unop( Iop_8Uto32, mkexpr( K ) ),
   12369                         mkU32( 0 ) ) ) );
   12370    assign( KisZero_false_mask,
   12371            unop( Iop_1Sto32,
   12372                  binop( Iop_CmpNE32,
   12373                         unop( Iop_8Uto32, mkexpr( K ) ),
   12374                         mkU32( 0 ) ) ) );
   12375 
   12376    assign( field,
   12377            binop( Iop_Or32,
   12378                   binop( Iop_And32,
   12379                          mkexpr( KisZero_false_mask ),
   12380                          binop( Iop_Or32,
   12381                                 binop( Iop_And32,
   12382                                        mkexpr( Lt_true_mask ),
   12383                                        mkU32( 0x8 ) ),
   12384                                 binop( Iop_Or32,
   12385                                        binop( Iop_And32,
   12386                                               mkexpr( Gt_true_mask ),
   12387                                               mkU32( 0x4 ) ),
   12388                                        binop( Iop_And32,
   12389                                               mkexpr( Eq_true_mask ),
   12390                                               mkU32( 0x2 ) ) ) ) ),
   12391                   binop( Iop_And32,
   12392                          mkexpr( KisZero_true_mask ),
   12393                          mkU32( 0x4 ) ) ) );
   12394 
   12395    putGST_field( PPC_GST_CR,
   12396                  binop( Iop_Or32,
   12397                         binop( Iop_And32,
   12398                                mkexpr( Unordered_true ),
   12399                                mkU32( 0x1 ) ),
   12400                         binop( Iop_And32,
   12401                                unop( Iop_Not32, mkexpr( Unordered_true ) ),
   12402                                mkexpr( field ) ) ),
   12403                  crfD );
   12404 
   12405    return True;
   12406 }
   12407 
   12408 /*------------------------------------------------------------*/
   12409 /*--- AltiVec Instruction Translation                      ---*/
   12410 /*------------------------------------------------------------*/
   12411 
   12412 /*
   12413   Altivec Cache Control Instructions (Data Streams)
   12414 */
   12415 static Bool dis_av_datastream ( UInt theInstr )
   12416 {
   12417    /* X-Form */
   12418    UChar opc1     = ifieldOPC(theInstr);
   12419    UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
   12420    UChar flag_A   = flag_T;
   12421    UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
   12422    UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
   12423    UChar rA_addr  = ifieldRegA(theInstr);
   12424    UChar rB_addr  = ifieldRegB(theInstr);
   12425    UInt  opc2     = ifieldOPClo10(theInstr);
   12426    UChar b0       = ifieldBIT0(theInstr);
   12427 
   12428    if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
   12429       vex_printf("dis_av_datastream(ppc)(instr)\n");
   12430       return False;
   12431    }
   12432 
   12433    switch (opc2) {
   12434    case 0x156: // dst (Data Stream Touch, AV p115)
   12435       DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   12436                                 rA_addr, rB_addr, STRM);
   12437       break;
   12438 
   12439    case 0x176: // dstst (Data Stream Touch for Store, AV p117)
   12440       DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   12441                                   rA_addr, rB_addr, STRM);
   12442       break;
   12443 
   12444    case 0x336: // dss (Data Stream Stop, AV p114)
   12445       if (rA_addr != 0 || rB_addr != 0) {
   12446          vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
   12447          return False;
   12448       }
   12449       if (flag_A == 0) {
   12450          DIP("dss %d\n", STRM);
   12451       } else {
   12452          DIP("dssall\n");
   12453       }
   12454       break;
   12455 
   12456    default:
   12457       vex_printf("dis_av_datastream(ppc)(opc2)\n");
   12458       return False;
   12459    }
   12460    return True;
   12461 }
   12462 
   12463 /*
   12464   AltiVec Processor Control Instructions
   12465 */
   12466 static Bool dis_av_procctl ( UInt theInstr )
   12467 {
   12468    /* VX-Form */
   12469    UChar opc1    = ifieldOPC(theInstr);
   12470    UChar vD_addr = ifieldRegDS(theInstr);
   12471    UChar vA_addr = ifieldRegA(theInstr);
   12472    UChar vB_addr = ifieldRegB(theInstr);
   12473    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   12474 
   12475    if (opc1 != 0x4) {
   12476       vex_printf("dis_av_procctl(ppc)(instr)\n");
   12477       return False;
   12478    }
   12479 
   12480    switch (opc2) {
   12481    case 0x604: // mfvscr (Move from VSCR, AV p129)
   12482       if (vA_addr != 0 || vB_addr != 0) {
   12483          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   12484          return False;
   12485       }
   12486       DIP("mfvscr v%d\n", vD_addr);
   12487       putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
   12488       break;
   12489 
   12490    case 0x644: { // mtvscr (Move to VSCR, AV p130)
   12491       IRTemp vB = newTemp(Ity_V128);
   12492       if (vD_addr != 0 || vA_addr != 0) {
   12493          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   12494          return False;
   12495       }
   12496       DIP("mtvscr v%d\n", vB_addr);
   12497       assign( vB, getVReg(vB_addr));
   12498       putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
   12499       break;
   12500    }
   12501    default:
   12502       vex_printf("dis_av_procctl(ppc)(opc2)\n");
   12503       return False;
   12504    }
   12505    return True;
   12506 }
   12507 
   12508 /*
   12509  * VSX scalar and vector convert instructions
   12510  */
   12511 static Bool
   12512 dis_vx_conv ( UInt theInstr, UInt opc2 )
   12513 {
   12514    /* XX2-Form */
   12515    UChar opc1 = ifieldOPC( theInstr );
   12516    UChar XT = ifieldRegXT( theInstr );
   12517    UChar XB = ifieldRegXB( theInstr );
   12518    IRTemp xB, xB2;
   12519    IRTemp b3, b2, b1, b0;
   12520    xB = xB2 = IRTemp_INVALID;
   12521 
   12522    if (opc1 != 0x3C) {
   12523       vex_printf( "dis_vx_conv(ppc)(instr)\n" );
   12524       return False;
   12525    }
   12526 
   12527    /* Create and assign temps only as needed for the given instruction. */
   12528    switch (opc2) {
   12529       // scalar double-precision floating point argument
   12530       case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
   12531          xB = newTemp(Ity_F64);
   12532          assign( xB,
   12533                  unop( Iop_ReinterpI64asF64,
   12534                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   12535          break;
   12536       // vector double-precision floating point arguments
   12537       case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
   12538 
   12539          xB = newTemp(Ity_F64);
   12540          xB2 = newTemp(Ity_F64);
   12541          assign( xB,
   12542                  unop( Iop_ReinterpI64asF64,
   12543                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   12544          assign( xB2,
   12545                  unop( Iop_ReinterpI64asF64,
   12546                        unop( Iop_V128to64, getVSReg( XB ) ) ) );
   12547          break;
   12548       // vector single precision or [un]signed integer word arguments
   12549       case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
   12550       case 0x1f0: case 0x1d0:
   12551          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   12552          breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
   12553          break;
   12554          // vector [un]signed integer doubleword argument
   12555       case 0x3f0: case 0x370: case 0x3d0: case 0x350:
   12556          xB = newTemp(Ity_I64);
   12557          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   12558          xB2 = newTemp(Ity_I64);
   12559          assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
   12560          break;
   12561       // scalar [un]signed integer doubleword argument
   12562       case 0x250: case 0x270: case 0x2D0: case 0x2F0:
   12563          xB = newTemp(Ity_I64);
   12564          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   12565          break;
   12566       // scalar single precision argument
   12567       case 0x292: // xscvspdp
   12568          xB  = newTemp(Ity_I32);
   12569 
   12570          assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
   12571                                                   unop( Iop_V128HIto64,
   12572                                                         getVSReg( XB ) ) ) ) );
   12573          break;
   12574       case 0x296: // xscvspdpn (non signaling version of xscvpdp)
   12575          xB = newTemp(Ity_I32);
   12576          assign( xB,
   12577                  unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   12578          break;
   12579 
   12580       /* Certain instructions have their complete implementation in the main switch statement
   12581        * that follows this one; thus we have a "do nothing" case for those instructions here.
   12582        */
   12583       case 0x170: case 0x150:
   12584          break; // do nothing
   12585 
   12586       default:
   12587          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   12588          return False;
   12589    }
   12590 
   12591 
   12592    switch (opc2) {
   12593       case 0x2B0:
   12594          // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
   12595          //             to Signed Integer Doubleword format with Saturate)
   12596          DIP("xscvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12597          putVSReg( XT,
   12598                    binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
   12599                                                  mkU32( Irrm_ZERO ),
   12600                                                  mkexpr( xB ) ), mkU64( 0 ) ) );
   12601          break;
   12602       case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
   12603                   //             Convert to Signed Integer Word format with Saturate)
   12604          DIP("xscvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12605          putVSReg( XT,
   12606                    binop( Iop_64HLtoV128,
   12607                           unop( Iop_32Sto64,
   12608                                 binop( Iop_F64toI32S,
   12609                                        mkU32( Irrm_ZERO ),
   12610                                        mkexpr( xB ) ) ),
   12611                                        mkU64( 0ULL ) ) );
   12612          break;
   12613       case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
   12614                   //             to Unsigned Integer Doubleword format with Saturate)
   12615          DIP("xscvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12616          putVSReg( XT,
   12617                    binop( Iop_64HLtoV128,
   12618                           binop( Iop_F64toI64U,
   12619                                  mkU32( Irrm_ZERO ),
   12620                                  mkexpr( xB ) ),
   12621                                  mkU64( 0ULL ) ) );
   12622          break;
   12623       case 0x270:
   12624          // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
   12625          //             to Single-Precision format)
   12626          DIP("xscvsxdsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12627          putVSReg( XT,
   12628                    binop( Iop_64HLtoV128,
   12629                           unop( Iop_ReinterpF64asI64,
   12630                                 binop( Iop_RoundF64toF32,
   12631                                        get_IR_roundingmode(),
   12632                                        binop( Iop_I64StoF64,
   12633                                               get_IR_roundingmode(),
   12634                                               mkexpr( xB ) ) ) ),
   12635                           mkU64( 0 ) ) );
   12636          break;
   12637       case 0x2F0:
   12638          // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
   12639          //            Double-Precision format)
   12640          DIP("xscvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12641          putVSReg( XT,
   12642                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   12643                                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   12644                                                        mkexpr( xB ) ) ),
   12645                                                        mkU64( 0 ) ) );
   12646          break;
   12647       case 0x250:
   12648          // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
   12649          //            Doubleword to Singel-Precision format)
   12650          DIP("xscvuxdsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12651          putVSReg( XT,
   12652                    binop( Iop_64HLtoV128,
   12653                           unop( Iop_ReinterpF64asI64,
   12654                                 binop( Iop_RoundF64toF32,
   12655                                        get_IR_roundingmode(),
   12656                                        binop( Iop_I64UtoF64,
   12657                                               get_IR_roundingmode(),
   12658                                               mkexpr( xB ) ) ) ),
   12659                           mkU64( 0 ) ) );
   12660          break;
   12661       case 0x2D0:
   12662          // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
   12663          //            Double-Precision format)
   12664          DIP("xscvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12665          putVSReg( XT,
   12666                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   12667                                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   12668                                                        mkexpr( xB ) ) ),
   12669                                                        mkU64( 0 ) ) );
   12670          break;
   12671       case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
   12672                   //             to Signed Integer Word format with Saturate)
   12673       {
   12674          IRTemp hiResult_32 = newTemp(Ity_I32);
   12675          IRTemp loResult_32 = newTemp(Ity_I32);
   12676          IRExpr* rmZero = mkU32(Irrm_ZERO);
   12677 
   12678          DIP("xvcvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12679          assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
   12680          assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
   12681          putVSReg( XT,
   12682                    binop( Iop_64HLtoV128,
   12683                           unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
   12684                           unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
   12685          break;
   12686       }
   12687       case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
   12688          //  (VSX Vector truncate Single-Precision to integer and
   12689          //   Convert to [Un]signed Integer Word format with Saturate)
   12690       {
   12691          IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
   12692          IRTemp tempResult = newTemp(Ity_V128);
   12693          IRTemp res0 = newTemp(Ity_I32);
   12694          IRTemp res1 = newTemp(Ity_I32);
   12695          IRTemp res2 = newTemp(Ity_I32);
   12696          IRTemp res3 = newTemp(Ity_I32);
   12697          IRTemp hi64 = newTemp(Ity_I64);
   12698          IRTemp lo64 = newTemp(Ity_I64);
   12699          Bool un_signed = (opc2 == 0x110);
   12700          IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
   12701 
   12702          DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB);
   12703          /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
   12704           * then result is set to 0x80000000.  */
   12705          assign(tempResult, unop(op, getVSReg(XB)));
   12706          assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
   12707          assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
   12708          assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
   12709          assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
   12710          assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
   12711          assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
   12712 
   12713          b3_result = IRExpr_ITE(is_NaN_32(b3),
   12714                                 // then: result is 0x{8|0}80000000
   12715                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12716                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12717                                 mkexpr(res3));
   12718          b2_result = IRExpr_ITE(is_NaN_32(b2),
   12719                                 // then: result is 0x{8|0}80000000
   12720                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12721                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12722                                 mkexpr(res2));
   12723          b1_result = IRExpr_ITE(is_NaN_32(b1),
   12724                                 // then: result is 0x{8|0}80000000
   12725                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12726                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12727                                 mkexpr(res1));
   12728          b0_result = IRExpr_ITE(is_NaN_32(b0),
   12729                                 // then: result is 0x{8|0}80000000
   12730                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12731                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12732                                 mkexpr(res0));
   12733 
   12734          putVSReg( XT,
   12735                    binop( Iop_64HLtoV128,
   12736                           binop( Iop_32HLto64, b3_result, b2_result ),
   12737                           binop( Iop_32HLto64, b1_result, b0_result ) ) );
   12738          break;
   12739       }
   12740       case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
   12741                   //           Convert to Single-Precision format
   12742          DIP("xscvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12743          putVSReg( XT,
   12744                    binop( Iop_64HLtoV128,
   12745                           binop( Iop_32HLto64,
   12746                                  unop( Iop_ReinterpF32asI32,
   12747                                        unop( Iop_TruncF64asF32,
   12748                                              binop( Iop_RoundF64toF32,
   12749                                                     get_IR_roundingmode(),
   12750                                                     mkexpr( xB ) ) ) ),
   12751                                  mkU32( 0 ) ),
   12752                           mkU64( 0ULL ) ) );
   12753          break;
   12754       case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
   12755                               vector Single-Precision non-signalling */
   12756          DIP("xscvdpspn v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12757          putVSReg( XT,
   12758                    binop( Iop_64HLtoV128,
   12759                           binop( Iop_32HLto64,
   12760                                  unop( Iop_ReinterpF32asI32,
   12761                                        unop( Iop_TruncF64asF32,
   12762                                              mkexpr( xB ) ) ),
   12763                                  mkU32( 0 ) ),
   12764                           mkU64( 0ULL ) ) );
   12765          break;
   12766       case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
   12767                   //             and Convert to Unsigned Integer Word format with Saturate)
   12768          DIP("xscvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12769          putVSReg( XT,
   12770                    binop( Iop_64HLtoV128,
   12771                           binop( Iop_32HLto64,
   12772                                  mkU32( 0 ),
   12773                                  binop( Iop_F64toI32U,
   12774                                         mkU32( Irrm_ZERO ),
   12775                                         mkexpr( xB ) ) ),
   12776                           mkU64( 0ULL ) ) );
   12777          break;
   12778       case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
   12779          DIP("xscvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12780          putVSReg( XT,
   12781                    binop( Iop_64HLtoV128,
   12782                           unop( Iop_ReinterpF64asI64,
   12783                                 unop( Iop_F32toF64,
   12784                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
   12785                           mkU64( 0ULL ) ) );
   12786          break;
   12787       case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
   12788          DIP("xscvspdpn v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12789          putVSReg( XT,
   12790                    binop( Iop_64HLtoV128,
   12791                           unop( Iop_ReinterpF64asI64,
   12792                                 unop( Iop_F32toF64,
   12793                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
   12794                                       mkU64( 0ULL ) ) );
   12795          break;
   12796       case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
   12797                   //           and Convert to Single-Precision format)
   12798          DIP("xvcvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12799          putVSReg( XT,
   12800                    binop( Iop_64HLtoV128,
   12801                           binop( Iop_32HLto64,
   12802                                  unop( Iop_ReinterpF32asI32,
   12803                                        unop( Iop_TruncF64asF32,
   12804                                              binop( Iop_RoundF64toF32,
   12805                                                     get_IR_roundingmode(),
   12806                                                     mkexpr( xB ) ) ) ),
   12807                                  mkU32( 0 ) ),
   12808                           binop( Iop_32HLto64,
   12809                                  unop( Iop_ReinterpF32asI32,
   12810                                        unop( Iop_TruncF64asF32,
   12811                                              binop( Iop_RoundF64toF32,
   12812                                                     get_IR_roundingmode(),
   12813                                                     mkexpr( xB2 ) ) ) ),
   12814                                  mkU32( 0 ) ) ) );
   12815          break;
   12816       case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
   12817                   //             and Convert to Unsigned Integer Doubleword format
   12818                   //             with Saturate)
   12819          DIP("xvcvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12820          putVSReg( XT,
   12821                    binop( Iop_64HLtoV128,
   12822                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   12823                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   12824          break;
   12825       case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
   12826                   //             Convert to Unsigned Integer Word format with Saturate)
   12827          DIP("xvcvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12828          putVSReg( XT,
   12829                    binop( Iop_64HLtoV128,
   12830                           binop( Iop_32HLto64,
   12831                                  binop( Iop_F64toI32U,
   12832                                         mkU32( Irrm_ZERO ),
   12833                                         mkexpr( xB ) ),
   12834                                  mkU32( 0 ) ),
   12835                           binop( Iop_32HLto64,
   12836                                  binop( Iop_F64toI32U,
   12837                                         mkU32( Irrm_ZERO ),
   12838                                         mkexpr( xB2 ) ),
   12839                                  mkU32( 0 ) ) ) );
   12840          break;
   12841       case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
   12842          DIP("xvcvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12843          putVSReg( XT,
   12844                    binop( Iop_64HLtoV128,
   12845                           unop( Iop_ReinterpF64asI64,
   12846                                 unop( Iop_F32toF64,
   12847                                       unop( Iop_ReinterpI32asF32,
   12848                                             handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
   12849                           unop( Iop_ReinterpF64asI64,
   12850                                 unop( Iop_F32toF64,
   12851                                       unop( Iop_ReinterpI32asF32,
   12852                                             handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
   12853          break;
   12854       case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
   12855                   //           Convert to Signed Integer Doubleword format with Saturate)
   12856          DIP("xvcvspsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12857          putVSReg( XT,
   12858                    binop( Iop_64HLtoV128,
   12859                           binop( Iop_F64toI64S,
   12860                                  mkU32( Irrm_ZERO ),
   12861                                  unop( Iop_F32toF64,
   12862                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   12863                           binop( Iop_F64toI64S,
   12864                                  mkU32( Irrm_ZERO ),
   12865                                  unop( Iop_F32toF64,
   12866                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   12867          break;
   12868       case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
   12869                   //            Convert to Unsigned Integer Doubleword format with Saturate)
   12870          DIP("xvcvspuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12871          putVSReg( XT,
   12872                    binop( Iop_64HLtoV128,
   12873                           binop( Iop_F64toI64U,
   12874                                  mkU32( Irrm_ZERO ),
   12875                                  unop( Iop_F32toF64,
   12876                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   12877                           binop( Iop_F64toI64U,
   12878                                  mkU32( Irrm_ZERO ),
   12879                                  unop( Iop_F32toF64,
   12880                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   12881          break;
   12882       case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
   12883                   //             Convert to Signed Integer Doubleword format with Saturate)
   12884          DIP("xvcvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12885          putVSReg( XT,
   12886                    binop( Iop_64HLtoV128,
   12887                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   12888                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   12889          break;
   12890       case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
   12891                   //            to Double-Precision format)
   12892          DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12893          putVSReg( XT,
   12894                    binop( Iop_64HLtoV128,
   12895                           unop( Iop_ReinterpF64asI64,
   12896                                 binop( Iop_I64StoF64,
   12897                                        get_IR_roundingmode(),
   12898                                        mkexpr( xB ) ) ),
   12899                           unop( Iop_ReinterpF64asI64,
   12900                                 binop( Iop_I64StoF64,
   12901                                        get_IR_roundingmode(),
   12902                                        mkexpr( xB2 ) ) ) ) );
   12903          break;
   12904       case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
   12905                   //            to Double-Precision format)
   12906          DIP("xvcvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12907          putVSReg( XT,
   12908                    binop( Iop_64HLtoV128,
   12909                           unop( Iop_ReinterpF64asI64,
   12910                                 binop( Iop_I64UtoF64,
   12911                                        get_IR_roundingmode(),
   12912                                        mkexpr( xB ) ) ),
   12913                           unop( Iop_ReinterpF64asI64,
   12914                                 binop( Iop_I64UtoF64,
   12915                                        get_IR_roundingmode(),
   12916                                        mkexpr( xB2 ) ) ) ) );
   12917 
   12918          break;
   12919       case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
   12920                   //            to Single-Precision format)
   12921          DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12922          putVSReg( XT,
   12923                    binop( Iop_64HLtoV128,
   12924                           binop( Iop_32HLto64,
   12925                                  unop( Iop_ReinterpF32asI32,
   12926                                        unop( Iop_TruncF64asF32,
   12927                                              binop( Iop_RoundF64toF32,
   12928                                                     get_IR_roundingmode(),
   12929                                                     binop( Iop_I64StoF64,
   12930                                                            get_IR_roundingmode(),
   12931                                                            mkexpr( xB ) ) ) ) ),
   12932                                  mkU32( 0 ) ),
   12933                           binop( Iop_32HLto64,
   12934                                  unop( Iop_ReinterpF32asI32,
   12935                                        unop( Iop_TruncF64asF32,
   12936                                              binop( Iop_RoundF64toF32,
   12937                                                     get_IR_roundingmode(),
   12938                                                     binop( Iop_I64StoF64,
   12939                                                            get_IR_roundingmode(),
   12940                                                            mkexpr( xB2 ) ) ) ) ),
   12941                                  mkU32( 0 ) ) ) );
   12942          break;
   12943       case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
   12944                   //            to Single-Precision format)
   12945          DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
   12946          putVSReg( XT,
   12947                    binop( Iop_64HLtoV128,
   12948                           binop( Iop_32HLto64,
   12949                                  unop( Iop_ReinterpF32asI32,
   12950                                        unop( Iop_TruncF64asF32,
   12951                                              binop( Iop_RoundF64toF32,
   12952                                                     get_IR_roundingmode(),
   12953                                                     binop( Iop_I64UtoF64,
   12954                                                            get_IR_roundingmode(),
   12955                                                            mkexpr( xB ) ) ) ) ),
   12956                                  mkU32( 0 ) ),
   12957                           binop( Iop_32HLto64,
   12958                                  unop( Iop_ReinterpF32asI32,
   12959                                        unop( Iop_TruncF64asF32,
   12960                                              binop( Iop_RoundF64toF32,
   12961                                                     get_IR_roundingmode(),
   12962                                                     binop( Iop_I64UtoF64,
   12963                                                            get_IR_roundingmode(),
   12964                                                            mkexpr( xB2 ) ) ) ) ),
   12965                                  mkU32( 0 ) ) ) );
   12966          break;
   12967 
   12968       case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
   12969          DIP("xvcvsxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12970          putVSReg( XT,
   12971                    binop( Iop_64HLtoV128,
   12972                           unop( Iop_ReinterpF64asI64,
   12973                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   12974                                        unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
   12975                           unop( Iop_ReinterpF64asI64,
   12976                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   12977                                        unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
   12978          break;
   12979       case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
   12980          DIP("xvcvuxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12981          putVSReg( XT,
   12982                    binop( Iop_64HLtoV128,
   12983                           unop( Iop_ReinterpF64asI64,
   12984                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   12985                                        unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
   12986                           unop( Iop_ReinterpF64asI64,
   12987                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   12988                                        unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
   12989          break;
   12990       case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
   12991          DIP("xvcvsxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12992          putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
   12993          break;
   12994       case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
   12995          DIP("xvcvuxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12996          putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
   12997          break;
   12998 
   12999       default:
   13000          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   13001          return False;
   13002    }
   13003    return True;
   13004 }
   13005 
   13006 /*
   13007  * VSX vector Double Precision Floating Point Arithmetic Instructions
   13008  */
   13009 static Bool
   13010 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
   13011 {
   13012    /* XX3-Form */
   13013    UChar opc1 = ifieldOPC( theInstr );
   13014    UChar XT = ifieldRegXT( theInstr );
   13015    UChar XA = ifieldRegXA( theInstr );
   13016    UChar XB = ifieldRegXB( theInstr );
   13017    IRExpr* rm = get_IR_roundingmode();
   13018    IRTemp frA = newTemp(Ity_F64);
   13019    IRTemp frB = newTemp(Ity_F64);
   13020    IRTemp frA2 = newTemp(Ity_F64);
   13021    IRTemp frB2 = newTemp(Ity_F64);
   13022 
   13023    if (opc1 != 0x3C) {
   13024       vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
   13025       return False;
   13026    }
   13027 
   13028    assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   13029    assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   13030    assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
   13031    assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
   13032 
   13033    switch (opc2) {
   13034       case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
   13035       case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
   13036       case 0x180: // xvadddp (VSX Vector Add Double-Precision)
   13037       case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
   13038       {
   13039          IROp mOp;
   13040          const HChar * oper_name;
   13041          switch (opc2) {
   13042             case 0x1E0:
   13043                mOp = Iop_DivF64;
   13044                oper_name = "div";
   13045                break;
   13046             case 0x1C0:
   13047                mOp = Iop_MulF64;
   13048                oper_name = "mul";
   13049                break;
   13050             case 0x180:
   13051                mOp = Iop_AddF64;
   13052                oper_name = "add";
   13053                break;
   13054             case 0x1A0:
   13055                mOp = Iop_SubF64;
   13056                oper_name = "sub";
   13057                break;
   13058 
   13059             default:
   13060                vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
   13061          }
   13062          IRTemp hiResult = newTemp(Ity_I64);
   13063          IRTemp loResult = newTemp(Ity_I64);
   13064          DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB);
   13065 
   13066          assign( hiResult,
   13067                  unop( Iop_ReinterpF64asI64,
   13068                        triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
   13069          assign( loResult,
   13070                  unop( Iop_ReinterpF64asI64,
   13071                        triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
   13072          putVSReg( XT,
   13073                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   13074          break;
   13075       }
   13076       case 0x196: // xvsqrtdp
   13077       {
   13078          IRTemp hiResult = newTemp(Ity_I64);
   13079          IRTemp loResult = newTemp(Ity_I64);
   13080          DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   13081 
   13082          assign( hiResult,
   13083                  unop( Iop_ReinterpF64asI64,
   13084                        binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
   13085          assign( loResult,
   13086                  unop( Iop_ReinterpF64asI64,
   13087                        binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
   13088          putVSReg( XT,
   13089                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   13090          break;
   13091       }
   13092       case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
   13093       case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
   13094       case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
   13095       case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
   13096       {
   13097          /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
   13098           *    XT == FRC
   13099           *    XA == FRA
   13100           *    XB == FRB
   13101           *
   13102           * and for xvm{add|sub}adp . . .
   13103           *    XT == FRB
   13104           *    XA == FRA
   13105           *    XB == FRC
   13106           */
   13107          Bool negate;
   13108          IROp mOp = Iop_INVALID;
   13109          const HChar * oper_name = NULL;
   13110          Bool mdp = False;
   13111 
   13112          switch (opc2) {
   13113             case 0x184: case 0x1A4:
   13114             case 0x384: case 0x3A4:
   13115                mOp = Iop_MAddF64;
   13116                oper_name = "add";
   13117                mdp = (opc2 & 0x0FF) == 0x0A4;
   13118                break;
   13119 
   13120             case 0x1C4: case 0x1E4:
   13121             case 0x3C4: case 0x3E4:
   13122                mOp = Iop_MSubF64;
   13123                oper_name = "sub";
   13124                mdp = (opc2 & 0x0FF) == 0x0E4;
   13125                break;
   13126 
   13127             default:
   13128                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   13129          }
   13130 
   13131          switch (opc2) {
   13132             case 0x384: case 0x3A4:
   13133             case 0x3C4: case 0x3E4:
   13134                negate = True;
   13135                break;
   13136             default:
   13137                negate = False;
   13138          }
   13139          IRTemp hiResult = newTemp(Ity_I64);
   13140          IRTemp loResult = newTemp(Ity_I64);
   13141          IRTemp frT = newTemp(Ity_F64);
   13142          IRTemp frT2 = newTemp(Ity_F64);
   13143          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
   13144              (UInt)XT, (UInt)XA, (UInt)XB);
   13145          assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
   13146          assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
   13147 
   13148          assign( hiResult,
   13149                  unop( Iop_ReinterpF64asI64,
   13150                        qop( mOp,
   13151                             rm,
   13152                             mkexpr( frA ),
   13153                             mkexpr( mdp ? frT : frB ),
   13154                             mkexpr( mdp ? frB : frT ) ) ) );
   13155          assign( loResult,
   13156                  unop( Iop_ReinterpF64asI64,
   13157                        qop( mOp,
   13158                             rm,
   13159                             mkexpr( frA2 ),
   13160                             mkexpr( mdp ? frT2 : frB2 ),
   13161                             mkexpr( mdp ? frB2 : frT2 ) ) ) );
   13162          putVSReg( XT,
   13163                    binop( Iop_64HLtoV128,
   13164                           mkexpr( negate ? getNegatedResult( hiResult )
   13165                                          : hiResult ),
   13166                           mkexpr( negate ? getNegatedResult( loResult )
   13167                                          : loResult ) ) );
   13168          break;
   13169       }
   13170       case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   13171       {
   13172          IRTemp frBHi_I64 = newTemp(Ity_I64);
   13173          IRTemp frBLo_I64 = newTemp(Ity_I64);
   13174          IRTemp flagsHi = newTemp(Ity_I32);
   13175          IRTemp flagsLo = newTemp(Ity_I32);
   13176          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13177          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   13178          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   13179 
   13180          DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
   13181          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   13182          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   13183          do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
   13184          do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
   13185          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   13186           * where fl_flag == 1 on ppc64.
   13187           */
   13188          assign( flagsHi,
   13189                  binop( Iop_Or32,
   13190                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13191                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   13192                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   13193          assign( flagsLo,
   13194                  binop( Iop_Or32,
   13195                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13196                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   13197                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   13198          putGST_field( PPC_GST_CR,
   13199                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   13200                        crfD );
   13201          break;
   13202       }
   13203       case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
   13204       {
   13205          IRTemp frBHi_I64 = newTemp(Ity_I64);
   13206          IRTemp frBLo_I64 = newTemp(Ity_I64);
   13207          IRTemp frAHi_I64 = newTemp(Ity_I64);
   13208          IRTemp frALo_I64 = newTemp(Ity_I64);
   13209          IRTemp flagsHi = newTemp(Ity_I32);
   13210          IRTemp flagsLo = newTemp(Ity_I32);
   13211          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13212          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   13213          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   13214 
   13215          DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
   13216          assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
   13217          assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
   13218          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   13219          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   13220 
   13221          _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
   13222          _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
   13223          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   13224           * where fl_flag == 1 on ppc64.
   13225           */
   13226          assign( flagsHi,
   13227                  binop( Iop_Or32,
   13228                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13229                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   13230                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   13231          assign( flagsLo,
   13232                  binop( Iop_Or32,
   13233                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13234                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   13235                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   13236          putGST_field( PPC_GST_CR,
   13237                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   13238                        crfD );
   13239          break;
   13240       }
   13241 
   13242       default:
   13243          vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
   13244          return False;
   13245    }
   13246    return True;
   13247 }
   13248 
   13249 /*
   13250  * VSX vector Single Precision Floating Point Arithmetic Instructions
   13251  */
   13252 static Bool
   13253 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
   13254 {
   13255    /* XX3-Form */
   13256    UChar opc1 = ifieldOPC( theInstr );
   13257    UChar XT = ifieldRegXT( theInstr );
   13258    UChar XA = ifieldRegXA( theInstr );
   13259    UChar XB = ifieldRegXB( theInstr );
   13260    IRExpr* rm = get_IR_roundingmode();
   13261    IRTemp a3, a2, a1, a0;
   13262    IRTemp b3, b2, b1, b0;
   13263    IRTemp res0 = newTemp(Ity_I32);
   13264    IRTemp res1 = newTemp(Ity_I32);
   13265    IRTemp res2 = newTemp(Ity_I32);
   13266    IRTemp res3 = newTemp(Ity_I32);
   13267 
   13268    a3 = a2 = a1 = a0 = IRTemp_INVALID;
   13269    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   13270 
   13271    if (opc1 != 0x3C) {
   13272       vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
   13273       return False;
   13274    }
   13275 
   13276    switch (opc2) {
   13277       case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
   13278          DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13279          // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
   13280          putVSReg( XT, triop(Iop_Add32Fx4, rm,
   13281                              getVSReg( XA ), getVSReg( XB )) );
   13282          break;
   13283 
   13284       case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
   13285          DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13286          // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
   13287          putVSReg( XT, triop(Iop_Mul32Fx4, rm,
   13288                              getVSReg( XA ), getVSReg( XB )) );
   13289          break;
   13290 
   13291       case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
   13292          DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13293          // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
   13294          putVSReg( XT, triop(Iop_Sub32Fx4, rm,
   13295                              getVSReg( XA ), getVSReg( XB )) );
   13296          break;
   13297 
   13298       case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
   13299       {
   13300          /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
   13301           * So there are two choices:
   13302           *   1. Implement the xvdivsp with a native insn; or
   13303           *   2. Extract the 4 single precision floats from each vector
   13304           *      register inputs and perform fdivs on each pair
   13305           * I will do the latter, due to the general philosophy of
   13306           * reusing existing implementations when practical.
   13307           */
   13308          DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13309          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   13310          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13311 
   13312          assign( res0,
   13313               unop( Iop_ReinterpF32asI32,
   13314                     unop( Iop_TruncF64asF32,
   13315                           triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
   13316          assign( res1,
   13317                  unop( Iop_ReinterpF32asI32,
   13318                        unop( Iop_TruncF64asF32,
   13319                              triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
   13320          assign( res2,
   13321                  unop( Iop_ReinterpF32asI32,
   13322                        unop( Iop_TruncF64asF32,
   13323                              triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
   13324          assign( res3,
   13325                  unop( Iop_ReinterpF32asI32,
   13326                        unop( Iop_TruncF64asF32,
   13327                              triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
   13328 
   13329          putVSReg( XT,
   13330                    binop( Iop_64HLtoV128,
   13331                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   13332                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   13333          break;
   13334       }
   13335       case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
   13336       {
   13337          DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
   13338          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13339          /* Note: The native xvsqrtsp insruction does not always give the same precision
   13340           * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
   13341           * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
   13342           * to the actual instruction.
   13343           */
   13344 
   13345          assign( res0,
   13346                  unop( Iop_ReinterpF32asI32,
   13347                        unop( Iop_TruncF64asF32,
   13348                              binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
   13349          assign( res1,
   13350                  unop( Iop_ReinterpF32asI32,
   13351                        unop( Iop_TruncF64asF32,
   13352                              binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
   13353          assign( res2,
   13354                  unop( Iop_ReinterpF32asI32,
   13355                        unop( Iop_TruncF64asF32,
   13356                              binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
   13357          assign( res3,
   13358                  unop( Iop_ReinterpF32asI32,
   13359                        unop( Iop_TruncF64asF32,
   13360                              binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
   13361 
   13362          putVSReg( XT,
   13363                    binop( Iop_64HLtoV128,
   13364                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   13365                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   13366          break;
   13367       }
   13368 
   13369       case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
   13370       case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
   13371       case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
   13372       case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
   13373       {
   13374          IRTemp t3, t2, t1, t0;
   13375          Bool msp = False;
   13376          Bool negate;
   13377          const HChar * oper_name = NULL;
   13378          IROp mOp = Iop_INVALID;
   13379          switch (opc2) {
   13380             case 0x104: case 0x124:
   13381             case 0x304: case 0x324:
   13382                msp = (opc2 & 0x0FF) == 0x024;
   13383                mOp = Iop_MAddF64r32;
   13384                oper_name = "madd";
   13385                break;
   13386 
   13387             case 0x144: case 0x164:
   13388             case 0x344: case 0x364:
   13389                msp = (opc2 & 0x0FF) == 0x064;
   13390                mOp = Iop_MSubF64r32;
   13391                oper_name = "sub";
   13392                break;
   13393 
   13394             default:
   13395                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   13396          }
   13397 
   13398          switch (opc2) {
   13399             case 0x304: case 0x324:
   13400             case 0x344: case 0x364:
   13401                negate = True;
   13402                break;
   13403 
   13404             default:
   13405                negate = False;
   13406          }
   13407 
   13408          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp",
   13409              (UInt)XT, (UInt)XA, (UInt)XB);
   13410 
   13411          t3 = t2 = t1 = t0 = IRTemp_INVALID;
   13412          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   13413          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13414          breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
   13415 
   13416          assign( res0,
   13417                  unop( Iop_ReinterpF32asI32,
   13418                        unop( Iop_TruncF64asF32,
   13419                              qop( mOp,
   13420                                   rm,
   13421                                   mkexpr( a0 ),
   13422                                   mkexpr( msp ? t0 : b0 ),
   13423                                   mkexpr( msp ? b0 : t0 ) ) ) ) );
   13424          assign( res1,
   13425                  unop( Iop_ReinterpF32asI32,
   13426                        unop( Iop_TruncF64asF32,
   13427                              qop( mOp,
   13428                                   rm,
   13429                                   mkexpr( a1 ),
   13430                                   mkexpr( msp ? t1 : b1 ),
   13431                                   mkexpr( msp ? b1 : t1 ) ) ) ) );
   13432          assign( res2,
   13433                  unop( Iop_ReinterpF32asI32,
   13434                        unop( Iop_TruncF64asF32,
   13435                              qop( mOp,
   13436                                   rm,
   13437                                   mkexpr( a2 ),
   13438                                   mkexpr( msp ? t2 : b2 ),
   13439                                   mkexpr( msp ? b2 : t2 ) ) ) ) );
   13440          assign( res3,
   13441                  unop( Iop_ReinterpF32asI32,
   13442                        unop( Iop_TruncF64asF32,
   13443                              qop( mOp,
   13444                                   rm,
   13445                                   mkexpr( a3 ),
   13446                                   mkexpr( msp ? t3 : b3 ),
   13447                                   mkexpr( msp ? b3 : t3 ) ) ) ) );
   13448 
   13449          putVSReg( XT,
   13450                    binop( Iop_64HLtoV128,
   13451                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
   13452                                  mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
   13453                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
   13454                                  mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
   13455 
   13456          break;
   13457       }
   13458       case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
   13459       {
   13460          IRTemp flags0 = newTemp(Ity_I32);
   13461          IRTemp flags1 = newTemp(Ity_I32);
   13462          IRTemp flags2 = newTemp(Ity_I32);
   13463          IRTemp flags3 = newTemp(Ity_I32);
   13464          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13465          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   13466          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   13467          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   13468          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   13469          DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
   13470 
   13471          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13472          do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   13473          do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   13474          do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   13475          do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   13476 
   13477          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   13478           * where fl_flag == 1 on ppc64.
   13479           */
   13480          assign( flags0,
   13481                  binop( Iop_Or32,
   13482                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13483                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   13484                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   13485          assign( flags1,
   13486                  binop( Iop_Or32,
   13487                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13488                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   13489                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   13490          assign( flags2,
   13491                  binop( Iop_Or32,
   13492                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13493                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   13494                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   13495          assign( flags3,
   13496                  binop( Iop_Or32,
   13497                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13498                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   13499                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   13500          putGST_field( PPC_GST_CR,
   13501                        binop( Iop_Or32,
   13502                               mkexpr( flags0 ),
   13503                               binop( Iop_Or32,
   13504                                      mkexpr( flags1 ),
   13505                                      binop( Iop_Or32,
   13506                                             mkexpr( flags2 ),
   13507                                             mkexpr( flags3 ) ) ) ),
   13508                        crfD );
   13509 
   13510          break;
   13511       }
   13512       case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
   13513       {
   13514          IRTemp flags0 = newTemp(Ity_I32);
   13515          IRTemp flags1 = newTemp(Ity_I32);
   13516          IRTemp flags2 = newTemp(Ity_I32);
   13517          IRTemp flags3 = newTemp(Ity_I32);
   13518          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13519          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   13520          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   13521          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   13522          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   13523          DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
   13524 
   13525          breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   13526          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13527          _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   13528          _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   13529          _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   13530          _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   13531 
   13532          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   13533           * where fl_flag == 1 on ppc64.
   13534           */
   13535          assign( flags0,
   13536                  binop( Iop_Or32,
   13537                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13538                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   13539                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   13540          assign( flags1,
   13541                  binop( Iop_Or32,
   13542                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13543                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   13544                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   13545          assign( flags2,
   13546                  binop( Iop_Or32,
   13547                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13548                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   13549                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   13550          assign( flags3,
   13551                  binop( Iop_Or32,
   13552                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13553                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   13554                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   13555          putGST_field( PPC_GST_CR,
   13556                        binop( Iop_Or32,
   13557                               mkexpr( flags0 ),
   13558                               binop( Iop_Or32,
   13559                                      mkexpr( flags1 ),
   13560                                      binop( Iop_Or32,
   13561                                             mkexpr( flags2 ),
   13562                                             mkexpr( flags3 ) ) ) ),
   13563                        crfD );
   13564 
   13565          break;
   13566       }
   13567 
   13568       default:
   13569          vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
   13570          return False;
   13571    }
   13572    return True;
   13573 }
   13574 
   13575 /*
   13576  * Vector Population Count/bit matrix transpose
   13577  */
   13578 static Bool
   13579 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
   13580 {
   13581    UChar vRB_addr = ifieldRegB(theInstr);
   13582    UChar vRT_addr = ifieldRegDS(theInstr);
   13583    UChar opc1 = ifieldOPC( theInstr );
   13584    IRTemp vB = newTemp(Ity_V128);
   13585    assign( vB, getVReg(vRB_addr));
   13586 
   13587    if (opc1 != 0x4) {
   13588       vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
   13589       return False;
   13590    }
   13591 
   13592    switch (opc2) {
   13593       case 0x702:    // vclzb
   13594          DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
   13595          putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) );
   13596          break;
   13597 
   13598       case 0x742:    // vclzh
   13599          DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
   13600          putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) );
   13601          break;
   13602 
   13603       case 0x782:    // vclzw
   13604          DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
   13605          putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) );
   13606          break;
   13607 
   13608       case 0x7C2:    // vclzd
   13609          DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
   13610          putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
   13611          break;
   13612 
   13613       case 0x703:    // vpopcntb
   13614       {
   13615          /* Break vector into 32-bit words and do the population count
   13616           * on byte in the words
   13617           */
   13618          IRType ty = Ity_I32;
   13619          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13620          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13621          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   13622          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   13623 
   13624          DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
   13625          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13626          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   BYTE);
   13627          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  BYTE);
   13628          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  BYTE);
   13629          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
   13630 
   13631          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   13632                                          cnt_bits32_63, cnt_bits0_31) );
   13633          break;
   13634       }
   13635 
   13636       case 0x743:    // vpopcnth
   13637       {
   13638          /* Break vector into 32-bit words and do the population count
   13639           * for each half word
   13640           */
   13641          IRType ty = Ity_I32;
   13642          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13643          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13644          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   13645          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   13646 
   13647          DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
   13648          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13649 
   13650          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   HWORD);
   13651          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  HWORD);
   13652          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  HWORD);
   13653          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
   13654 
   13655          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   13656                                          cnt_bits32_63, cnt_bits0_31) );
   13657          break;
   13658       }
   13659 
   13660       case 0x783:    // vpopcntw
   13661       {
   13662          /* Break vector into 32-bit words and do the population count
   13663           * on each word.
   13664           */
   13665          IRType ty = Ity_I32;
   13666          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13667          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13668          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   13669          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   13670 
   13671          DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
   13672          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13673 
   13674          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   WORD);
   13675          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  WORD);
   13676          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  WORD);
   13677          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
   13678 
   13679          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   13680                                          cnt_bits32_63, cnt_bits0_31) );
   13681          break;
   13682       }
   13683 
   13684       case 0x7C3:    // vpopcntd
   13685       {
   13686          if (mode64) {
   13687             /* Break vector into 64-bit double words and do the population count
   13688              * on each double word.
   13689              */
   13690             IRType ty = Ity_I64;
   13691             IRTemp bits0_63   = newTemp(Ity_I64);
   13692             IRTemp bits64_127 = newTemp(Ity_I64);
   13693             IRTemp cnt_bits0_63   = newTemp(Ity_I64);
   13694             IRTemp cnt_bits64_127 = newTemp(Ity_I64);
   13695 
   13696             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
   13697 
   13698             assign(bits0_63,   unop( Iop_V128to64,   mkexpr( vB ) ) );
   13699             assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
   13700             cnt_bits0_63   = gen_POPCOUNT(ty, bits0_63,   DWORD);
   13701             cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
   13702 
   13703             putVReg( vRT_addr, binop( Iop_64HLtoV128,
   13704                                       mkexpr( cnt_bits64_127 ),
   13705                                       mkexpr( cnt_bits0_63 ) ) );
   13706          } else {
   13707             /* Break vector into 32-bit words and do the population count
   13708              * on each doubleword.
   13709              */
   13710             IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13711             bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13712             IRTemp cnt_bits0_63   = newTemp(Ity_I64);
   13713             IRTemp cnt_bits64_127  = newTemp(Ity_I64);
   13714 
   13715             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
   13716             breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13717 
   13718             cnt_bits0_63   = gen_vpopcntd_mode32(bits0_31, bits32_63);
   13719             cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
   13720 
   13721             putVReg( vRT_addr, binop( Iop_64HLtoV128,
   13722                                       mkexpr( cnt_bits64_127 ),
   13723                                       mkexpr( cnt_bits0_63 ) ) );
   13724          }
   13725          break;
   13726       }
   13727 
   13728       case 0x50C:  // vgbbd Vector Gather Bits by Bytes by Doubleword
   13729          DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
   13730          putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
   13731          break;
   13732 
   13733       default:
   13734          vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
   13735          return False;
   13736       break;
   13737    }
   13738    return True;
   13739 }
   13740 
   13741 typedef enum {
   13742    PPC_CMP_EQ = 2,
   13743    PPC_CMP_GT = 4,
   13744    PPC_CMP_GE = 6,
   13745    PPC_CMP_LT = 8
   13746 } ppc_cmp_t;
   13747 
   13748 
   13749 /*
   13750   This helper function takes as input the IRExpr returned
   13751   from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
   13752   in IR form.  This helper function converts it to PPC form.
   13753 
   13754   Map compare result from IR to PPC
   13755 
   13756   FP cmp result | PPC | IR
   13757   --------------------------
   13758   UN            | 0x1 | 0x45
   13759   EQ            | 0x2 | 0x40
   13760   GT            | 0x4 | 0x00
   13761   LT            | 0x8 | 0x01
   13762 
   13763  condcode = Shl(1, (~(ccIR>>5) & 2)
   13764                     | ((ccIR ^ (ccIR>>6)) & 1)
   13765 */
   13766 static IRTemp
   13767 get_fp_cmp_CR_val (IRExpr * ccIR_expr)
   13768 {
   13769    IRTemp condcode = newTemp( Ity_I32 );
   13770    IRTemp ccIR = newTemp( Ity_I32 );
   13771 
   13772    assign(ccIR, ccIR_expr);
   13773    assign( condcode,
   13774            binop( Iop_Shl32,
   13775                   mkU32( 1 ),
   13776                   unop( Iop_32to8,
   13777                         binop( Iop_Or32,
   13778                                binop( Iop_And32,
   13779                                       unop( Iop_Not32,
   13780                                             binop( Iop_Shr32,
   13781                                                    mkexpr( ccIR ),
   13782                                                    mkU8( 5 ) ) ),
   13783                                       mkU32( 2 ) ),
   13784                                binop( Iop_And32,
   13785                                       binop( Iop_Xor32,
   13786                                              mkexpr( ccIR ),
   13787                                              binop( Iop_Shr32,
   13788                                                     mkexpr( ccIR ),
   13789                                                     mkU8( 6 ) ) ),
   13790                                       mkU32( 1 ) ) ) ) ) );
   13791    return condcode;
   13792 }
   13793 
   13794 /*
   13795  * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
   13796  * following these special rules:
   13797  *   - The max/min of a QNaN and any value is that value
   13798  *     (When two QNaNs are being compared, the frA QNaN is the return value.)
   13799  *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
   13800  *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
   13801  */
   13802 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
   13803 {
   13804    IRTemp frA_isNaN = newTemp(Ity_I1);
   13805    IRTemp frB_isNaN = newTemp(Ity_I1);
   13806    IRTemp frA_isSNaN = newTemp(Ity_I1);
   13807    IRTemp frB_isSNaN = newTemp(Ity_I1);
   13808    IRTemp frA_isQNaN = newTemp(Ity_I1);
   13809    IRTemp frB_isQNaN = newTemp(Ity_I1);
   13810 
   13811    assign( frA_isNaN, is_NaN( frA_I64 ) );
   13812    assign( frB_isNaN, is_NaN( frB_I64 ) );
   13813    // If operand is a NAN and bit 12 is '0', then it's an SNaN
   13814    assign( frA_isSNaN,
   13815            mkAND1( mkexpr(frA_isNaN),
   13816                    binop( Iop_CmpEQ32,
   13817                           binop( Iop_And32,
   13818                                  unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
   13819                                  mkU32( 0x00080000 ) ),
   13820                           mkU32( 0 ) ) ) );
   13821    assign( frB_isSNaN,
   13822            mkAND1( mkexpr(frB_isNaN),
   13823                    binop( Iop_CmpEQ32,
   13824                           binop( Iop_And32,
   13825                                  unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
   13826                                  mkU32( 0x00080000 ) ),
   13827                           mkU32( 0 ) ) ) );
   13828    assign( frA_isQNaN,
   13829            mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
   13830    assign( frB_isQNaN,
   13831            mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
   13832 
   13833    /* Based on the rules specified in the function prologue, the algorithm is as follows:
   13834     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   13835     *   if frA is a SNaN
   13836     *     result = frA converted to QNaN
   13837     *   else if frB is a SNaN
   13838     *     result = frB converted to QNaN
   13839     *   else if frB is a QNaN
   13840     *     result = frA
   13841     *   // One of frA or frB was a NaN in order for this function to be called, so
   13842     *   // if we get to this point, we KNOW that frA must be a QNaN.
   13843     *   else // frA is a QNaN
   13844     *     result = frB
   13845     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   13846     */
   13847 
   13848 #define SNAN_MASK 0x0008000000000000ULL
   13849    return
   13850    IRExpr_ITE(mkexpr(frA_isSNaN),
   13851               /* then: result = frA converted to QNaN */
   13852               binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
   13853               /* else:  if frB is a SNaN */
   13854               IRExpr_ITE(mkexpr(frB_isSNaN),
   13855                          /* then: result = frB converted to QNaN */
   13856                          binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
   13857                          /* else:  if frB is a QNaN */
   13858                          IRExpr_ITE(mkexpr(frB_isQNaN),
   13859                                     /* then: result = frA */
   13860                                     mkexpr(frA_I64),
   13861                                     /* else:  frA is a QNaN, so result = frB */
   13862                                     mkexpr(frB_I64))));
   13863 }
   13864 
   13865 /*
   13866  * Helper function for get_max_min_fp.
   13867  */
   13868 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
   13869 {
   13870    IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   13871                                                   unop( Iop_ReinterpI64asF64,
   13872                                                         mkexpr( src1 ) ),
   13873                                                   unop( Iop_ReinterpI64asF64,
   13874                                                         mkexpr( src2 ) ) ) );
   13875 
   13876    return IRExpr_ITE( binop( Iop_CmpEQ32,
   13877                                mkexpr( src1cmpsrc2 ),
   13878                                mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
   13879                       /* then: use src1 */
   13880                       mkexpr( src1 ),
   13881                       /* else: use src2 */
   13882                       mkexpr( src2 ) );
   13883 }
   13884 
   13885 /*
   13886  * Helper function for "Maximum/Minimum Double Precision" operations.
   13887  * Arguments: frA and frb are Ity_I64
   13888  * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
   13889  */
   13890 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
   13891 {
   13892    /* There are three special cases where get_fp_cmp_CR_val is not helpful
   13893     * for ascertaining the maximum between two doubles:
   13894     *   1. The max/min of +0 and -0 is +0.
   13895     *   2. The max/min of a QNaN and any value is that value.
   13896     *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
   13897     * We perform the check for [+/-]0 here in this function and use the
   13898     * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
   13899     * to do the standard comparison function.
   13900     */
   13901    IRTemp anyNaN = newTemp(Ity_I1);
   13902    IRTemp frA_isZero = newTemp(Ity_I1);
   13903    IRTemp frB_isZero = newTemp(Ity_I1);
   13904    assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
   13905    assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
   13906    assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
   13907 #define MINUS_ZERO 0x8000000000000000ULL
   13908 
   13909    return IRExpr_ITE( /* If both arguments are zero . . . */
   13910                      mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
   13911                      /* then: if frA is -0 and isMin==True, return -0;
   13912                       *     else if frA is +0 and isMin==False; return +0;
   13913                       *     otherwise, simply return frB. */
   13914                      IRExpr_ITE( binop( Iop_CmpEQ32,
   13915                                         unop( Iop_64HIto32,
   13916                                               mkexpr( frA_I64 ) ),
   13917                                         mkU32( isMin ? 0x80000000 : 0 ) ),
   13918                                  mkU64( isMin ? MINUS_ZERO : 0ULL ),
   13919                                  mkexpr( frB_I64 ) ),
   13920                      /* else: check if either input is a NaN*/
   13921                      IRExpr_ITE( mkexpr( anyNaN ),
   13922                                  /* then: use "NaN helper" */
   13923                                  _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
   13924                                  /* else: use "comparison helper" */
   13925                                  _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
   13926 }
   13927 
   13928 static const HChar * _get_vsx_rdpi_suffix(UInt opc2)
   13929 {
   13930    switch (opc2 & 0x7F) {
   13931       case 0x72:
   13932          return "m";
   13933       case 0x52:
   13934          return "p";
   13935       case 0x56:
   13936          return "c";
   13937       case 0x32:
   13938          return "z";
   13939       case 0x12:
   13940          return "";
   13941 
   13942       default: // Impossible to get here
   13943          vex_printf("Unrecognized opcode %x\n", opc2);
   13944          vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
   13945    }
   13946 }
   13947 
   13948 /*
   13949  * Helper function for vector/scalar double precision fp round to integer instructions.
   13950  */
   13951 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
   13952 {
   13953 
   13954    /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
   13955    IRTemp frB = newTemp(Ity_F64);
   13956    IRTemp frD = newTemp(Ity_F64);
   13957    IRTemp intermediateResult = newTemp(Ity_I64);
   13958    IRTemp is_SNAN = newTemp(Ity_I1);
   13959    IRExpr * hi32;
   13960    IRExpr * rxpi_rm;
   13961    switch (opc2 & 0x7F) {
   13962       case 0x72:
   13963          rxpi_rm = mkU32(Irrm_NegINF);
   13964          break;
   13965       case 0x52:
   13966          rxpi_rm = mkU32(Irrm_PosINF);
   13967          break;
   13968       case 0x56:
   13969          rxpi_rm = get_IR_roundingmode();
   13970          break;
   13971       case 0x32:
   13972          rxpi_rm = mkU32(Irrm_ZERO);
   13973          break;
   13974       case 0x12:
   13975          rxpi_rm = mkU32(Irrm_NEAREST);
   13976          break;
   13977 
   13978       default: // Impossible to get here
   13979          vex_printf("Unrecognized opcode %x\n", opc2);
   13980          vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
   13981    }
   13982    assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
   13983    assign( intermediateResult,
   13984            binop( Iop_F64toI64S, rxpi_rm,
   13985                   mkexpr( frB ) ) );
   13986 
   13987    /* don't use the rounded integer if frB is outside -9e18..9e18 */
   13988    /* F64 has only log10(2**52) significant digits anyway */
   13989    /* need to preserve sign of zero */
   13990    /*   frD = (fabs(frB) > 9e18) ? frB :
   13991             (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
   13992    assign( frD,
   13993            IRExpr_ITE(
   13994               binop( Iop_CmpNE8,
   13995                      unop( Iop_32to8,
   13996                            binop( Iop_CmpF64,
   13997                                   IRExpr_Const( IRConst_F64( 9e18 ) ),
   13998                                   unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
   13999                      mkU8(0) ),
   14000               mkexpr( frB ),
   14001               IRExpr_ITE(
   14002                  binop( Iop_CmpNE32,
   14003                         binop( Iop_Shr32,
   14004                                unop( Iop_64HIto32,
   14005                                      mkexpr( frB_I64 ) ),
   14006                                mkU8( 31 ) ),
   14007                         mkU32(0) ),
   14008                  unop( Iop_NegF64,
   14009                        unop( Iop_AbsF64,
   14010                              binop( Iop_I64StoF64,
   14011                                     mkU32( 0 ),
   14012                                     mkexpr( intermediateResult ) ) ) ),
   14013                  binop( Iop_I64StoF64,
   14014                         mkU32( 0 ),
   14015                         mkexpr( intermediateResult ) )
   14016               )
   14017            )
   14018    );
   14019 
   14020    /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
   14021     * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
   14022     */
   14023 #define SNAN_MASK 0x0008000000000000ULL
   14024    hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
   14025    assign( is_SNAN,
   14026            mkAND1( is_NaN( frB_I64 ),
   14027                    binop( Iop_CmpEQ32,
   14028                           binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
   14029                           mkU32( 0 ) ) ) );
   14030 
   14031    return IRExpr_ITE( mkexpr( is_SNAN ),
   14032                         unop( Iop_ReinterpI64asF64,
   14033                               binop( Iop_Xor64,
   14034                                      mkU64( SNAN_MASK ),
   14035                                      mkexpr( frB_I64 ) ) ),
   14036                       mkexpr( frD ));
   14037 }
   14038 
   14039 /*
   14040  * Miscellaneous VSX vector instructions
   14041  */
   14042 static Bool
   14043 dis_vxv_misc ( UInt theInstr, UInt opc2 )
   14044 {
   14045    /* XX3-Form */
   14046    UChar opc1 = ifieldOPC( theInstr );
   14047    UChar XT = ifieldRegXT( theInstr );
   14048    UChar XB = ifieldRegXB( theInstr );
   14049 
   14050    if (opc1 != 0x3C) {
   14051       vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
   14052       return False;
   14053    }
   14054 
   14055    switch (opc2) {
   14056       case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
   14057       case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
   14058                    //             Double-Precision)
   14059       {
   14060          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   14061          IRExpr* rm  = get_IR_roundingmode();
   14062          IRTemp frB = newTemp(Ity_I64);
   14063          IRTemp frB2 = newTemp(Ity_I64);
   14064          Bool redp = opc2 == 0x1B4;
   14065          IRTemp sqrtHi = newTemp(Ity_F64);
   14066          IRTemp sqrtLo = newTemp(Ity_F64);
   14067          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   14068          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   14069 
   14070          DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB);
   14071          if (!redp) {
   14072             assign( sqrtHi,
   14073                     binop( Iop_SqrtF64,
   14074                            rm,
   14075                            unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
   14076             assign( sqrtLo,
   14077                     binop( Iop_SqrtF64,
   14078                            rm,
   14079                            unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
   14080          }
   14081          putVSReg( XT,
   14082                    binop( Iop_64HLtoV128,
   14083                           unop( Iop_ReinterpF64asI64,
   14084                                 triop( Iop_DivF64,
   14085                                        rm,
   14086                                        ieee_one,
   14087                                        redp ? unop( Iop_ReinterpI64asF64,
   14088                                                     mkexpr( frB ) )
   14089                                             : mkexpr( sqrtHi ) ) ),
   14090                           unop( Iop_ReinterpF64asI64,
   14091                                 triop( Iop_DivF64,
   14092                                        rm,
   14093                                        ieee_one,
   14094                                        redp ? unop( Iop_ReinterpI64asF64,
   14095                                                     mkexpr( frB2 ) )
   14096                                             : mkexpr( sqrtLo ) ) ) ) );
   14097          break;
   14098 
   14099       }
   14100       case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
   14101       case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
   14102       {
   14103          IRTemp b3, b2, b1, b0;
   14104          IRTemp res0 = newTemp(Ity_I32);
   14105          IRTemp res1 = newTemp(Ity_I32);
   14106          IRTemp res2 = newTemp(Ity_I32);
   14107          IRTemp res3 = newTemp(Ity_I32);
   14108          IRTemp sqrt3 = newTemp(Ity_F64);
   14109          IRTemp sqrt2 = newTemp(Ity_F64);
   14110          IRTemp sqrt1 = newTemp(Ity_F64);
   14111          IRTemp sqrt0 = newTemp(Ity_F64);
   14112          IRExpr* rm  = get_IR_roundingmode();
   14113          Bool resp = opc2 == 0x134;
   14114 
   14115          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   14116 
   14117          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   14118          DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB);
   14119          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   14120 
   14121          if (!resp) {
   14122             assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
   14123             assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
   14124             assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
   14125             assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
   14126          }
   14127 
   14128          assign( res0,
   14129                  unop( Iop_ReinterpF32asI32,
   14130                        unop( Iop_TruncF64asF32,
   14131                              triop( Iop_DivF64r32,
   14132                                     rm,
   14133                                     ieee_one,
   14134                                     resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
   14135          assign( res1,
   14136                  unop( Iop_ReinterpF32asI32,
   14137                        unop( Iop_TruncF64asF32,
   14138                              triop( Iop_DivF64r32,
   14139                                     rm,
   14140                                     ieee_one,
   14141                                     resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
   14142          assign( res2,
   14143                  unop( Iop_ReinterpF32asI32,
   14144                        unop( Iop_TruncF64asF32,
   14145                              triop( Iop_DivF64r32,
   14146                                     rm,
   14147                                     ieee_one,
   14148                                     resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
   14149          assign( res3,
   14150                  unop( Iop_ReinterpF32asI32,
   14151                        unop( Iop_TruncF64asF32,
   14152                              triop( Iop_DivF64r32,
   14153                                     rm,
   14154                                     ieee_one,
   14155                                     resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
   14156          putVSReg( XT,
   14157                    binop( Iop_64HLtoV128,
   14158                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   14159                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   14160          break;
   14161       }
   14162       case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
   14163       case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
   14164       {
   14165          UChar XA = ifieldRegXA( theInstr );
   14166          IRTemp a3, a2, a1, a0;
   14167          IRTemp b3, b2, b1, b0;
   14168          IRTemp res0 = newTemp( Ity_I32 );
   14169          IRTemp res1 = newTemp( Ity_I32 );
   14170          IRTemp res2 = newTemp( Ity_I32 );
   14171          IRTemp res3 = newTemp( Ity_I32 );
   14172          IRTemp a0_I64 = newTemp( Ity_I64 );
   14173          IRTemp a1_I64 = newTemp( Ity_I64 );
   14174          IRTemp a2_I64 = newTemp( Ity_I64 );
   14175          IRTemp a3_I64 = newTemp( Ity_I64 );
   14176          IRTemp b0_I64 = newTemp( Ity_I64 );
   14177          IRTemp b1_I64 = newTemp( Ity_I64 );
   14178          IRTemp b2_I64 = newTemp( Ity_I64 );
   14179          IRTemp b3_I64 = newTemp( Ity_I64 );
   14180 
   14181          Bool isMin = opc2 == 0x320 ? True : False;
   14182 
   14183          a3 = a2 = a1 = a0 = IRTemp_INVALID;
   14184          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   14185          DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB);
   14186          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   14187          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   14188          assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
   14189          assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
   14190          assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
   14191          assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
   14192          assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
   14193          assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
   14194          assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
   14195          assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
   14196          assign( res0,
   14197                  unop( Iop_ReinterpF32asI32,
   14198                        unop( Iop_TruncF64asF32,
   14199                              unop( Iop_ReinterpI64asF64,
   14200                                    get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
   14201          assign( res1,
   14202                  unop( Iop_ReinterpF32asI32,
   14203                        unop( Iop_TruncF64asF32,
   14204                              unop( Iop_ReinterpI64asF64,
   14205                                    get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
   14206          assign( res2,
   14207                  unop( Iop_ReinterpF32asI32,
   14208                        unop( Iop_TruncF64asF32,
   14209                              unop( Iop_ReinterpI64asF64,
   14210                                    get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
   14211          assign( res3,
   14212                  unop( Iop_ReinterpF32asI32,
   14213                        unop( Iop_TruncF64asF32,
   14214                              unop( Iop_ReinterpI64asF64,
   14215                                    get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
   14216          putVSReg( XT,
   14217                    binop( Iop_64HLtoV128,
   14218                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   14219                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   14220          break;
   14221       }
   14222       case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
   14223       case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
   14224       {
   14225          UChar XA = ifieldRegXA( theInstr );
   14226          IRTemp frA = newTemp(Ity_I64);
   14227          IRTemp frB = newTemp(Ity_I64);
   14228          IRTemp frA2 = newTemp(Ity_I64);
   14229          IRTemp frB2 = newTemp(Ity_I64);
   14230          Bool isMin = opc2 == 0x3A0 ? True : False;
   14231 
   14232          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   14233          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   14234          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   14235          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   14236          DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB);
   14237          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
   14238 
   14239          break;
   14240       }
   14241       case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
   14242       {
   14243          UChar XA = ifieldRegXA( theInstr );
   14244          IRTemp frA = newTemp(Ity_I64);
   14245          IRTemp frB = newTemp(Ity_I64);
   14246          IRTemp frA2 = newTemp(Ity_I64);
   14247          IRTemp frB2 = newTemp(Ity_I64);
   14248          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   14249          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   14250          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   14251          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   14252 
   14253          DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14254          putVSReg( XT,
   14255                    binop( Iop_64HLtoV128,
   14256                           binop( Iop_Or64,
   14257                                  binop( Iop_And64,
   14258                                         mkexpr( frA ),
   14259                                         mkU64( SIGN_BIT ) ),
   14260                                  binop( Iop_And64,
   14261                                         mkexpr( frB ),
   14262                                         mkU64( SIGN_MASK ) ) ),
   14263                           binop( Iop_Or64,
   14264                                  binop( Iop_And64,
   14265                                         mkexpr( frA2 ),
   14266                                         mkU64( SIGN_BIT ) ),
   14267                                  binop( Iop_And64,
   14268                                         mkexpr( frB2 ),
   14269                                         mkU64( SIGN_MASK ) ) ) ) );
   14270          break;
   14271       }
   14272       case 0x340: // xvcpsgnsp
   14273       {
   14274          UChar XA = ifieldRegXA( theInstr );
   14275          IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
   14276          IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
   14277          IRTemp resHi = newTemp(Ity_I64);
   14278          IRTemp resLo = newTemp(Ity_I64);
   14279 
   14280          a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
   14281          b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
   14282          DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB);
   14283          breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
   14284          breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
   14285 
   14286          assign( resHi,
   14287                  binop( Iop_32HLto64,
   14288                         binop( Iop_Or32,
   14289                                binop( Iop_And32,
   14290                                       unop(Iop_64to32, mkexpr( a3_I64 ) ),
   14291                                       mkU32( SIGN_BIT32 ) ),
   14292                                binop( Iop_And32,
   14293                                       unop(Iop_64to32, mkexpr( b3_I64 ) ),
   14294                                       mkU32( SIGN_MASK32) ) ),
   14295 
   14296                         binop( Iop_Or32,
   14297                                binop( Iop_And32,
   14298                                       unop(Iop_64to32, mkexpr( a2_I64 ) ),
   14299                                       mkU32( SIGN_BIT32 ) ),
   14300                                binop( Iop_And32,
   14301                                       unop(Iop_64to32, mkexpr( b2_I64 ) ),
   14302                                       mkU32( SIGN_MASK32 ) ) ) ) );
   14303          assign( resLo,
   14304                  binop( Iop_32HLto64,
   14305                         binop( Iop_Or32,
   14306                                binop( Iop_And32,
   14307                                       unop(Iop_64to32, mkexpr( a1_I64 ) ),
   14308                                       mkU32( SIGN_BIT32 ) ),
   14309                                binop( Iop_And32,
   14310                                       unop(Iop_64to32, mkexpr( b1_I64 ) ),
   14311                                       mkU32( SIGN_MASK32 ) ) ),
   14312 
   14313                         binop( Iop_Or32,
   14314                                binop( Iop_And32,
   14315                                       unop(Iop_64to32, mkexpr( a0_I64 ) ),
   14316                                       mkU32( SIGN_BIT32 ) ),
   14317                                binop( Iop_And32,
   14318                                       unop(Iop_64to32, mkexpr( b0_I64 ) ),
   14319                                       mkU32( SIGN_MASK32 ) ) ) ) );
   14320          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
   14321          break;
   14322       }
   14323       case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
   14324       case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
   14325       {
   14326          IRTemp frB = newTemp(Ity_F64);
   14327          IRTemp frB2 = newTemp(Ity_F64);
   14328          IRTemp abs_resultHi = newTemp(Ity_F64);
   14329          IRTemp abs_resultLo = newTemp(Ity_F64);
   14330          Bool make_negative = (opc2 == 0x3D2) ? True : False;
   14331          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14332          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   14333 
   14334          DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB);
   14335          if (make_negative) {
   14336             assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
   14337             assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
   14338 
   14339          } else {
   14340             assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
   14341             assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
   14342          }
   14343          putVSReg( XT, binop( Iop_64HLtoV128,
   14344                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
   14345                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
   14346          break;
   14347       }
   14348       case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
   14349       case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
   14350       {
   14351          /*
   14352           * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
   14353           * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
   14354           * of this function is so easy using shifts, I choose to emulate this instruction that
   14355           * way versus a native instruction method of implementation.
   14356           */
   14357          Bool make_negative = (opc2 == 0x352) ? True : False;
   14358          IRTemp shiftVector = newTemp(Ity_V128);
   14359          IRTemp absVal_vector = newTemp(Ity_V128);
   14360          assign( shiftVector,
   14361                  binop( Iop_64HLtoV128,
   14362                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
   14363                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
   14364          assign( absVal_vector,
   14365                    binop( Iop_Shr32x4,
   14366                           binop( Iop_Shl32x4,
   14367                                  getVSReg( XB ),
   14368                                  mkexpr( shiftVector ) ),
   14369                           mkexpr( shiftVector ) ) );
   14370          if (make_negative) {
   14371             IRTemp signBit_vector = newTemp(Ity_V128);
   14372             assign( signBit_vector,
   14373                     binop( Iop_64HLtoV128,
   14374                            binop( Iop_32HLto64,
   14375                                   mkU32( 0x80000000 ),
   14376                                   mkU32( 0x80000000 ) ),
   14377                            binop( Iop_32HLto64,
   14378                                   mkU32( 0x80000000 ),
   14379                                   mkU32( 0x80000000 ) ) ) );
   14380             putVSReg( XT,
   14381                       binop( Iop_OrV128,
   14382                              mkexpr( absVal_vector ),
   14383                              mkexpr( signBit_vector ) ) );
   14384          } else {
   14385             putVSReg( XT, mkexpr( absVal_vector ) );
   14386          }
   14387          break;
   14388       }
   14389       case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
   14390       {
   14391          IRTemp frB = newTemp(Ity_F64);
   14392          IRTemp frB2 = newTemp(Ity_F64);
   14393          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14394          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   14395          DIP("xvnegdp v%d,v%d\n",  (UInt)XT, (UInt)XB);
   14396          putVSReg( XT,
   14397                    binop( Iop_64HLtoV128,
   14398                           unop( Iop_ReinterpF64asI64,
   14399                                 unop( Iop_NegF64, mkexpr( frB ) ) ),
   14400                           unop( Iop_ReinterpF64asI64,
   14401                                 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
   14402          break;
   14403       }
   14404       case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
   14405       case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
   14406       case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
   14407       case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
   14408       case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
   14409       {
   14410          IRTemp frBHi_I64 = newTemp(Ity_I64);
   14411          IRTemp frBLo_I64 = newTemp(Ity_I64);
   14412          IRExpr * frD_fp_roundHi = NULL;
   14413          IRExpr * frD_fp_roundLo = NULL;
   14414 
   14415          assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   14416          frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
   14417          assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
   14418          frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
   14419 
   14420          DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB);
   14421          putVSReg( XT,
   14422                    binop( Iop_64HLtoV128,
   14423                           unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
   14424                           unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
   14425          break;
   14426       }
   14427       case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
   14428       case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
   14429       case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
   14430       case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
   14431       case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
   14432       {
   14433          const HChar * insn_suffix = NULL;
   14434          IROp op;
   14435          if (opc2 != 0x156) {
   14436             // Use pre-defined IRop's for vrfi{m|n|p|z}
   14437             switch (opc2) {
   14438                case 0x112:
   14439                   insn_suffix = "";
   14440                   op = Iop_RoundF32x4_RN;
   14441                   break;
   14442                case 0x172:
   14443                   insn_suffix = "m";
   14444                   op = Iop_RoundF32x4_RM;
   14445                   break;
   14446                case 0x152:
   14447                   insn_suffix = "p";
   14448                   op = Iop_RoundF32x4_RP;
   14449                   break;
   14450                case 0x132:
   14451                   insn_suffix = "z";
   14452                   op = Iop_RoundF32x4_RZ;
   14453                   break;
   14454 
   14455                default:
   14456                   vex_printf("Unrecognized opcode %x\n", opc2);
   14457                   vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
   14458             }
   14459             DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
   14460             putVSReg( XT, unop( op, getVSReg(XB) ) );
   14461          } else {
   14462             // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
   14463             IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
   14464             IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
   14465             IRTemp b3_I64 = newTemp(Ity_I64);
   14466             IRTemp b2_I64 = newTemp(Ity_I64);
   14467             IRTemp b1_I64 = newTemp(Ity_I64);
   14468             IRTemp b0_I64 = newTemp(Ity_I64);
   14469 
   14470             b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
   14471             frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
   14472             breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
   14473             assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
   14474             assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
   14475             assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
   14476             assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
   14477             frD_fp_roundb3 = unop(Iop_TruncF64asF32,
   14478                                   _do_vsx_fp_roundToInt(b3_I64, opc2));
   14479             frD_fp_roundb2 = unop(Iop_TruncF64asF32,
   14480                                   _do_vsx_fp_roundToInt(b2_I64, opc2));
   14481             frD_fp_roundb1 = unop(Iop_TruncF64asF32,
   14482                                   _do_vsx_fp_roundToInt(b1_I64, opc2));
   14483             frD_fp_roundb0 = unop(Iop_TruncF64asF32,
   14484                                   _do_vsx_fp_roundToInt(b0_I64, opc2));
   14485             DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB);
   14486             putVSReg( XT,
   14487                       binop( Iop_64HLtoV128,
   14488                              binop( Iop_32HLto64,
   14489                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
   14490                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
   14491                              binop( Iop_32HLto64,
   14492                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
   14493                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
   14494          }
   14495          break;
   14496       }
   14497 
   14498       default:
   14499          vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
   14500          return False;
   14501    }
   14502    return True;
   14503 }
   14504 
   14505 
   14506 /*
   14507  * VSX Scalar Floating Point Arithmetic Instructions
   14508  */
   14509 static Bool
   14510 dis_vxs_arith ( UInt theInstr, UInt opc2 )
   14511 {
   14512    /* XX3-Form */
   14513    UChar opc1 = ifieldOPC( theInstr );
   14514    UChar XT = ifieldRegXT( theInstr );
   14515    UChar XA = ifieldRegXA( theInstr );
   14516    UChar XB = ifieldRegXB( theInstr );
   14517    IRExpr* rm = get_IR_roundingmode();
   14518    IRTemp frA = newTemp(Ity_F64);
   14519    IRTemp frB = newTemp(Ity_F64);
   14520 
   14521    if (opc1 != 0x3C) {
   14522       vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
   14523       return False;
   14524    }
   14525 
   14526    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   14527    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14528 
   14529    /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
   14530     * of VSX[XT] are undefined after the operation; therefore, we can simply set
   14531     * element to zero where it makes sense to do so.
   14532     */
   14533    switch (opc2) {
   14534       case 0x000: // xsaddsp  (VSX Scalar Add Single-Precision)
   14535          DIP("xsaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14536          putVSReg( XT, binop( Iop_64HLtoV128,
   14537                               unop( Iop_ReinterpF64asI64,
   14538                                     binop( Iop_RoundF64toF32, rm,
   14539                                            triop( Iop_AddF64, rm,
   14540                                                   mkexpr( frA ),
   14541                                                   mkexpr( frB ) ) ) ),
   14542                               mkU64( 0 ) ) );
   14543          break;
   14544       case 0x020: // xssubsp  (VSX Scalar Subtract Single-Precision)
   14545          DIP("xssubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14546          putVSReg( XT, binop( Iop_64HLtoV128,
   14547                               unop( Iop_ReinterpF64asI64,
   14548                                     binop( Iop_RoundF64toF32, rm,
   14549                                            triop( Iop_SubF64, rm,
   14550                                                   mkexpr( frA ),
   14551                                                   mkexpr( frB ) ) ) ),
   14552                               mkU64( 0 ) ) );
   14553          break;
   14554       case 0x080: // xsadddp (VSX scalar add double-precision)
   14555          DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14556          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14557                                                     triop( Iop_AddF64, rm,
   14558                                                            mkexpr( frA ),
   14559                                                            mkexpr( frB ) ) ),
   14560                               mkU64( 0 ) ) );
   14561          break;
   14562       case 0x060: // xsdivsp (VSX scalar divide single-precision)
   14563          DIP("xsdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14564          putVSReg( XT, binop( Iop_64HLtoV128,
   14565                               unop( Iop_ReinterpF64asI64,
   14566                                     binop( Iop_RoundF64toF32, rm,
   14567                                            triop( Iop_DivF64, rm,
   14568                                                   mkexpr( frA ),
   14569                                                   mkexpr( frB ) ) ) ),
   14570                                mkU64( 0 ) ) );
   14571          break;
   14572       case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
   14573          DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14574          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14575                                                     triop( Iop_DivF64, rm,
   14576                                                            mkexpr( frA ),
   14577                                                            mkexpr( frB ) ) ),
   14578                               mkU64( 0 ) ) );
   14579          break;
   14580       case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
   14581                                * single-precision)
   14582                                */
   14583       {
   14584          IRTemp frT = newTemp(Ity_F64);
   14585          Bool mdp = opc2 == 0x024;
   14586          DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14587          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14588                                                         getVSReg( XT ) ) ) );
   14589          putVSReg( XT,
   14590                    binop( Iop_64HLtoV128,
   14591                           unop( Iop_ReinterpF64asI64,
   14592                                 binop( Iop_RoundF64toF32, rm,
   14593                                        qop( Iop_MAddF64, rm,
   14594                                             mkexpr( frA ),
   14595                                             mkexpr( mdp ? frT : frB ),
   14596                                             mkexpr( mdp ? frB : frT ) ) ) ),
   14597                           mkU64( 0 ) ) );
   14598          break;
   14599       }
   14600       case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
   14601       {
   14602          IRTemp frT = newTemp(Ity_F64);
   14603          Bool mdp = opc2 == 0x0A4;
   14604          DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14605          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14606                                                         getVSReg( XT ) ) ) );
   14607          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14608                                                     qop( Iop_MAddF64, rm,
   14609                                                          mkexpr( frA ),
   14610                                                          mkexpr( mdp ? frT : frB ),
   14611                                                          mkexpr( mdp ? frB : frT ) ) ),
   14612                               mkU64( 0 ) ) );
   14613          break;
   14614       }
   14615       case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
   14616                                * multiply-subtract single-precision)
   14617 			       */
   14618       {
   14619          IRTemp frT = newTemp(Ity_F64);
   14620          Bool mdp = opc2 == 0x064;
   14621          DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14622          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14623                                                         getVSReg( XT ) ) ) );
   14624          putVSReg( XT,
   14625                    binop( Iop_64HLtoV128,
   14626                           unop( Iop_ReinterpF64asI64,
   14627                                 binop( Iop_RoundF64toF32, rm,
   14628                                        qop( Iop_MSubF64, rm,
   14629                                             mkexpr( frA ),
   14630                                             mkexpr( mdp ? frT : frB ),
   14631                                             mkexpr( mdp ? frB : frT ) ) ) ),
   14632                           mkU64( 0 ) ) );
   14633          break;
   14634       }
   14635       case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
   14636       {
   14637          IRTemp frT = newTemp(Ity_F64);
   14638          Bool mdp = opc2 == 0x0E4;
   14639          DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14640          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14641                                                         getVSReg( XT ) ) ) );
   14642          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14643                                                     qop( Iop_MSubF64, rm,
   14644                                                          mkexpr( frA ),
   14645                                                          mkexpr( mdp ? frT : frB ),
   14646                                                          mkexpr( mdp ? frB : frT ) ) ),
   14647                               mkU64( 0 ) ) );
   14648          break;
   14649       }
   14650       case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
   14651       {
   14652          /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
   14653           * of fnmadd and use pretty much the same code. However, that code has a bug in the
   14654           * way it blindly negates the signbit, even if the floating point result is a NaN.
   14655           * So, the TODO is to fix fnmadd (which I'll do in a different patch).
   14656           * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
   14657           * bit for NaN result.
   14658           */
   14659          Bool mdp = opc2 == 0x2A4;
   14660          IRTemp frT = newTemp(Ity_F64);
   14661          IRTemp maddResult = newTemp(Ity_I64);
   14662 
   14663          DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14664          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14665                                                         getVSReg( XT ) ) ) );
   14666          assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
   14667                                                               mkexpr( frA ),
   14668                                                               mkexpr( mdp ? frT : frB ),
   14669                                                               mkexpr( mdp ? frB : frT ) ) ) );
   14670 
   14671          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
   14672                               mkU64( 0 ) ) );
   14673          break;
   14674       }
   14675       case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
   14676                                * multiply-add single-precision)
   14677                                */
   14678       {
   14679          Bool mdp = opc2 == 0x224;
   14680          IRTemp frT = newTemp(Ity_F64);
   14681          IRTemp maddResult = newTemp(Ity_I64);
   14682 
   14683          DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14684          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14685                                                         getVSReg( XT ) ) ) );
   14686          assign( maddResult,
   14687                  unop( Iop_ReinterpF64asI64,
   14688                        binop( Iop_RoundF64toF32, rm,
   14689                               qop( Iop_MAddF64, rm,
   14690                                    mkexpr( frA ),
   14691                                    mkexpr( mdp ? frT : frB ),
   14692                                    mkexpr( mdp ? frB : frT ) ) ) ) );
   14693 
   14694          putVSReg( XT, binop( Iop_64HLtoV128,
   14695                               mkexpr( getNegatedResult(maddResult) ),
   14696                               mkU64( 0 ) ) );
   14697          break;
   14698       }
   14699       case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
   14700                                * Multiply-Subtract Single-Precision)
   14701                                */
   14702       {
   14703          IRTemp frT = newTemp(Ity_F64);
   14704          Bool mdp = opc2 == 0x264;
   14705          IRTemp msubResult = newTemp(Ity_I64);
   14706 
   14707          DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14708          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14709                                                         getVSReg( XT ) ) ) );
   14710          assign( msubResult,
   14711                  unop( Iop_ReinterpF64asI64,
   14712                        binop( Iop_RoundF64toF32, rm,
   14713                               qop( Iop_MSubF64, rm,
   14714                                    mkexpr( frA ),
   14715                                    mkexpr( mdp ? frT : frB ),
   14716                                    mkexpr( mdp ? frB : frT ) ) ) ) );
   14717 
   14718          putVSReg( XT, binop( Iop_64HLtoV128,
   14719                               mkexpr( getNegatedResult(msubResult) ),
   14720                               mkU64( 0 ) ) );
   14721 
   14722          break;
   14723       }
   14724 
   14725       case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
   14726       {
   14727          IRTemp frT = newTemp(Ity_F64);
   14728          Bool mdp = opc2 == 0x2E4;
   14729          IRTemp msubResult = newTemp(Ity_I64);
   14730 
   14731          DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14732          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14733                                                         getVSReg( XT ) ) ) );
   14734          assign(msubResult, unop( Iop_ReinterpF64asI64,
   14735                                       qop( Iop_MSubF64,
   14736                                            rm,
   14737                                            mkexpr( frA ),
   14738                                            mkexpr( mdp ? frT : frB ),
   14739                                            mkexpr( mdp ? frB : frT ) ) ));
   14740 
   14741          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
   14742 
   14743          break;
   14744       }
   14745 
   14746       case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
   14747          DIP("xsmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14748          putVSReg( XT, binop( Iop_64HLtoV128,
   14749                               unop( Iop_ReinterpF64asI64,
   14750                                     binop( Iop_RoundF64toF32, rm,
   14751                                            triop( Iop_MulF64, rm,
   14752                                                    mkexpr( frA ),
   14753                                                    mkexpr( frB ) ) ) ),
   14754                               mkU64( 0 ) ) );
   14755          break;
   14756 
   14757       case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
   14758          DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14759          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14760                                                     triop( Iop_MulF64, rm,
   14761                                                            mkexpr( frA ),
   14762                                                            mkexpr( frB ) ) ),
   14763                               mkU64( 0 ) ) );
   14764          break;
   14765       case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
   14766          DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14767          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14768                                                     triop( Iop_SubF64, rm,
   14769                                                            mkexpr( frA ),
   14770                                                            mkexpr( frB ) ) ),
   14771                               mkU64( 0 ) ) );
   14772          break;
   14773 
   14774       case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
   14775          DIP("xssqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
   14776          putVSReg( XT,
   14777                    binop( Iop_64HLtoV128,
   14778                           unop( Iop_ReinterpF64asI64,
   14779                                 binop( Iop_RoundF64toF32, rm,
   14780                                        binop( Iop_SqrtF64, rm,
   14781                                               mkexpr( frB ) ) ) ),
   14782                           mkU64( 0 ) ) );
   14783          break;
   14784 
   14785       case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
   14786          DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   14787          putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14788                                                      binop( Iop_SqrtF64, rm,
   14789                                                             mkexpr( frB ) ) ),
   14790                                mkU64( 0 ) ) );
   14791          break;
   14792 
   14793       case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
   14794       {
   14795          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   14796          IRTemp frA_I64 = newTemp(Ity_I64);
   14797          IRTemp frB_I64 = newTemp(Ity_I64);
   14798          DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB);
   14799          assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
   14800          assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
   14801          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
   14802          break;
   14803       }
   14804       case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   14805       {
   14806          IRTemp frB_I64 = newTemp(Ity_I64);
   14807          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   14808          IRTemp flags = newTemp(Ity_I32);
   14809          IRTemp  fe_flag, fg_flag;
   14810          fe_flag = fg_flag = IRTemp_INVALID;
   14811          DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   14812          assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   14813          do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
   14814          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   14815           * where fl_flag == 1 on ppc64.
   14816           */
   14817          assign( flags,
   14818                  binop( Iop_Or32,
   14819                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   14820                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   14821                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
   14822          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
   14823          break;
   14824       }
   14825 
   14826       default:
   14827          vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
   14828          return False;
   14829    }
   14830 
   14831    return True;
   14832 }
   14833 
   14834 
   14835 /*
   14836  * VSX Floating Point Compare Instructions
   14837  */
   14838 static Bool
   14839 dis_vx_cmp( UInt theInstr, UInt opc2 )
   14840 {
   14841    /* XX3-Form and XX2-Form */
   14842    UChar opc1 = ifieldOPC( theInstr );
   14843    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   14844    IRTemp ccPPC32;
   14845    UChar XA       = ifieldRegXA ( theInstr );
   14846    UChar XB       = ifieldRegXB ( theInstr );
   14847    IRTemp frA     = newTemp(Ity_F64);
   14848    IRTemp frB     = newTemp(Ity_F64);
   14849 
   14850    if (opc1 != 0x3C) {
   14851       vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
   14852       return False;
   14853    }
   14854 
   14855    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   14856    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14857    switch (opc2) {
   14858       case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   14859          /* Note: Differences between xscmpudp and xscmpodp are only in
   14860           * exception flag settings, which aren't supported anyway. */
   14861          DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
   14862                                            crfD, (UInt)XA, (UInt)XB);
   14863          ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
   14864          putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   14865          break;
   14866 
   14867       default:
   14868          vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
   14869          return False;
   14870    }
   14871    return True;
   14872 }
   14873 
   14874 static void
   14875 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
   14876                  ppc_cmp_t cmp_type )
   14877 {
   14878    IRTemp frA_hi     = newTemp(Ity_F64);
   14879    IRTemp frB_hi     = newTemp(Ity_F64);
   14880    IRTemp frA_lo     = newTemp(Ity_F64);
   14881    IRTemp frB_lo     = newTemp(Ity_F64);
   14882    IRTemp ccPPC32    = newTemp(Ity_I32);
   14883    IRTemp ccIR_hi;
   14884    IRTemp ccIR_lo;
   14885 
   14886    IRTemp hiResult = newTemp(Ity_I64);
   14887    IRTemp loResult = newTemp(Ity_I64);
   14888    IRTemp hiEQlo = newTemp(Ity_I1);
   14889    IRTemp all_elem_true = newTemp(Ity_I32);
   14890    IRTemp all_elem_false = newTemp(Ity_I32);
   14891 
   14892    assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
   14893    assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
   14894    assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
   14895    assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
   14896 
   14897    ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   14898                                        mkexpr( frA_hi ),
   14899                                        mkexpr( frB_hi ) ) );
   14900    ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   14901                                        mkexpr( frA_lo ),
   14902                                        mkexpr( frB_lo ) ) );
   14903 
   14904    if (cmp_type != PPC_CMP_GE) {
   14905       assign( hiResult,
   14906               unop( Iop_1Sto64,
   14907                     binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
   14908       assign( loResult,
   14909               unop( Iop_1Sto64,
   14910                     binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
   14911    } else {
   14912       // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
   14913       // the other element compare may return "2" (for "equal to").
   14914       IRTemp lo_GE = newTemp(Ity_I1);
   14915       IRTemp hi_GE = newTemp(Ity_I1);
   14916 
   14917       assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
   14918                            binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
   14919       assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
   14920 
   14921       assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
   14922                            binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
   14923       assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
   14924    }
   14925 
   14926    // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
   14927    assign( hiEQlo,
   14928            binop( Iop_CmpEQ32,
   14929                   unop( Iop_64to32, mkexpr( hiResult ) ),
   14930                   unop( Iop_64to32, mkexpr( loResult ) ) ) );
   14931    putVSReg( XT,
   14932              binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   14933 
   14934    assign( all_elem_true,
   14935            unop( Iop_1Uto32,
   14936                  mkAND1( mkexpr( hiEQlo ),
   14937                          binop( Iop_CmpEQ32,
   14938                                 mkU32( 0xffffffff ),
   14939                                 unop( Iop_64to32,
   14940                                 mkexpr( hiResult ) ) ) ) ) );
   14941 
   14942    assign( all_elem_false,
   14943            unop( Iop_1Uto32,
   14944                  mkAND1( mkexpr( hiEQlo ),
   14945                          binop( Iop_CmpEQ32,
   14946                                 mkU32( 0 ),
   14947                                 unop( Iop_64to32,
   14948                                 mkexpr( hiResult ) ) ) ) ) );
   14949    assign( ccPPC32,
   14950            binop( Iop_Or32,
   14951                   binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
   14952                   binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
   14953 
   14954    if (flag_rC) {
   14955       putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
   14956    }
   14957 }
   14958 
   14959 /*
   14960  * VSX Vector Compare Instructions
   14961  */
   14962 static Bool
   14963 dis_vvec_cmp( UInt theInstr, UInt opc2 )
   14964 {
   14965    /* XX3-Form */
   14966    UChar opc1 = ifieldOPC( theInstr );
   14967    UChar XT = ifieldRegXT ( theInstr );
   14968    UChar XA = ifieldRegXA ( theInstr );
   14969    UChar XB = ifieldRegXB ( theInstr );
   14970    UChar flag_rC  = ifieldBIT10(theInstr);
   14971    IRTemp vA = newTemp( Ity_V128 );
   14972    IRTemp vB = newTemp( Ity_V128 );
   14973 
   14974    if (opc1 != 0x3C) {
   14975       vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
   14976       return False;
   14977    }
   14978 
   14979    assign( vA, getVSReg( XA ) );
   14980    assign( vB, getVSReg( XB ) );
   14981 
   14982    switch (opc2) {
   14983       case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
   14984       {
   14985          DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   14986              (UInt)XT, (UInt)XA, (UInt)XB);
   14987          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
   14988          break;
   14989       }
   14990 
   14991       case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
   14992       {
   14993          DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   14994              (UInt)XT, (UInt)XA, (UInt)XB);
   14995          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
   14996          break;
   14997       }
   14998 
   14999       case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
   15000       {
   15001          DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   15002              (UInt)XT, (UInt)XA, (UInt)XB);
   15003          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
   15004          break;
   15005       }
   15006 
   15007       case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
   15008       {
   15009          IRTemp vD = newTemp(Ity_V128);
   15010 
   15011          DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   15012              (UInt)XT, (UInt)XA, (UInt)XB);
   15013          assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   15014          putVSReg( XT, mkexpr(vD) );
   15015          if (flag_rC) {
   15016             set_AV_CR6( mkexpr(vD), True );
   15017          }
   15018          break;
   15019       }
   15020 
   15021       case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
   15022       {
   15023          IRTemp vD = newTemp(Ity_V128);
   15024 
   15025          DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   15026              (UInt)XT, (UInt)XA, (UInt)XB);
   15027          assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   15028          putVSReg( XT, mkexpr(vD) );
   15029          if (flag_rC) {
   15030             set_AV_CR6( mkexpr(vD), True );
   15031          }
   15032          break;
   15033       }
   15034 
   15035       case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
   15036       {
   15037          IRTemp vD = newTemp(Ity_V128);
   15038 
   15039          DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   15040              (UInt)XT, (UInt)XA, (UInt)XB);
   15041          assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   15042          putVSReg( XT, mkexpr(vD) );
   15043          if (flag_rC) {
   15044             set_AV_CR6( mkexpr(vD), True );
   15045          }
   15046          break;
   15047       }
   15048 
   15049       default:
   15050          vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
   15051          return False;
   15052    }
   15053    return True;
   15054 }
   15055 /*
   15056  * Miscellaneous VSX Scalar Instructions
   15057  */
   15058 static Bool
   15059 dis_vxs_misc( UInt theInstr, UInt opc2 )
   15060 {
   15061 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
   15062    /* XX3-Form and XX2-Form */
   15063    UChar opc1 = ifieldOPC( theInstr );
   15064    UChar XT = ifieldRegXT ( theInstr );
   15065    UChar XA = ifieldRegXA ( theInstr );
   15066    UChar XB = ifieldRegXB ( theInstr );
   15067    IRTemp vA = newTemp( Ity_V128 );
   15068    IRTemp vB = newTemp( Ity_V128 );
   15069 
   15070    if (opc1 != 0x3C) {
   15071       vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
   15072       return False;
   15073    }
   15074 
   15075    assign( vA, getVSReg( XA ) );
   15076    assign( vB, getVSReg( XB ) );
   15077 
   15078    /* For all the VSX move instructions, the contents of doubleword element 1
   15079     * of VSX[XT] are undefined after the operation; therefore, we can simply
   15080     * move the entire array element where it makes sense to do so.
   15081     */
   15082 
   15083    switch (opc2) {
   15084       case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
   15085       {
   15086          /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
   15087          IRTemp absVal = newTemp(Ity_V128);
   15088          if (host_endness == VexEndnessLE) {
   15089             IRTemp hi64 = newTemp(Ity_I64);
   15090             IRTemp lo64 = newTemp(Ity_I64);
   15091             assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) );
   15092             assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) );
   15093             assign( absVal, binop( Iop_64HLtoV128,
   15094                                    binop( Iop_And64, mkexpr(hi64),
   15095                                           mkU64(VG_PPC_SIGN_MASK) ),
   15096                                    mkexpr(lo64) ) );
   15097          } else {
   15098             assign(absVal, binop(Iop_ShrV128,
   15099                                  binop(Iop_ShlV128, mkexpr(vB),
   15100                                        mkU8(1)), mkU8(1)));
   15101          }
   15102          DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   15103          putVSReg(XT, mkexpr(absVal));
   15104          break;
   15105       }
   15106       case 0x2C0: // xscpsgndp
   15107       {
   15108          /* Scalar copy sign double-precision */
   15109          IRTemp vecA_signed = newTemp(Ity_I64);
   15110          IRTemp vecB_unsigned = newTemp(Ity_I64);
   15111          IRTemp vec_result = newTemp(Ity_V128);
   15112          DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15113          assign( vecA_signed, binop( Iop_And64,
   15114                                      unop( Iop_V128HIto64,
   15115                                            mkexpr(vA)),
   15116                                            mkU64(~VG_PPC_SIGN_MASK) ) );
   15117          assign( vecB_unsigned, binop( Iop_And64,
   15118                                        unop( Iop_V128HIto64,
   15119                                              mkexpr(vB) ),
   15120                                              mkU64(VG_PPC_SIGN_MASK) ) );
   15121          assign( vec_result, binop( Iop_64HLtoV128,
   15122                                     binop( Iop_Or64,
   15123                                            mkexpr(vecA_signed),
   15124                                            mkexpr(vecB_unsigned) ),
   15125                                     mkU64(0x0ULL)));
   15126          putVSReg(XT, mkexpr(vec_result));
   15127          break;
   15128       }
   15129       case 0x2D2: // xsnabsdp
   15130       {
   15131          /* Scalar negative absolute value double-precision */
   15132          IRTemp BHi_signed = newTemp(Ity_I64);
   15133          DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   15134          assign( BHi_signed, binop( Iop_Or64,
   15135                                     unop( Iop_V128HIto64,
   15136                                           mkexpr(vB) ),
   15137                                           mkU64(~VG_PPC_SIGN_MASK) ) );
   15138          putVSReg(XT, binop( Iop_64HLtoV128,
   15139                              mkexpr(BHi_signed), mkU64(0x0ULL) ) );
   15140          break;
   15141       }
   15142       case 0x2F2: // xsnegdp
   15143       {
   15144          /* Scalar negate double-precision */
   15145          IRTemp BHi_signed = newTemp(Ity_I64);
   15146          IRTemp BHi_unsigned = newTemp(Ity_I64);
   15147          IRTemp BHi_negated = newTemp(Ity_I64);
   15148          IRTemp BHi_negated_signbit = newTemp(Ity_I1);
   15149          IRTemp vec_result = newTemp(Ity_V128);
   15150          DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   15151          assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) );
   15152          assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed),
   15153                                       mkU64(VG_PPC_SIGN_MASK) ) );
   15154          assign( BHi_negated_signbit,
   15155                  unop( Iop_Not1,
   15156                        unop( Iop_32to1,
   15157                              binop( Iop_Shr32,
   15158                                     unop( Iop_64HIto32,
   15159                                           binop( Iop_And64,
   15160                                                  mkexpr(BHi_signed),
   15161                                                  mkU64(~VG_PPC_SIGN_MASK) )
   15162                                           ),
   15163                                     mkU8(31) ) ) ) );
   15164          assign( BHi_negated,
   15165                  binop( Iop_Or64,
   15166                         binop( Iop_32HLto64,
   15167                                binop( Iop_Shl32,
   15168                                       unop( Iop_1Uto32,
   15169                                             mkexpr(BHi_negated_signbit) ),
   15170                                       mkU8(31) ),
   15171                                mkU32(0) ),
   15172                         mkexpr(BHi_unsigned) ) );
   15173          assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
   15174                                     mkU64(0x0ULL)));
   15175          putVSReg( XT, mkexpr(vec_result));
   15176          break;
   15177       }
   15178       case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
   15179       case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
   15180       {
   15181          IRTemp frA     = newTemp(Ity_I64);
   15182          IRTemp frB     = newTemp(Ity_I64);
   15183          Bool isMin = opc2 == 0x2A0 ? True : False;
   15184          DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB);
   15185 
   15186          assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
   15187          assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
   15188          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
   15189 
   15190          break;
   15191       }
   15192       case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
   15193       case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
   15194       case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
   15195       case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
   15196       case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
   15197       {
   15198          IRTemp frB_I64 = newTemp(Ity_I64);
   15199          IRExpr * frD_fp_round = NULL;
   15200 
   15201          assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
   15202          frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
   15203 
   15204          DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB);
   15205          putVSReg( XT,
   15206                    binop( Iop_64HLtoV128,
   15207                           unop( Iop_ReinterpF64asI64, frD_fp_round),
   15208                           mkU64( 0 ) ) );
   15209          break;
   15210       }
   15211       case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
   15212       case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
   15213                    * single-Precision)
   15214                    */
   15215       {
   15216          IRTemp frB = newTemp(Ity_F64);
   15217          IRTemp sqrt = newTemp(Ity_F64);
   15218          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   15219          IRExpr* rm  = get_IR_roundingmode();
   15220          Bool redp = opc2 == 0x034;
   15221          DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", (UInt)XT,
   15222              (UInt)XB);
   15223 
   15224          assign( frB,
   15225                  unop( Iop_ReinterpI64asF64,
   15226                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   15227 
   15228          if (!redp)
   15229             assign( sqrt,
   15230                     binop( Iop_SqrtF64,
   15231                            rm,
   15232                            mkexpr(frB) ) );
   15233          putVSReg( XT,
   15234                       binop( Iop_64HLtoV128,
   15235                              unop( Iop_ReinterpF64asI64,
   15236                                    binop( Iop_RoundF64toF32, rm,
   15237                                           triop( Iop_DivF64,
   15238                                                  rm,
   15239                                                  ieee_one,
   15240                                                  redp ? mkexpr( frB ) :
   15241                                                         mkexpr( sqrt ) ) ) ),
   15242                              mkU64( 0 ) ) );
   15243          break;
   15244       }
   15245 
   15246       case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
   15247       case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
   15248 
   15249       {
   15250          IRTemp frB = newTemp(Ity_F64);
   15251          IRTemp sqrt = newTemp(Ity_F64);
   15252          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   15253          IRExpr* rm  = get_IR_roundingmode();
   15254          Bool redp = opc2 == 0x0B4;
   15255          DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB);
   15256          assign( frB,
   15257                  unop( Iop_ReinterpI64asF64,
   15258                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   15259 
   15260          if (!redp)
   15261             assign( sqrt,
   15262                     binop( Iop_SqrtF64,
   15263                            rm,
   15264                            mkexpr(frB) ) );
   15265          putVSReg( XT,
   15266                       binop( Iop_64HLtoV128,
   15267                              unop( Iop_ReinterpF64asI64,
   15268                                    triop( Iop_DivF64,
   15269                                           rm,
   15270                                           ieee_one,
   15271                                           redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
   15272                              mkU64( 0 ) ) );
   15273          break;
   15274       }
   15275 
   15276       case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
   15277       {
   15278          IRTemp frB = newTemp(Ity_F64);
   15279          IRExpr* rm  = get_IR_roundingmode();
   15280          DIP("xsrsp v%d, v%d\n", (UInt)XT, (UInt)XB);
   15281          assign( frB,
   15282                  unop( Iop_ReinterpI64asF64,
   15283                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   15284 
   15285          putVSReg( XT, binop( Iop_64HLtoV128,
   15286                               unop( Iop_ReinterpF64asI64,
   15287                                     binop( Iop_RoundF64toF32,
   15288                                            rm,
   15289                                            mkexpr( frB ) ) ),
   15290                               mkU64( 0 ) ) );
   15291          break;
   15292       }
   15293 
   15294       default:
   15295          vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
   15296          return False;
   15297    }
   15298    return True;
   15299 }
   15300 
   15301 /*
   15302  * VSX Logical Instructions
   15303  */
   15304 static Bool
   15305 dis_vx_logic ( UInt theInstr, UInt opc2 )
   15306 {
   15307    /* XX3-Form */
   15308    UChar opc1 = ifieldOPC( theInstr );
   15309    UChar XT = ifieldRegXT ( theInstr );
   15310    UChar XA = ifieldRegXA ( theInstr );
   15311    UChar XB = ifieldRegXB ( theInstr );
   15312    IRTemp vA = newTemp( Ity_V128 );
   15313    IRTemp vB = newTemp( Ity_V128 );
   15314 
   15315    if (opc1 != 0x3C) {
   15316       vex_printf( "dis_vx_logic(ppc)(instr)\n" );
   15317       return False;
   15318    }
   15319 
   15320    assign( vA, getVSReg( XA ) );
   15321    assign( vB, getVSReg( XB ) );
   15322 
   15323    switch (opc2) {
   15324       case 0x268: // xxlxor
   15325          DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15326          putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
   15327          break;
   15328       case 0x248: // xxlor
   15329          DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15330          putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
   15331          break;
   15332       case 0x288: // xxlnor
   15333          DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15334          putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
   15335                                                  mkexpr( vB ) ) ) );
   15336          break;
   15337       case 0x208: // xxland
   15338          DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15339          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
   15340          break;
   15341       case 0x228: //xxlandc
   15342          DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15343          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
   15344                                                                mkexpr( vB ) ) ) );
   15345          break;
   15346       case 0x2A8: // xxlorc (VSX Logical OR with complement)
   15347          DIP("xxlorc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15348          putVSReg( XT, binop( Iop_OrV128,
   15349                               mkexpr( vA ),
   15350                               unop( Iop_NotV128, mkexpr( vB ) ) ) );
   15351          break;
   15352       case 0x2C8: // xxlnand (VSX Logical NAND)
   15353          DIP("xxlnand v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15354          putVSReg( XT, unop( Iop_NotV128,
   15355                              binop( Iop_AndV128, mkexpr( vA ),
   15356                                     mkexpr( vB ) ) ) );
   15357          break;
   15358       case 0x2E8: // xxleqv (VSX Logical Equivalence)
   15359          DIP("xxleqv v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15360          putVSReg( XT, unop( Iop_NotV128,
   15361                              binop( Iop_XorV128,
   15362                              mkexpr( vA ), mkexpr( vB ) ) ) );
   15363          break;
   15364       default:
   15365          vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
   15366          return False;
   15367    }
   15368    return True;
   15369 }
   15370 
   15371 /*
   15372  * VSX Load Instructions
   15373  * NOTE: VSX supports word-aligned storage access.
   15374  */
   15375 static Bool
   15376 dis_vx_load ( UInt theInstr )
   15377 {
   15378    /* XX1-Form */
   15379    UChar opc1 = ifieldOPC( theInstr );
   15380    UChar XT = ifieldRegXT ( theInstr );
   15381    UChar rA_addr = ifieldRegA( theInstr );
   15382    UChar rB_addr = ifieldRegB( theInstr );
   15383    UInt opc2 = ifieldOPClo10( theInstr );
   15384 
   15385    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   15386    IRTemp EA = newTemp( ty );
   15387 
   15388    if (opc1 != 0x1F) {
   15389       vex_printf( "dis_vx_load(ppc)(instr)\n" );
   15390       return False;
   15391    }
   15392 
   15393    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   15394 
   15395    switch (opc2) {
   15396    case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
   15397    {
   15398       IRExpr * exp;
   15399       DIP("lxsiwzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15400 
   15401       if (host_endness == VexEndnessLE)
   15402          exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
   15403       else
   15404          exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
   15405 
   15406       putVSReg( XT, binop( Iop_64HLtoV128,
   15407                            unop( Iop_32Uto64, exp),
   15408                            mkU64(0) ) );
   15409       break;
   15410    }
   15411    case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
   15412    {
   15413       IRExpr * exp;
   15414       DIP("lxsiwax %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15415 
   15416       if (host_endness == VexEndnessLE)
   15417          exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
   15418       else
   15419          exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
   15420 
   15421       putVSReg( XT, binop( Iop_64HLtoV128,
   15422                            unop( Iop_32Sto64, exp),
   15423                            mkU64(0) ) );
   15424       break;
   15425    }
   15426    case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
   15427    {
   15428       IRExpr * exp;
   15429       DIP("lxsspx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15430       /* Take 32-bit floating point value in the upper half of the fetched
   15431        * 64-bit value, convert to 64-bit floating point value and load into
   15432        * top word of V128.
   15433        */
   15434       exp = unop( Iop_ReinterpF64asI64,
   15435                   unop( Iop_F32toF64,
   15436                         unop( Iop_ReinterpI32asF32,
   15437                               load( Ity_I32, mkexpr( EA ) ) ) ) );
   15438 
   15439       putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
   15440       break;
   15441    }
   15442    case 0x24C: // lxsdx
   15443    {
   15444       IRExpr * exp;
   15445       DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15446       exp = load( Ity_I64, mkexpr( EA ) );
   15447       // We need to pass an expression of type Ity_V128 with putVSReg, but the load
   15448       // we just performed is only a DW.  But since the contents of VSR[XT] element 1
   15449       // are undefined after this operation, we can just do a splat op.
   15450       putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
   15451       break;
   15452    }
   15453    case 0x34C: // lxvd2x
   15454    {
   15455       IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
   15456       IRExpr * high, *low;
   15457       ULong ea_off = 8;
   15458       IRExpr* high_addr;
   15459       DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15460       high = load( Ity_I64, mkexpr( EA ) );
   15461       high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
   15462             : mkU32( ea_off ) );
   15463       low = load( Ity_I64, high_addr );
   15464       putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
   15465       break;
   15466    }
   15467    case 0x14C: // lxvdsx
   15468    {
   15469       IRTemp data = newTemp(Ity_I64);
   15470       DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15471       assign( data, load( Ity_I64, mkexpr( EA ) ) );
   15472       putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
   15473       break;
   15474    }
   15475    case 0x30C:
   15476    {
   15477       IRExpr *t0;
   15478 
   15479       DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15480 
   15481       /* The load will result in the data being in BE order. */
   15482       if (host_endness == VexEndnessLE) {
   15483          IRExpr *t0_BE;
   15484          IRTemp perm_LE = newTemp(Ity_V128);
   15485 
   15486          t0_BE = load( Ity_V128, mkexpr( EA ) );
   15487 
   15488          /*  Permute the data to LE format */
   15489          assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL),
   15490                                  mkU64(0x0405060700010203ULL)));
   15491 
   15492          t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) );
   15493       } else {
   15494          t0 = load( Ity_V128, mkexpr( EA ) );
   15495       }
   15496 
   15497       putVSReg( XT, t0 );
   15498       break;
   15499    }
   15500    default:
   15501       vex_printf( "dis_vx_load(ppc)(opc2)\n" );
   15502       return False;
   15503    }
   15504    return True;
   15505 }
   15506 
   15507 /*
   15508  * VSX Store Instructions
   15509  * NOTE: VSX supports word-aligned storage access.
   15510  */
   15511 static Bool
   15512 dis_vx_store ( UInt theInstr )
   15513 {
   15514    /* XX1-Form */
   15515    UChar opc1 = ifieldOPC( theInstr );
   15516    UChar XS = ifieldRegXS( theInstr );
   15517    UChar rA_addr = ifieldRegA( theInstr );
   15518    UChar rB_addr = ifieldRegB( theInstr );
   15519    IRTemp vS = newTemp( Ity_V128 );
   15520    UInt opc2 = ifieldOPClo10( theInstr );
   15521 
   15522    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   15523    IRTemp EA = newTemp( ty );
   15524 
   15525    if (opc1 != 0x1F) {
   15526       vex_printf( "dis_vx_store(ppc)(instr)\n" );
   15527       return False;
   15528    }
   15529 
   15530    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   15531    assign( vS, getVSReg( XS ) );
   15532 
   15533    switch (opc2) {
   15534    case 0x08C:
   15535    {
   15536      /* Need the next to the most significant 32-bit word from
   15537       * the 128-bit vector.
   15538       */
   15539       IRExpr * high64, * low32;
   15540       DIP("stxsiwx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   15541       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   15542       low32  = unop( Iop_64to32, high64 );
   15543       store( mkexpr( EA ), low32 );
   15544       break;
   15545    }
   15546    case 0x28C:
   15547    {
   15548       IRTemp high64 = newTemp(Ity_F64);
   15549       IRTemp val32  = newTemp(Ity_I32);
   15550       DIP("stxsspx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   15551       assign(high64, unop( Iop_ReinterpI64asF64,
   15552                            unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
   15553       assign(val32, unop( Iop_ReinterpF32asI32,
   15554                           unop( Iop_TruncF64asF32,
   15555                                 mkexpr(high64) ) ) );
   15556       store( mkexpr( EA ), mkexpr( val32 ) );
   15557       break;
   15558    }
   15559    case 0x2CC:
   15560    {
   15561       IRExpr * high64;
   15562       DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   15563       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   15564       store( mkexpr( EA ), high64 );
   15565       break;
   15566    }
   15567    case 0x3CC:
   15568    {
   15569       IRExpr * high64, *low64;
   15570       DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   15571       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   15572       low64 = unop( Iop_V128to64, mkexpr( vS ) );
   15573       store( mkexpr( EA ), high64 );
   15574       store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15575                     ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 );
   15576       break;
   15577    }
   15578    case 0x38C:
   15579    {
   15580       UInt ea_off = 0;
   15581       IRExpr* irx_addr;
   15582       IRTemp hi64 = newTemp( Ity_I64 );
   15583       IRTemp lo64 = newTemp( Ity_I64 );
   15584 
   15585       DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   15586 
   15587       // This instruction supports word-aligned stores, so EA may not be
   15588       // quad-word aligned.  Therefore, do 4 individual word-size stores.
   15589       assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
   15590       assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
   15591       store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
   15592       ea_off += 4;
   15593       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15594                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15595       store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
   15596       ea_off += 4;
   15597       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15598                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15599       store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
   15600       ea_off += 4;
   15601       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15602                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15603       store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
   15604 
   15605       break;
   15606    }
   15607    default:
   15608       vex_printf( "dis_vx_store(ppc)(opc2)\n" );
   15609       return False;
   15610    }
   15611    return True;
   15612 }
   15613 
   15614 /*
   15615  * VSX permute and other miscealleous instructions
   15616  */
   15617 static Bool
   15618 dis_vx_permute_misc( UInt theInstr, UInt opc2 )
   15619 {
   15620    /* XX3-Form */
   15621    UChar opc1 = ifieldOPC( theInstr );
   15622    UChar XT = ifieldRegXT ( theInstr );
   15623    UChar XA = ifieldRegXA ( theInstr );
   15624    UChar XB = ifieldRegXB ( theInstr );
   15625    IRTemp vT = newTemp( Ity_V128 );
   15626    IRTemp vA = newTemp( Ity_V128 );
   15627    IRTemp vB = newTemp( Ity_V128 );
   15628 
   15629    if (opc1 != 0x3C) {
   15630       vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
   15631       return False;
   15632    }
   15633 
   15634    assign( vA, getVSReg( XA ) );
   15635    assign( vB, getVSReg( XB ) );
   15636 
   15637    switch (opc2) {
   15638       case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
   15639       {
   15640          UChar SHW = ifieldSHW ( theInstr );
   15641          IRTemp result = newTemp(Ity_V128);
   15642          if ( SHW != 0 ) {
   15643              IRTemp hi = newTemp(Ity_V128);
   15644              IRTemp lo = newTemp(Ity_V128);
   15645              assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
   15646              assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
   15647              assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
   15648          } else
   15649              assign ( result, mkexpr(vA) );
   15650          DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW);
   15651          putVSReg( XT, mkexpr(result) );
   15652          break;
   15653       }
   15654       case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
   15655       {
   15656          UChar DM = ifieldDM ( theInstr );
   15657          IRTemp hi = newTemp(Ity_I64);
   15658          IRTemp lo = newTemp(Ity_I64);
   15659 
   15660          if (DM & 0x2)
   15661            assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
   15662          else
   15663            assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
   15664 
   15665          if (DM & 0x1)
   15666            assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
   15667          else
   15668            assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
   15669 
   15670          assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
   15671 
   15672          DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM);
   15673          putVSReg( XT, mkexpr( vT ) );
   15674          break;
   15675       }
   15676       case 0x48: // xxmrghw (VSX Merge High Word)
   15677       case 0xc8: // xxmrglw (VSX Merge Low Word)
   15678       {
   15679          const HChar type = (opc2 == 0x48) ? 'h' : 'l';
   15680          IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
   15681          IRTemp a64 = newTemp(Ity_I64);
   15682          IRTemp ahi32 = newTemp(Ity_I32);
   15683          IRTemp alo32 = newTemp(Ity_I32);
   15684          IRTemp b64 = newTemp(Ity_I64);
   15685          IRTemp bhi32 = newTemp(Ity_I32);
   15686          IRTemp blo32 = newTemp(Ity_I32);
   15687 
   15688          assign( a64, unop(word_op, mkexpr(vA)) );
   15689          assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
   15690          assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
   15691 
   15692          assign( b64, unop(word_op, mkexpr(vB)) );
   15693          assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
   15694          assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
   15695 
   15696          assign( vT, binop(Iop_64HLtoV128,
   15697                            binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
   15698                            binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
   15699 
   15700          DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB);
   15701          putVSReg( XT, mkexpr( vT ) );
   15702          break;
   15703       }
   15704       case 0x018: // xxsel (VSX Select)
   15705       {
   15706          UChar XC = ifieldRegXC(theInstr);
   15707          IRTemp vC = newTemp( Ity_V128 );
   15708          assign( vC, getVSReg( XC ) );
   15709          DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC);
   15710          /* vD = (vA & ~vC) | (vB & vC) */
   15711          putVSReg( XT, binop(Iop_OrV128,
   15712             binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   15713             binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   15714          break;
   15715       }
   15716       case 0x148: // xxspltw (VSX Splat Word)
   15717       {
   15718          UChar UIM   = ifieldRegA(theInstr) & 3;
   15719          UChar sh_uim = (3 - (UIM)) * 32;
   15720          DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM);
   15721          putVSReg( XT,
   15722                    unop( Iop_Dup32x4,
   15723                          unop( Iop_V128to32,
   15724                                binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
   15725          break;
   15726       }
   15727 
   15728       default:
   15729          vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
   15730          return False;
   15731    }
   15732    return True;
   15733 }
   15734 
   15735 /*
   15736   AltiVec Load Instructions
   15737 */
   15738 static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr )
   15739 {
   15740    /* X-Form */
   15741    UChar opc1     = ifieldOPC(theInstr);
   15742    UChar vD_addr  = ifieldRegDS(theInstr);
   15743    UChar rA_addr  = ifieldRegA(theInstr);
   15744    UChar rB_addr  = ifieldRegB(theInstr);
   15745    UInt  opc2     = ifieldOPClo10(theInstr);
   15746    UChar b0       = ifieldBIT0(theInstr);
   15747 
   15748    IRType ty         = mode64 ? Ity_I64 : Ity_I32;
   15749    IRTemp EA         = newTemp(ty);
   15750    IRTemp EA_align16 = newTemp(ty);
   15751 
   15752    if (opc1 != 0x1F || b0 != 0) {
   15753       vex_printf("dis_av_load(ppc)(instr)\n");
   15754       return False;
   15755    }
   15756 
   15757    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   15758    assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
   15759 
   15760    switch (opc2) {
   15761 
   15762    case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
   15763       IRDirty* d;
   15764       UInt vD_off = vectorGuestRegOffset(vD_addr);
   15765       IRExpr** args_be = mkIRExprVec_5(
   15766                          IRExpr_BBPTR(),
   15767                          mkU32(vD_off),
   15768                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   15769                                           mkU32(0xF)),
   15770                          mkU32(0)/*left*/,
   15771                          mkU32(1)/*Big Endian*/);
   15772       IRExpr** args_le = mkIRExprVec_5(
   15773                          IRExpr_BBPTR(),
   15774                          mkU32(vD_off),
   15775                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   15776                                           mkU32(0xF)),
   15777                          mkU32(0)/*left*/,
   15778                          mkU32(0)/*Little Endian*/);
   15779       if (!mode64) {
   15780          d = unsafeIRDirty_0_N (
   15781                         0/*regparms*/,
   15782                         "ppc32g_dirtyhelper_LVS",
   15783                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   15784                         args_be );
   15785       } else {
   15786          if (host_endness == VexEndnessBE)
   15787             d = unsafeIRDirty_0_N (
   15788                            0/*regparms*/,
   15789                            "ppc64g_dirtyhelper_LVS",
   15790                            fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   15791                            args_be );
   15792          else
   15793             d = unsafeIRDirty_0_N (
   15794                            0/*regparms*/,
   15795                            "ppc64g_dirtyhelper_LVS",
   15796                            &ppc64g_dirtyhelper_LVS,
   15797                            args_le );
   15798       }
   15799       DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15800       /* declare guest state effects */
   15801       d->nFxState = 1;
   15802       vex_bzero(&d->fxState, sizeof(d->fxState));
   15803       d->fxState[0].fx     = Ifx_Write;
   15804       d->fxState[0].offset = vD_off;
   15805       d->fxState[0].size   = sizeof(U128);
   15806 
   15807       /* execute the dirty call, side-effecting guest state */
   15808       stmt( IRStmt_Dirty(d) );
   15809       break;
   15810    }
   15811    case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
   15812       IRDirty* d;
   15813       UInt vD_off = vectorGuestRegOffset(vD_addr);
   15814       IRExpr** args_be = mkIRExprVec_5(
   15815                              IRExpr_BBPTR(),
   15816                              mkU32(vD_off),
   15817                              binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   15818                                               mkU32(0xF)),
   15819                              mkU32(1)/*right*/,
   15820                              mkU32(1)/*Big Endian*/);
   15821       IRExpr** args_le = mkIRExprVec_5(
   15822                              IRExpr_BBPTR(),
   15823                              mkU32(vD_off),
   15824                              binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   15825                                               mkU32(0xF)),
   15826                              mkU32(1)/*right*/,
   15827                              mkU32(0)/*Little Endian*/);
   15828 
   15829       if (!mode64) {
   15830          d = unsafeIRDirty_0_N (
   15831                         0/*regparms*/,
   15832                         "ppc32g_dirtyhelper_LVS",
   15833                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   15834                         args_be );
   15835       } else {
   15836          if (host_endness == VexEndnessBE)
   15837             d = unsafeIRDirty_0_N (
   15838                            0/*regparms*/,
   15839                            "ppc64g_dirtyhelper_LVS",
   15840                            fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   15841                            args_be );
   15842          else
   15843             d = unsafeIRDirty_0_N (
   15844                            0/*regparms*/,
   15845                            "ppc64g_dirtyhelper_LVS",
   15846                            &ppc64g_dirtyhelper_LVS,
   15847                            args_le );
   15848       }
   15849       DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15850       /* declare guest state effects */
   15851       d->nFxState = 1;
   15852       vex_bzero(&d->fxState, sizeof(d->fxState));
   15853       d->fxState[0].fx     = Ifx_Write;
   15854       d->fxState[0].offset = vD_off;
   15855       d->fxState[0].size   = sizeof(U128);
   15856 
   15857       /* execute the dirty call, side-effecting guest state */
   15858       stmt( IRStmt_Dirty(d) );
   15859       break;
   15860    }
   15861    case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
   15862       DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15863       /* loads addressed byte into vector[EA[0:3]
   15864          since all other destination bytes are undefined,
   15865          can simply load entire vector from 16-aligned EA */
   15866       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   15867       break;
   15868 
   15869    case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
   15870       DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15871       /* see note for lvebx */
   15872       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   15873       break;
   15874 
   15875    case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
   15876       DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15877       /* see note for lvebx */
   15878       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   15879       break;
   15880 
   15881    case 0x067: // lvx (Load Vector Indexed, AV p127)
   15882       DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15883       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   15884       break;
   15885 
   15886    case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
   15887       DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15888       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   15889       break;
   15890 
   15891    default:
   15892       vex_printf("dis_av_load(ppc)(opc2)\n");
   15893       return False;
   15894    }
   15895    return True;
   15896 }
   15897 
   15898 /*
   15899   AltiVec Store Instructions
   15900 */
   15901 static Bool dis_av_store ( UInt theInstr )
   15902 {
   15903    /* X-Form */
   15904    UChar opc1     = ifieldOPC(theInstr);
   15905    UChar vS_addr  = ifieldRegDS(theInstr);
   15906    UChar rA_addr  = ifieldRegA(theInstr);
   15907    UChar rB_addr  = ifieldRegB(theInstr);
   15908    UInt  opc2     = ifieldOPClo10(theInstr);
   15909    UChar b0       = ifieldBIT0(theInstr);
   15910 
   15911    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   15912    IRTemp EA           = newTemp(ty);
   15913    IRTemp addr_aligned = newTemp(ty);
   15914    IRTemp vS           = newTemp(Ity_V128);
   15915    IRTemp eb           = newTemp(Ity_I8);
   15916    IRTemp idx          = newTemp(Ity_I8);
   15917 
   15918    if (opc1 != 0x1F || b0 != 0) {
   15919       vex_printf("dis_av_store(ppc)(instr)\n");
   15920       return False;
   15921    }
   15922 
   15923    assign( vS, getVReg(vS_addr));
   15924    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   15925 
   15926    switch (opc2) {
   15927    case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
   15928       DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   15929       assign( eb, binop(Iop_And8, mkU8(0xF),
   15930                         unop(Iop_32to8,
   15931                              mkNarrowTo32(ty, mkexpr(EA)) )) );
   15932      if (host_endness == VexEndnessLE) {
   15933          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
   15934       } else {
   15935          assign( idx, binop(Iop_Shl8,
   15936                             binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
   15937                             mkU8(3)) );
   15938       }
   15939       store( mkexpr(EA),
   15940              unop( Iop_32to8, unop(Iop_V128to32,
   15941                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   15942       break;
   15943    }
   15944    case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
   15945       DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   15946       assign( addr_aligned, addr_align(mkexpr(EA), 2) );
   15947       assign( eb, binop(Iop_And8, mkU8(0xF),
   15948                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   15949       if (host_endness == VexEndnessLE) {
   15950           assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
   15951       } else {
   15952          assign( idx, binop(Iop_Shl8,
   15953                             binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
   15954                             mkU8(3)) );
   15955       }
   15956       store( mkexpr(addr_aligned),
   15957              unop( Iop_32to16, unop(Iop_V128to32,
   15958                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   15959       break;
   15960    }
   15961    case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
   15962       DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   15963       assign( addr_aligned, addr_align(mkexpr(EA), 4) );
   15964       assign( eb, binop(Iop_And8, mkU8(0xF),
   15965                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   15966       if (host_endness == VexEndnessLE) {
   15967          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
   15968       } else {
   15969          assign( idx, binop(Iop_Shl8,
   15970                             binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
   15971                             mkU8(3)) );
   15972       }
   15973       store( mkexpr( addr_aligned),
   15974              unop( Iop_V128to32,
   15975                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
   15976       break;
   15977    }
   15978 
   15979    case 0x0E7: // stvx (Store Vector Indexed, AV p134)
   15980       DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   15981       store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   15982       break;
   15983 
   15984    case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
   15985       DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   15986       store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   15987       break;
   15988 
   15989    default:
   15990       vex_printf("dis_av_store(ppc)(opc2)\n");
   15991       return False;
   15992    }
   15993    return True;
   15994 }
   15995 
   15996 /*
   15997   AltiVec Arithmetic Instructions
   15998 */
   15999 static Bool dis_av_arith ( UInt theInstr )
   16000 {
   16001    /* VX-Form */
   16002    UChar opc1     = ifieldOPC(theInstr);
   16003    UChar vD_addr  = ifieldRegDS(theInstr);
   16004    UChar vA_addr  = ifieldRegA(theInstr);
   16005    UChar vB_addr  = ifieldRegB(theInstr);
   16006    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   16007 
   16008    IRTemp vA = newTemp(Ity_V128);
   16009    IRTemp vB = newTemp(Ity_V128);
   16010    IRTemp z3 = newTemp(Ity_I64);
   16011    IRTemp z2 = newTemp(Ity_I64);
   16012    IRTemp z1 = newTemp(Ity_I64);
   16013    IRTemp z0 = newTemp(Ity_I64);
   16014    IRTemp aEvn, aOdd;
   16015    IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
   16016    IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
   16017    IRTemp b3, b2, b1, b0;
   16018 
   16019    aEvn = aOdd = IRTemp_INVALID;
   16020    a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
   16021    a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
   16022    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   16023 
   16024    assign( vA, getVReg(vA_addr));
   16025    assign( vB, getVReg(vB_addr));
   16026 
   16027    if (opc1 != 0x4) {
   16028       vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
   16029       return False;
   16030    }
   16031 
   16032    switch (opc2) {
   16033    /* Add */
   16034    case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
   16035       DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16036       /* unsigned_ov(x+y) = (y >u not(x)) */
   16037       putVReg( vD_addr, binop(Iop_ShrN32x4,
   16038                               binop(Iop_CmpGT32Ux4, mkexpr(vB),
   16039                                     unop(Iop_NotV128, mkexpr(vA))),
   16040                               mkU8(31)) );
   16041       break;
   16042    }
   16043    case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
   16044       DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16045       putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
   16046       break;
   16047 
   16048    case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
   16049       DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16050       putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
   16051       break;
   16052 
   16053    case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
   16054       DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16055       putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
   16056       break;
   16057 
   16058    case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
   16059       DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16060       putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
   16061       break;
   16062 
   16063    case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
   16064       DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16065       putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
   16066       // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
   16067       break;
   16068 
   16069    case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
   16070       DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16071       putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
   16072       // TODO: set VSCR[SAT]
   16073       break;
   16074 
   16075    case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
   16076       DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16077       putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
   16078       // TODO: set VSCR[SAT]
   16079       break;
   16080 
   16081    case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
   16082       DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16083       putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
   16084       // TODO: set VSCR[SAT]
   16085       break;
   16086 
   16087    case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
   16088       DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16089       putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
   16090       // TODO: set VSCR[SAT]
   16091       break;
   16092 
   16093    case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
   16094       DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16095       putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
   16096       // TODO: set VSCR[SAT]
   16097       break;
   16098 
   16099 
   16100    /* Subtract */
   16101    case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
   16102       DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16103       /* unsigned_ov(x-y) = (y >u x) */
   16104       putVReg( vD_addr, binop(Iop_ShrN32x4,
   16105                               unop(Iop_NotV128,
   16106                                    binop(Iop_CmpGT32Ux4, mkexpr(vB),
   16107                                          mkexpr(vA))),
   16108                               mkU8(31)) );
   16109       break;
   16110    }
   16111    case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
   16112       DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16113       putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
   16114       break;
   16115 
   16116    case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
   16117       DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16118       putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
   16119       break;
   16120 
   16121    case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
   16122       DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16123       putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
   16124       break;
   16125 
   16126    case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
   16127       DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16128       putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
   16129       break;
   16130 
   16131    case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
   16132       DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16133       putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
   16134       // TODO: set VSCR[SAT]
   16135       break;
   16136 
   16137    case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
   16138       DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16139       putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
   16140       // TODO: set VSCR[SAT]
   16141       break;
   16142 
   16143    case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
   16144       DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16145       putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
   16146       // TODO: set VSCR[SAT]
   16147       break;
   16148 
   16149    case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
   16150       DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16151       putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
   16152       // TODO: set VSCR[SAT]
   16153       break;
   16154 
   16155    case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
   16156       DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16157       putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
   16158       // TODO: set VSCR[SAT]
   16159       break;
   16160 
   16161    case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
   16162       DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16163       putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
   16164       // TODO: set VSCR[SAT]
   16165       break;
   16166 
   16167 
   16168    /* Maximum */
   16169    case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
   16170       DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16171       putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
   16172       break;
   16173 
   16174    case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
   16175       DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16176       putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
   16177       break;
   16178 
   16179    case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
   16180       DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16181       putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
   16182       break;
   16183 
   16184    case 0x0C2: // vmaxud (Maximum Unsigned Double word)
   16185       DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16186       putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
   16187       break;
   16188 
   16189    case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
   16190       DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16191       putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
   16192       break;
   16193 
   16194    case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
   16195       DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16196       putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
   16197       break;
   16198 
   16199    case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
   16200       DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16201       putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
   16202       break;
   16203 
   16204    case 0x1C2: // vmaxsd (Maximum Signed Double word)
   16205       DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16206       putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
   16207       break;
   16208 
   16209    /* Minimum */
   16210    case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
   16211       DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16212       putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
   16213       break;
   16214 
   16215    case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
   16216       DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16217       putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
   16218       break;
   16219 
   16220    case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
   16221       DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16222       putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
   16223       break;
   16224 
   16225    case 0x2C2: // vminud (Minimum Unsigned Double Word)
   16226       DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16227       putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
   16228       break;
   16229 
   16230    case 0x302: // vminsb (Minimum Signed Byte, AV p188)
   16231       DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16232       putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
   16233       break;
   16234 
   16235    case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
   16236       DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16237       putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
   16238       break;
   16239 
   16240    case 0x382: // vminsw (Minimum Signed Word, AV p190)
   16241       DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16242       putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
   16243       break;
   16244 
   16245    case 0x3C2: // vminsd (Minimum Signed Double Word)
   16246       DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16247       putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
   16248       break;
   16249 
   16250 
   16251    /* Average */
   16252    case 0x402: // vavgub (Average Unsigned Byte, AV p152)
   16253       DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16254       putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
   16255       break;
   16256 
   16257    case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
   16258       DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16259       putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
   16260       break;
   16261 
   16262    case 0x482: // vavguw (Average Unsigned Word, AV p154)
   16263       DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16264       putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
   16265       break;
   16266 
   16267    case 0x502: // vavgsb (Average Signed Byte, AV p149)
   16268       DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16269       putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
   16270       break;
   16271 
   16272    case 0x542: // vavgsh (Average Signed Half Word, AV p150)
   16273       DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16274       putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
   16275       break;
   16276 
   16277    case 0x582: // vavgsw (Average Signed Word, AV p151)
   16278       DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16279       putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
   16280       break;
   16281 
   16282 
   16283    /* Multiply */
   16284    case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
   16285       DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16286       putVReg( vD_addr,
   16287                binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
   16288       break;
   16289 
   16290    case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
   16291       DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16292       putVReg( vD_addr,
   16293                binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
   16294       break;
   16295 
   16296    case 0x088: // vmulouw (Multiply Odd Unsigned Word)
   16297       DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16298       putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
   16299       break;
   16300 
   16301    case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
   16302       DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16303       putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
   16304       break;
   16305 
   16306    case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
   16307       DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16308       putVReg( vD_addr,
   16309                binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
   16310       break;
   16311 
   16312    case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
   16313       DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16314       putVReg( vD_addr,
   16315                binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
   16316       break;
   16317 
   16318    case 0x188: // vmulosw (Multiply Odd Signed Word)
   16319       DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16320       putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
   16321       break;
   16322 
   16323    case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
   16324       DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16325       putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   16326       break;
   16327 
   16328    case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
   16329       DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16330       putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   16331       break;
   16332 
   16333    case 0x288: // vmuleuw (Multiply Even Unsigned Word)
   16334       DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16335       putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
   16336       break;
   16337 
   16338    case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
   16339       DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16340       putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
   16341       break;
   16342 
   16343    case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
   16344       DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16345       putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   16346       break;
   16347 
   16348    case 0x388: // vmulesw (Multiply Even Signed Word)
   16349       DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16350       putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
   16351       break;
   16352 
   16353    /* Sum Across Partial */
   16354    case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
   16355       IRTemp aEE, aEO, aOE, aOO;
   16356       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   16357       DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16358 
   16359       /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
   16360       expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   16361       expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   16362       expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   16363 
   16364       /* break V128 to 4xI32's, zero-extending to I64's */
   16365       breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   16366       breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   16367       breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   16368       breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   16369       breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   16370 
   16371       /* add lanes */
   16372       assign( z3, binop(Iop_Add64, mkexpr(b3),
   16373                      binop(Iop_Add64,
   16374                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   16375                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   16376       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16377                      binop(Iop_Add64,
   16378                          binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   16379                          binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   16380       assign( z1, binop(Iop_Add64, mkexpr(b1),
   16381                      binop(Iop_Add64,
   16382                          binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   16383                          binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   16384       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16385                      binop(Iop_Add64,
   16386                          binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   16387                          binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   16388 
   16389       /* saturate-narrow to 32bit, and combine to V128 */
   16390       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   16391                                          mkexpr(z1), mkexpr(z0)) );
   16392       break;
   16393    }
   16394    case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
   16395       IRTemp aEE, aEO, aOE, aOO;
   16396       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   16397       DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16398 
   16399       /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
   16400       expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   16401       expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   16402       expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   16403 
   16404       /* break V128 to 4xI32's, sign-extending to I64's */
   16405       breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   16406       breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   16407       breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   16408       breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   16409       breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   16410 
   16411       /* add lanes */
   16412       assign( z3, binop(Iop_Add64, mkexpr(b3),
   16413                      binop(Iop_Add64,
   16414                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   16415                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   16416       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16417                      binop(Iop_Add64,
   16418                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   16419                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   16420       assign( z1, binop(Iop_Add64, mkexpr(b1),
   16421                      binop(Iop_Add64,
   16422                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   16423                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   16424       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16425                      binop(Iop_Add64,
   16426                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   16427                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   16428 
   16429       /* saturate-narrow to 32bit, and combine to V128 */
   16430       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   16431                                          mkexpr(z1), mkexpr(z0)) );
   16432       break;
   16433    }
   16434    case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
   16435       DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16436 
   16437       /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
   16438       expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
   16439 
   16440       /* break V128 to 4xI32's, sign-extending to I64's */
   16441       breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
   16442       breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
   16443       breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
   16444 
   16445       /* add lanes */
   16446       assign( z3, binop(Iop_Add64, mkexpr(b3),
   16447                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
   16448       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16449                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
   16450       assign( z1, binop(Iop_Add64, mkexpr(b1),
   16451                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
   16452       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16453                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
   16454 
   16455       /* saturate-narrow to 32bit, and combine to V128 */
   16456       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   16457                                          mkexpr(z1), mkexpr(z0)) );
   16458       break;
   16459    }
   16460    case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
   16461       DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16462 
   16463       /* break V128 to 4xI32's, sign-extending to I64's */
   16464       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   16465       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   16466 
   16467       /* add lanes */
   16468       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16469                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
   16470       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16471                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
   16472 
   16473       /* saturate-narrow to 32bit, and combine to V128 */
   16474       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
   16475                                          mkU64(0), mkexpr(z0)) );
   16476       break;
   16477    }
   16478    case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
   16479       DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16480 
   16481       /* break V128 to 4xI32's, sign-extending to I64's */
   16482       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   16483       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   16484 
   16485       /* add lanes */
   16486       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16487                      binop(Iop_Add64,
   16488                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   16489                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   16490 
   16491       /* saturate-narrow to 32bit, and combine to V128 */
   16492       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
   16493                                          mkU64(0), mkexpr(z0)) );
   16494       break;
   16495    }
   16496    default:
   16497       vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
   16498       return False;
   16499    }
   16500    return True;
   16501 }
   16502 
   16503 /*
   16504   AltiVec Logic Instructions
   16505 */
   16506 static Bool dis_av_logic ( UInt theInstr )
   16507 {
   16508    /* VX-Form */
   16509    UChar opc1    = ifieldOPC(theInstr);
   16510    UChar vD_addr = ifieldRegDS(theInstr);
   16511    UChar vA_addr = ifieldRegA(theInstr);
   16512    UChar vB_addr = ifieldRegB(theInstr);
   16513    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   16514 
   16515    IRTemp vA = newTemp(Ity_V128);
   16516    IRTemp vB = newTemp(Ity_V128);
   16517    assign( vA, getVReg(vA_addr));
   16518    assign( vB, getVReg(vB_addr));
   16519 
   16520    if (opc1 != 0x4) {
   16521       vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
   16522       return False;
   16523    }
   16524 
   16525    switch (opc2) {
   16526    case 0x404: // vand (And, AV p147)
   16527       DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16528       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
   16529       break;
   16530 
   16531    case 0x444: // vandc (And, AV p148)
   16532       DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16533       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
   16534                               unop(Iop_NotV128, mkexpr(vB))) );
   16535       break;
   16536 
   16537    case 0x484: // vor (Or, AV p217)
   16538       DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16539       putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
   16540       break;
   16541 
   16542    case 0x4C4: // vxor (Xor, AV p282)
   16543       DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16544       putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
   16545       break;
   16546 
   16547    case 0x504: // vnor (Nor, AV p216)
   16548       DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16549       putVReg( vD_addr,
   16550          unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
   16551       break;
   16552 
   16553    case 0x544: // vorc (vA Or'd with complement of vb)
   16554       DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16555       putVReg( vD_addr, binop( Iop_OrV128,
   16556                                mkexpr( vA ),
   16557                                unop( Iop_NotV128, mkexpr( vB ) ) ) );
   16558       break;
   16559 
   16560    case 0x584: // vnand (Nand)
   16561       DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16562       putVReg( vD_addr, unop( Iop_NotV128,
   16563                               binop(Iop_AndV128, mkexpr( vA ),
   16564                               mkexpr( vB ) ) ) );
   16565       break;
   16566 
   16567    case 0x684: // veqv (complemented XOr)
   16568       DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16569       putVReg( vD_addr, unop( Iop_NotV128,
   16570                               binop( Iop_XorV128, mkexpr( vA ),
   16571                               mkexpr( vB ) ) ) );
   16572       break;
   16573 
   16574    default:
   16575       vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
   16576       return False;
   16577    }
   16578    return True;
   16579 }
   16580 
   16581 /*
   16582   AltiVec Compare Instructions
   16583 */
   16584 static Bool dis_av_cmp ( UInt theInstr )
   16585 {
   16586    /* VXR-Form */
   16587    UChar opc1     = ifieldOPC(theInstr);
   16588    UChar vD_addr  = ifieldRegDS(theInstr);
   16589    UChar vA_addr  = ifieldRegA(theInstr);
   16590    UChar vB_addr  = ifieldRegB(theInstr);
   16591    UChar flag_rC  = ifieldBIT10(theInstr);
   16592    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   16593 
   16594    IRTemp vA = newTemp(Ity_V128);
   16595    IRTemp vB = newTemp(Ity_V128);
   16596    IRTemp vD = newTemp(Ity_V128);
   16597    assign( vA, getVReg(vA_addr));
   16598    assign( vB, getVReg(vB_addr));
   16599 
   16600    if (opc1 != 0x4) {
   16601       vex_printf("dis_av_cmp(ppc)(instr)\n");
   16602       return False;
   16603    }
   16604 
   16605    switch (opc2) {
   16606    case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
   16607       DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16608                                       vD_addr, vA_addr, vB_addr);
   16609       assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
   16610       break;
   16611 
   16612    case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
   16613       DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16614                                       vD_addr, vA_addr, vB_addr);
   16615       assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
   16616       break;
   16617 
   16618    case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
   16619       DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16620                                       vD_addr, vA_addr, vB_addr);
   16621       assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
   16622       break;
   16623 
   16624    case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
   16625       DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16626                                       vD_addr, vA_addr, vB_addr);
   16627       assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
   16628       break;
   16629 
   16630    case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
   16631       DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16632                                       vD_addr, vA_addr, vB_addr);
   16633       assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
   16634       break;
   16635 
   16636    case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
   16637       DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16638                                       vD_addr, vA_addr, vB_addr);
   16639       assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
   16640       break;
   16641 
   16642    case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
   16643       DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16644                                        vD_addr, vA_addr, vB_addr);
   16645       assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
   16646       break;
   16647 
   16648    case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
   16649       DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16650                                       vD_addr, vA_addr, vB_addr);
   16651       assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
   16652       break;
   16653 
   16654    case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
   16655       DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16656                                        vD_addr, vA_addr, vB_addr);
   16657       assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
   16658       break;
   16659 
   16660    case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
   16661       DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16662                                       vD_addr, vA_addr, vB_addr);
   16663       assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
   16664       break;
   16665 
   16666    case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
   16667       DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16668                                       vD_addr, vA_addr, vB_addr);
   16669       assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
   16670       break;
   16671 
   16672    case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
   16673       DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16674                                       vD_addr, vA_addr, vB_addr);
   16675       assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
   16676       break;
   16677 
   16678    default:
   16679       vex_printf("dis_av_cmp(ppc)(opc2)\n");
   16680       return False;
   16681    }
   16682 
   16683    putVReg( vD_addr, mkexpr(vD) );
   16684 
   16685    if (flag_rC) {
   16686       set_AV_CR6( mkexpr(vD), True );
   16687    }
   16688    return True;
   16689 }
   16690 
   16691 /*
   16692   AltiVec Multiply-Sum Instructions
   16693 */
   16694 static Bool dis_av_multarith ( UInt theInstr )
   16695 {
   16696    /* VA-Form */
   16697    UChar opc1     = ifieldOPC(theInstr);
   16698    UChar vD_addr  = ifieldRegDS(theInstr);
   16699    UChar vA_addr  = ifieldRegA(theInstr);
   16700    UChar vB_addr  = ifieldRegB(theInstr);
   16701    UChar vC_addr  = ifieldRegC(theInstr);
   16702    UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
   16703 
   16704    IRTemp vA    = newTemp(Ity_V128);
   16705    IRTemp vB    = newTemp(Ity_V128);
   16706    IRTemp vC    = newTemp(Ity_V128);
   16707    IRTemp zeros = newTemp(Ity_V128);
   16708    IRTemp aLo   = newTemp(Ity_V128);
   16709    IRTemp bLo   = newTemp(Ity_V128);
   16710    IRTemp cLo   = newTemp(Ity_V128);
   16711    IRTemp zLo   = newTemp(Ity_V128);
   16712    IRTemp aHi   = newTemp(Ity_V128);
   16713    IRTemp bHi   = newTemp(Ity_V128);
   16714    IRTemp cHi   = newTemp(Ity_V128);
   16715    IRTemp zHi   = newTemp(Ity_V128);
   16716    IRTemp abEvn = newTemp(Ity_V128);
   16717    IRTemp abOdd = newTemp(Ity_V128);
   16718    IRTemp z3    = newTemp(Ity_I64);
   16719    IRTemp z2    = newTemp(Ity_I64);
   16720    IRTemp z1    = newTemp(Ity_I64);
   16721    IRTemp z0    = newTemp(Ity_I64);
   16722    IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
   16723    IRTemp c3, c2, c1, c0;
   16724 
   16725    ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
   16726    c3 = c2 = c1 = c0 = IRTemp_INVALID;
   16727 
   16728    assign( vA, getVReg(vA_addr));
   16729    assign( vB, getVReg(vB_addr));
   16730    assign( vC, getVReg(vC_addr));
   16731    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   16732 
   16733    if (opc1 != 0x4) {
   16734       vex_printf("dis_av_multarith(ppc)(instr)\n");
   16735       return False;
   16736    }
   16737 
   16738    switch (opc2) {
   16739    /* Multiply-Add */
   16740    case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
   16741       IRTemp cSigns = newTemp(Ity_V128);
   16742       DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
   16743           vD_addr, vA_addr, vB_addr, vC_addr);
   16744       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
   16745       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   16746       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   16747       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   16748       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   16749       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   16750       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   16751 
   16752       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   16753                          binop(Iop_SarN32x4,
   16754                                binop(Iop_MullEven16Sx8,
   16755                                      mkexpr(aLo), mkexpr(bLo)),
   16756                                mkU8(15))) );
   16757 
   16758       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   16759                          binop(Iop_SarN32x4,
   16760                                binop(Iop_MullEven16Sx8,
   16761                                      mkexpr(aHi), mkexpr(bHi)),
   16762                                mkU8(15))) );
   16763 
   16764       putVReg( vD_addr,
   16765                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   16766       break;
   16767    }
   16768    case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
   16769       IRTemp zKonst = newTemp(Ity_V128);
   16770       IRTemp cSigns = newTemp(Ity_V128);
   16771       DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
   16772           vD_addr, vA_addr, vB_addr, vC_addr);
   16773       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
   16774       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   16775       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   16776       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   16777       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   16778       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   16779       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   16780 
   16781       /* shifting our const avoids store/load version of Dup */
   16782       assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
   16783                             mkU8(14)) );
   16784 
   16785       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   16786                          binop(Iop_SarN32x4,
   16787                                binop(Iop_Add32x4, mkexpr(zKonst),
   16788                                      binop(Iop_MullEven16Sx8,
   16789                                            mkexpr(aLo), mkexpr(bLo))),
   16790                                mkU8(15))) );
   16791 
   16792       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   16793                          binop(Iop_SarN32x4,
   16794                                binop(Iop_Add32x4, mkexpr(zKonst),
   16795                                      binop(Iop_MullEven16Sx8,
   16796                                            mkexpr(aHi), mkexpr(bHi))),
   16797                                mkU8(15))) );
   16798 
   16799       putVReg( vD_addr,
   16800                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   16801       break;
   16802    }
   16803    case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
   16804       DIP("vmladduhm v%d,v%d,v%d,v%d\n",
   16805           vD_addr, vA_addr, vB_addr, vC_addr);
   16806       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   16807       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   16808       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
   16809       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   16810       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   16811       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
   16812       assign(zLo, binop(Iop_Add32x4,
   16813                      binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
   16814                      mkexpr(cLo)) );
   16815       assign(zHi, binop(Iop_Add32x4,
   16816                      binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
   16817                      mkexpr(cHi)));
   16818       putVReg( vD_addr,
   16819                binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
   16820       break;
   16821    }
   16822 
   16823 
   16824    /* Multiply-Sum */
   16825    case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
   16826       IRTemp abEE, abEO, abOE, abOO;
   16827       abEE = abEO = abOE = abOO = IRTemp_INVALID;
   16828       DIP("vmsumubm v%d,v%d,v%d,v%d\n",
   16829           vD_addr, vA_addr, vB_addr, vC_addr);
   16830 
   16831       /* multiply vA,vB (unsigned, widening) */
   16832       assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   16833       assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
   16834 
   16835       /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
   16836       expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
   16837       expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
   16838 
   16839       putVReg( vD_addr,
   16840          binop(Iop_Add32x4, mkexpr(vC),
   16841                binop(Iop_Add32x4,
   16842                      binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
   16843                      binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
   16844       break;
   16845    }
   16846    case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
   16847       IRTemp aEvn, aOdd, bEvn, bOdd;
   16848       IRTemp abEE = newTemp(Ity_V128);
   16849       IRTemp abEO = newTemp(Ity_V128);
   16850       IRTemp abOE = newTemp(Ity_V128);
   16851       IRTemp abOO = newTemp(Ity_V128);
   16852       aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
   16853       DIP("vmsummbm v%d,v%d,v%d,v%d\n",
   16854           vD_addr, vA_addr, vB_addr, vC_addr);
   16855 
   16856       /* sign-extend vA, zero-extend vB, for mixed-sign multiply
   16857          (separating out adjacent lanes to different vectors) */
   16858       expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
   16859       expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
   16860 
   16861       /* multiply vA, vB, again separating adjacent lanes */
   16862       assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
   16863       assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
   16864       assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
   16865       assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
   16866 
   16867       /* add results together, + vC */
   16868       putVReg( vD_addr,
   16869          binop(Iop_QAdd32Sx4, mkexpr(vC),
   16870                binop(Iop_QAdd32Sx4,
   16871                      binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
   16872                      binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
   16873       break;
   16874    }
   16875    case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
   16876       DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
   16877           vD_addr, vA_addr, vB_addr, vC_addr);
   16878       assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   16879       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   16880       putVReg( vD_addr,
   16881          binop(Iop_Add32x4, mkexpr(vC),
   16882                binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
   16883       break;
   16884    }
   16885    case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
   16886       DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
   16887           vD_addr, vA_addr, vB_addr, vC_addr);
   16888       /* widening multiply, separating lanes */
   16889       assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
   16890       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   16891 
   16892       /* break V128 to 4xI32's, zero-extending to I64's */
   16893       breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   16894       breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   16895       breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   16896 
   16897       /* add lanes */
   16898       assign( z3, binop(Iop_Add64, mkexpr(c3),
   16899                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   16900       assign( z2, binop(Iop_Add64, mkexpr(c2),
   16901                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   16902       assign( z1, binop(Iop_Add64, mkexpr(c1),
   16903                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   16904       assign( z0, binop(Iop_Add64, mkexpr(c0),
   16905                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   16906 
   16907       /* saturate-narrow to 32bit, and combine to V128 */
   16908       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   16909                                          mkexpr(z1), mkexpr(z0)) );
   16910 
   16911       break;
   16912    }
   16913    case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
   16914       DIP("vmsumshm v%d,v%d,v%d,v%d\n",
   16915           vD_addr, vA_addr, vB_addr, vC_addr);
   16916       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   16917       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   16918       putVReg( vD_addr,
   16919          binop(Iop_Add32x4, mkexpr(vC),
   16920                binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
   16921       break;
   16922    }
   16923    case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
   16924       DIP("vmsumshs v%d,v%d,v%d,v%d\n",
   16925           vD_addr, vA_addr, vB_addr, vC_addr);
   16926       /* widening multiply, separating lanes */
   16927       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   16928       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   16929 
   16930       /* break V128 to 4xI32's, sign-extending to I64's */
   16931       breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   16932       breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   16933       breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   16934 
   16935       /* add lanes */
   16936       assign( z3, binop(Iop_Add64, mkexpr(c3),
   16937                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   16938       assign( z2, binop(Iop_Add64, mkexpr(c2),
   16939                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   16940       assign( z1, binop(Iop_Add64, mkexpr(c1),
   16941                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   16942       assign( z0, binop(Iop_Add64, mkexpr(c0),
   16943                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   16944 
   16945       /* saturate-narrow to 32bit, and combine to V128 */
   16946       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   16947                                          mkexpr(z1), mkexpr(z0)) );
   16948       break;
   16949    }
   16950    default:
   16951       vex_printf("dis_av_multarith(ppc)(opc2)\n");
   16952       return False;
   16953    }
   16954    return True;
   16955 }
   16956 
   16957 /*
   16958   AltiVec Polynomial Multiply-Sum Instructions
   16959 */
   16960 static Bool dis_av_polymultarith ( UInt theInstr )
   16961 {
   16962    /* VA-Form */
   16963    UChar opc1     = ifieldOPC(theInstr);
   16964    UChar vD_addr  = ifieldRegDS(theInstr);
   16965    UChar vA_addr  = ifieldRegA(theInstr);
   16966    UChar vB_addr  = ifieldRegB(theInstr);
   16967    UChar vC_addr  = ifieldRegC(theInstr);
   16968    UInt  opc2     = IFIELD(theInstr, 0, 11);
   16969    IRTemp vA    = newTemp(Ity_V128);
   16970    IRTemp vB    = newTemp(Ity_V128);
   16971    IRTemp vC    = newTemp(Ity_V128);
   16972 
   16973    assign( vA, getVReg(vA_addr));
   16974    assign( vB, getVReg(vB_addr));
   16975    assign( vC, getVReg(vC_addr));
   16976 
   16977    if (opc1 != 0x4) {
   16978       vex_printf("dis_av_polymultarith(ppc)(instr)\n");
   16979       return False;
   16980    }
   16981 
   16982    switch (opc2) {
   16983       /* Polynomial Multiply-Add */
   16984       case 0x408:  // vpmsumb   Vector Polynomial Multipy-sum Byte
   16985          DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16986          putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
   16987                                  mkexpr(vA), mkexpr(vB)) );
   16988          break;
   16989       case 0x448:  // vpmsumd   Vector Polynomial Multipy-sum Double Word
   16990          DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16991          putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
   16992                                  mkexpr(vA), mkexpr(vB)) );
   16993          break;
   16994       case 0x488:  // vpmsumw   Vector Polynomial Multipy-sum Word
   16995          DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16996          putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
   16997                                  mkexpr(vA), mkexpr(vB)) );
   16998          break;
   16999       case 0x4C8:  // vpmsumh   Vector Polynomial Multipy-sum Half Word
   17000          DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17001          putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
   17002                                  mkexpr(vA), mkexpr(vB)) );
   17003          break;
   17004       default:
   17005          vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
   17006          return False;
   17007    }
   17008    return True;
   17009 }
   17010 
   17011 /*
   17012   AltiVec Shift/Rotate Instructions
   17013 */
   17014 static Bool dis_av_shift ( UInt theInstr )
   17015 {
   17016    /* VX-Form */
   17017    UChar opc1    = ifieldOPC(theInstr);
   17018    UChar vD_addr = ifieldRegDS(theInstr);
   17019    UChar vA_addr = ifieldRegA(theInstr);
   17020    UChar vB_addr = ifieldRegB(theInstr);
   17021    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   17022 
   17023    IRTemp vA = newTemp(Ity_V128);
   17024    IRTemp vB = newTemp(Ity_V128);
   17025    assign( vA, getVReg(vA_addr));
   17026    assign( vB, getVReg(vB_addr));
   17027 
   17028    if (opc1 != 0x4){
   17029       vex_printf("dis_av_shift(ppc)(instr)\n");
   17030       return False;
   17031    }
   17032 
   17033    switch (opc2) {
   17034    /* Rotate */
   17035    case 0x004: // vrlb (Rotate Left Integer B, AV p234)
   17036       DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17037       putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
   17038       break;
   17039 
   17040    case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
   17041       DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17042       putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
   17043       break;
   17044 
   17045    case 0x084: // vrlw (Rotate Left Integer W, AV p236)
   17046       DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17047       putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
   17048       break;
   17049 
   17050    case 0x0C4: // vrld (Rotate Left Integer Double Word)
   17051       DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17052       putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
   17053       break;
   17054 
   17055 
   17056    /* Shift Left */
   17057    case 0x104: // vslb (Shift Left Integer B, AV p240)
   17058       DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17059       putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
   17060       break;
   17061 
   17062    case 0x144: // vslh (Shift Left Integer HW, AV p242)
   17063       DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17064       putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
   17065       break;
   17066 
   17067    case 0x184: // vslw (Shift Left Integer W, AV p244)
   17068       DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17069       putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
   17070       break;
   17071 
   17072    case 0x5C4: // vsld (Shift Left Integer Double Word)
   17073       DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17074       putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
   17075       break;
   17076 
   17077    case 0x1C4: { // vsl (Shift Left, AV p239)
   17078       IRTemp sh = newTemp(Ity_I8);
   17079       DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17080       assign( sh, binop(Iop_And8, mkU8(0x7),
   17081                         unop(Iop_32to8,
   17082                              unop(Iop_V128to32, mkexpr(vB)))) );
   17083       putVReg( vD_addr,
   17084                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   17085       break;
   17086    }
   17087    case 0x40C: { // vslo (Shift Left by Octet, AV p243)
   17088       IRTemp sh = newTemp(Ity_I8);
   17089       DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17090       assign( sh, binop(Iop_And8, mkU8(0x78),
   17091                         unop(Iop_32to8,
   17092                              unop(Iop_V128to32, mkexpr(vB)))) );
   17093       putVReg( vD_addr,
   17094                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   17095       break;
   17096    }
   17097 
   17098 
   17099    /* Shift Right */
   17100    case 0x204: // vsrb (Shift Right B, AV p256)
   17101       DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17102       putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
   17103       break;
   17104 
   17105    case 0x244: // vsrh (Shift Right HW, AV p257)
   17106       DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17107       putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
   17108       break;
   17109 
   17110    case 0x284: // vsrw (Shift Right W, AV p259)
   17111       DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17112       putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
   17113       break;
   17114 
   17115    case 0x2C4: { // vsr (Shift Right, AV p251)
   17116       IRTemp sh = newTemp(Ity_I8);
   17117       DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17118       assign( sh, binop(Iop_And8, mkU8(0x7),
   17119                         unop(Iop_32to8,
   17120                              unop(Iop_V128to32, mkexpr(vB)))) );
   17121       putVReg( vD_addr,
   17122                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   17123       break;
   17124    }
   17125    case 0x304: // vsrab (Shift Right Alg B, AV p253)
   17126       DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17127       putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
   17128       break;
   17129 
   17130    case 0x344: // vsrah (Shift Right Alg HW, AV p254)
   17131       DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17132       putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
   17133       break;
   17134 
   17135    case 0x384: // vsraw (Shift Right Alg W, AV p255)
   17136       DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17137       putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
   17138       break;
   17139 
   17140    case 0x3C4: // vsrad (Shift Right Alg Double Word)
   17141       DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17142       putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
   17143       break;
   17144 
   17145    case 0x44C: { // vsro (Shift Right by Octet, AV p258)
   17146       IRTemp sh = newTemp(Ity_I8);
   17147       DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17148       assign( sh, binop(Iop_And8, mkU8(0x78),
   17149                         unop(Iop_32to8,
   17150                              unop(Iop_V128to32, mkexpr(vB)))) );
   17151       putVReg( vD_addr,
   17152                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   17153       break;
   17154    }
   17155 
   17156    case 0x6C4: // vsrd (Shift Right Double Word)
   17157       DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17158       putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
   17159       break;
   17160 
   17161 
   17162    default:
   17163       vex_printf("dis_av_shift(ppc)(opc2)\n");
   17164       return False;
   17165    }
   17166    return True;
   17167 }
   17168 
   17169 /*
   17170   AltiVec Permute Instructions
   17171 */
   17172 static Bool dis_av_permute ( UInt theInstr )
   17173 {
   17174    /* VA-Form, VX-Form */
   17175    UChar opc1      = ifieldOPC(theInstr);
   17176    UChar vD_addr   = ifieldRegDS(theInstr);
   17177    UChar vA_addr   = ifieldRegA(theInstr);
   17178    UChar UIMM_5    = vA_addr;
   17179    UChar vB_addr   = ifieldRegB(theInstr);
   17180    UChar vC_addr   = ifieldRegC(theInstr);
   17181    UChar b10       = ifieldBIT10(theInstr);
   17182    UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
   17183    UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
   17184 
   17185    UChar SIMM_8 = extend_s_5to8(UIMM_5);
   17186 
   17187    IRTemp vA = newTemp(Ity_V128);
   17188    IRTemp vB = newTemp(Ity_V128);
   17189    IRTemp vC = newTemp(Ity_V128);
   17190    assign( vA, getVReg(vA_addr));
   17191    assign( vB, getVReg(vB_addr));
   17192    assign( vC, getVReg(vC_addr));
   17193 
   17194    if (opc1 != 0x4) {
   17195       vex_printf("dis_av_permute(ppc)(instr)\n");
   17196       return False;
   17197    }
   17198 
   17199    switch (opc2) {
   17200    case 0x2A: // vsel (Conditional Select, AV p238)
   17201       DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
   17202       /* vD = (vA & ~vC) | (vB & vC) */
   17203       putVReg( vD_addr, binop(Iop_OrV128,
   17204          binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   17205          binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   17206       return True;
   17207 
   17208    case 0x2B: { // vperm (Permute, AV p218)
   17209       /* limited to two args for IR, so have to play games... */
   17210       IRTemp a_perm  = newTemp(Ity_V128);
   17211       IRTemp b_perm  = newTemp(Ity_V128);
   17212       IRTemp mask    = newTemp(Ity_V128);
   17213       IRTemp vC_andF = newTemp(Ity_V128);
   17214       DIP("vperm v%d,v%d,v%d,v%d\n",
   17215           vD_addr, vA_addr, vB_addr, vC_addr);
   17216       /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
   17217          IR specifies, and also to hide irrelevant bits from
   17218          memcheck */
   17219       assign( vC_andF,
   17220               binop(Iop_AndV128, mkexpr(vC),
   17221                                  unop(Iop_Dup8x16, mkU8(0xF))) );
   17222       assign( a_perm,
   17223               binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
   17224       assign( b_perm,
   17225               binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
   17226       // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
   17227       assign( mask, binop(Iop_SarN8x16,
   17228                           binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
   17229                           mkU8(7)) );
   17230       // dst = (a & ~mask) | (b & mask)
   17231       putVReg( vD_addr, binop(Iop_OrV128,
   17232                               binop(Iop_AndV128, mkexpr(a_perm),
   17233                                     unop(Iop_NotV128, mkexpr(mask))),
   17234                               binop(Iop_AndV128, mkexpr(b_perm),
   17235                                     mkexpr(mask))) );
   17236       return True;
   17237    }
   17238    case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
   17239       if (b10 != 0) {
   17240          vex_printf("dis_av_permute(ppc)(vsldoi)\n");
   17241          return False;
   17242       }
   17243       DIP("vsldoi v%d,v%d,v%d,%d\n",
   17244           vD_addr, vA_addr, vB_addr, SHB_uimm4);
   17245       if (SHB_uimm4 == 0)
   17246          putVReg( vD_addr, mkexpr(vA) );
   17247       else
   17248          putVReg( vD_addr,
   17249             binop(Iop_OrV128,
   17250                   binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
   17251                   binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
   17252       return True;
   17253    case 0x2D: {  // vpermxor (Vector Permute and Exclusive-OR)
   17254       IRTemp a_perm  = newTemp(Ity_V128);
   17255       IRTemp b_perm  = newTemp(Ity_V128);
   17256       IRTemp vrc_a   = newTemp(Ity_V128);
   17257       IRTemp vrc_b   = newTemp(Ity_V128);
   17258 
   17259       /* IBM index  is 0:7, Change index value to index 7:0 */
   17260       assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
   17261                             unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
   17262       assign( vrc_a, binop( Iop_ShrV128,
   17263                             binop( Iop_AndV128, mkexpr( vC ),
   17264                                    unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
   17265                             mkU8 ( 4 ) ) );
   17266       assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
   17267       assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
   17268       putVReg( vD_addr, binop( Iop_XorV128,
   17269                                mkexpr( a_perm ), mkexpr( b_perm) ) );
   17270       return True;
   17271    }
   17272    default:
   17273      break; // Fall through...
   17274    }
   17275 
   17276    opc2 = IFIELD( theInstr, 0, 11 );
   17277    switch (opc2) {
   17278 
   17279    /* Merge */
   17280    case 0x00C: // vmrghb (Merge High B, AV p195)
   17281       DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17282       putVReg( vD_addr,
   17283                binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
   17284       break;
   17285 
   17286    case 0x04C: // vmrghh (Merge High HW, AV p196)
   17287       DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17288       putVReg( vD_addr,
   17289                binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
   17290       break;
   17291 
   17292    case 0x08C: // vmrghw (Merge High W, AV p197)
   17293       DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17294       putVReg( vD_addr,
   17295                binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
   17296       break;
   17297 
   17298    case 0x10C: // vmrglb (Merge Low B, AV p198)
   17299       DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17300       putVReg( vD_addr,
   17301                binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
   17302       break;
   17303 
   17304    case 0x14C: // vmrglh (Merge Low HW, AV p199)
   17305       DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17306       putVReg( vD_addr,
   17307                binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
   17308       break;
   17309 
   17310    case 0x18C: // vmrglw (Merge Low W, AV p200)
   17311       DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17312       putVReg( vD_addr,
   17313                binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
   17314       break;
   17315 
   17316 
   17317    /* Splat */
   17318    case 0x20C: { // vspltb (Splat Byte, AV p245)
   17319       /* vD = Dup8x16( vB[UIMM_5] ) */
   17320       UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
   17321       DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   17322       putVReg( vD_addr, unop(Iop_Dup8x16,
   17323            unop(Iop_32to8, unop(Iop_V128to32,
   17324                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   17325       break;
   17326    }
   17327    case 0x24C: { // vsplth (Splat Half Word, AV p246)
   17328       UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
   17329       DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   17330       putVReg( vD_addr, unop(Iop_Dup16x8,
   17331            unop(Iop_32to16, unop(Iop_V128to32,
   17332                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   17333       break;
   17334    }
   17335    case 0x28C: { // vspltw (Splat Word, AV p250)
   17336       /* vD = Dup32x4( vB[UIMM_5] ) */
   17337       UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
   17338       DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   17339       putVReg( vD_addr, unop(Iop_Dup32x4,
   17340          unop(Iop_V128to32,
   17341               binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
   17342       break;
   17343    }
   17344    case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
   17345       DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
   17346       putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
   17347       break;
   17348 
   17349    case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
   17350       DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
   17351       putVReg( vD_addr,
   17352                unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
   17353       break;
   17354 
   17355    case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
   17356       DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
   17357       putVReg( vD_addr,
   17358                unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
   17359       break;
   17360 
   17361    case 0x68C: // vmrgow (Merge Odd Word)
   17362      DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17363       /*   VD[0] <- VA[1]
   17364            VD[1] <- VB[1]
   17365            VD[2] <- VA[3]
   17366            VD[3] <- VB[3]
   17367       */
   17368       putVReg( vD_addr,
   17369                binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
   17370       break;
   17371 
   17372    case 0x78C: // vmrgew (Merge Even Word)
   17373       DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17374       /*   VD[0] <- VA[0]
   17375            VD[1] <- VB[0]
   17376            VD[2] <- VA[2]
   17377            VD[3] <- VB[2]
   17378       */
   17379       putVReg( vD_addr,
   17380                binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
   17381       break;
   17382 
   17383    default:
   17384       vex_printf("dis_av_permute(ppc)(opc2)\n");
   17385       return False;
   17386    }
   17387    return True;
   17388 }
   17389 
   17390 /*
   17391   AltiVec Pack/Unpack Instructions
   17392 */
   17393 static Bool dis_av_pack ( UInt theInstr )
   17394 {
   17395    /* VX-Form */
   17396    UChar opc1     = ifieldOPC(theInstr);
   17397    UChar vD_addr  = ifieldRegDS(theInstr);
   17398    UChar vA_addr  = ifieldRegA(theInstr);
   17399    UChar vB_addr  = ifieldRegB(theInstr);
   17400    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17401 
   17402    IRTemp signs = IRTemp_INVALID;
   17403    IRTemp zeros = IRTemp_INVALID;
   17404    IRTemp vA    = newTemp(Ity_V128);
   17405    IRTemp vB    = newTemp(Ity_V128);
   17406    assign( vA, getVReg(vA_addr));
   17407    assign( vB, getVReg(vB_addr));
   17408 
   17409    if (opc1 != 0x4) {
   17410       vex_printf("dis_av_pack(ppc)(instr)\n");
   17411       return False;
   17412    }
   17413    switch (opc2) {
   17414    /* Packing */
   17415    case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
   17416       DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17417       putVReg( vD_addr,
   17418                binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
   17419       return True;
   17420 
   17421    case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
   17422       DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17423       putVReg( vD_addr,
   17424                binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
   17425       return True;
   17426 
   17427    case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
   17428       DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17429       putVReg( vD_addr,
   17430                binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
   17431       // TODO: set VSCR[SAT]
   17432       return True;
   17433 
   17434    case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
   17435       DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17436       putVReg( vD_addr,
   17437                binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
   17438       // TODO: set VSCR[SAT]
   17439       return True;
   17440 
   17441    case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
   17442       // This insn does a signed->unsigned saturating conversion.
   17443       // Conversion done here, then uses unsigned->unsigned vpk insn:
   17444       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
   17445       IRTemp vA_tmp = newTemp(Ity_V128);
   17446       IRTemp vB_tmp = newTemp(Ity_V128);
   17447       DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17448       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   17449                             unop(Iop_NotV128,
   17450                                  binop(Iop_SarN16x8,
   17451                                        mkexpr(vA), mkU8(15)))) );
   17452       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   17453                             unop(Iop_NotV128,
   17454                                  binop(Iop_SarN16x8,
   17455                                        mkexpr(vB), mkU8(15)))) );
   17456       putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
   17457                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   17458       // TODO: set VSCR[SAT]
   17459       return True;
   17460    }
   17461    case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
   17462       // This insn does a signed->unsigned saturating conversion.
   17463       // Conversion done here, then uses unsigned->unsigned vpk insn:
   17464       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
   17465       IRTemp vA_tmp = newTemp(Ity_V128);
   17466       IRTemp vB_tmp = newTemp(Ity_V128);
   17467       DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17468       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   17469                             unop(Iop_NotV128,
   17470                                  binop(Iop_SarN32x4,
   17471                                        mkexpr(vA), mkU8(31)))) );
   17472       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   17473                             unop(Iop_NotV128,
   17474                                  binop(Iop_SarN32x4,
   17475                                        mkexpr(vB), mkU8(31)))) );
   17476       putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
   17477                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   17478       // TODO: set VSCR[SAT]
   17479       return True;
   17480    }
   17481    case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
   17482       DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17483       putVReg( vD_addr,
   17484                binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
   17485       // TODO: set VSCR[SAT]
   17486       return True;
   17487 
   17488    case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
   17489       DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17490       putVReg( vD_addr,
   17491                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
   17492       // TODO: set VSCR[SAT]
   17493       return True;
   17494 
   17495    case 0x30E: { // vpkpx (Pack Pixel, AV p219)
   17496       /* CAB: Worth a new primop? */
   17497       /* Using shifts to compact pixel elements, then packing them */
   17498       IRTemp a1 = newTemp(Ity_V128);
   17499       IRTemp a2 = newTemp(Ity_V128);
   17500       IRTemp a3 = newTemp(Ity_V128);
   17501       IRTemp a_tmp = newTemp(Ity_V128);
   17502       IRTemp b1 = newTemp(Ity_V128);
   17503       IRTemp b2 = newTemp(Ity_V128);
   17504       IRTemp b3 = newTemp(Ity_V128);
   17505       IRTemp b_tmp = newTemp(Ity_V128);
   17506       DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17507       assign( a1, binop(Iop_ShlN16x8,
   17508                         binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
   17509                         mkU8(10)) );
   17510       assign( a2, binop(Iop_ShlN16x8,
   17511                         binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
   17512                         mkU8(5)) );
   17513       assign( a3,  binop(Iop_ShrN16x8,
   17514                          binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
   17515                          mkU8(11)) );
   17516       assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
   17517                            binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
   17518 
   17519       assign( b1, binop(Iop_ShlN16x8,
   17520                         binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
   17521                         mkU8(10)) );
   17522       assign( b2, binop(Iop_ShlN16x8,
   17523                         binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
   17524                         mkU8(5)) );
   17525       assign( b3,  binop(Iop_ShrN16x8,
   17526                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
   17527                          mkU8(11)) );
   17528       assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
   17529                            binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
   17530 
   17531       putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
   17532                               mkexpr(a_tmp), mkexpr(b_tmp)) );
   17533       return True;
   17534    }
   17535 
   17536    case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
   17537       DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17538       putVReg( vD_addr,
   17539                binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
   17540       return True;
   17541 
   17542    case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
   17543       DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17544       putVReg( vD_addr,
   17545                binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
   17546       // TODO: set VSCR[SAT]
   17547       return True;
   17548 
   17549    case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
   17550       // This insn does a doubled signed->double unsigned saturating conversion
   17551       // Conversion done here, then uses unsigned->unsigned vpk insn:
   17552       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
   17553       // This is similar to the technique used for vpkswus, except done
   17554       // with double word integers versus word integers.
   17555       IRTemp vA_tmp = newTemp(Ity_V128);
   17556       IRTemp vB_tmp = newTemp(Ity_V128);
   17557       DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17558       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   17559                             unop(Iop_NotV128,
   17560                                  binop(Iop_SarN64x2,
   17561                                        mkexpr(vA), mkU8(63)))) );
   17562       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   17563                             unop(Iop_NotV128,
   17564                                  binop(Iop_SarN64x2,
   17565                                        mkexpr(vB), mkU8(63)))) );
   17566       putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
   17567                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   17568       // TODO: set VSCR[SAT]
   17569       return True;
   17570    }
   17571 
   17572    case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
   17573       DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17574       putVReg( vD_addr,
   17575                binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
   17576       // TODO: set VSCR[SAT]
   17577       return True;
   17578    default:
   17579       break; // Fall through...
   17580    }
   17581 
   17582 
   17583    if (vA_addr != 0) {
   17584       vex_printf("dis_av_pack(ppc)(vA_addr)\n");
   17585       return False;
   17586    }
   17587 
   17588    signs = newTemp(Ity_V128);
   17589    zeros = newTemp(Ity_V128);
   17590    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   17591 
   17592    switch (opc2) {
   17593    /* Unpacking */
   17594    case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
   17595       DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
   17596       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   17597       putVReg( vD_addr,
   17598                binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
   17599       break;
   17600    }
   17601    case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
   17602       DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
   17603       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   17604       putVReg( vD_addr,
   17605                binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
   17606       break;
   17607    }
   17608    case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
   17609       DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
   17610       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   17611       putVReg( vD_addr,
   17612                binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
   17613       break;
   17614    }
   17615    case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
   17616       DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
   17617       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   17618       putVReg( vD_addr,
   17619                binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
   17620       break;
   17621    }
   17622    case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
   17623       /* CAB: Worth a new primop? */
   17624       /* Using shifts to isolate pixel elements, then expanding them */
   17625       IRTemp z0  = newTemp(Ity_V128);
   17626       IRTemp z1  = newTemp(Ity_V128);
   17627       IRTemp z01 = newTemp(Ity_V128);
   17628       IRTemp z2  = newTemp(Ity_V128);
   17629       IRTemp z3  = newTemp(Ity_V128);
   17630       IRTemp z23 = newTemp(Ity_V128);
   17631       DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
   17632       assign( z0,  binop(Iop_ShlN16x8,
   17633                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   17634                          mkU8(8)) );
   17635       assign( z1,  binop(Iop_ShrN16x8,
   17636                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   17637                          mkU8(11)) );
   17638       assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   17639                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   17640       assign( z2,  binop(Iop_ShrN16x8,
   17641                          binop(Iop_ShlN16x8,
   17642                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   17643                                mkU8(11)),
   17644                          mkU8(3)) );
   17645       assign( z3,  binop(Iop_ShrN16x8,
   17646                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   17647                          mkU8(11)) );
   17648       assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   17649                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   17650       putVReg( vD_addr,
   17651                binop(Iop_OrV128,
   17652                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   17653                      mkexpr(z23)) );
   17654       break;
   17655    }
   17656    case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
   17657       /* identical to vupkhpx, except interleaving LO */
   17658       IRTemp z0  = newTemp(Ity_V128);
   17659       IRTemp z1  = newTemp(Ity_V128);
   17660       IRTemp z01 = newTemp(Ity_V128);
   17661       IRTemp z2  = newTemp(Ity_V128);
   17662       IRTemp z3  = newTemp(Ity_V128);
   17663       IRTemp z23 = newTemp(Ity_V128);
   17664       DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
   17665       assign( z0,  binop(Iop_ShlN16x8,
   17666                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   17667                          mkU8(8)) );
   17668       assign( z1,  binop(Iop_ShrN16x8,
   17669                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   17670                          mkU8(11)) );
   17671       assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   17672                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   17673       assign( z2,  binop(Iop_ShrN16x8,
   17674                          binop(Iop_ShlN16x8,
   17675                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   17676                                mkU8(11)),
   17677                          mkU8(3)) );
   17678       assign( z3,  binop(Iop_ShrN16x8,
   17679                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   17680                          mkU8(11)) );
   17681       assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   17682                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   17683       putVReg( vD_addr,
   17684                binop(Iop_OrV128,
   17685                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   17686                      mkexpr(z23)) );
   17687       break;
   17688    }
   17689    case 0x64E: { // vupkhsw (Unpack High Signed Word)
   17690       DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
   17691       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
   17692       putVReg( vD_addr,
   17693                binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
   17694       break;
   17695    }
   17696    case 0x6CE: { // vupklsw (Unpack Low Signed Word)
   17697       DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
   17698       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
   17699       putVReg( vD_addr,
   17700                binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
   17701       break;
   17702    }
   17703    default:
   17704       vex_printf("dis_av_pack(ppc)(opc2)\n");
   17705       return False;
   17706    }
   17707    return True;
   17708 }
   17709 
   17710 /*
   17711   AltiVec Cipher Instructions
   17712 */
   17713 static Bool dis_av_cipher ( UInt theInstr )
   17714 {
   17715    /* VX-Form */
   17716    UChar opc1     = ifieldOPC(theInstr);
   17717    UChar vD_addr  = ifieldRegDS(theInstr);
   17718    UChar vA_addr  = ifieldRegA(theInstr);
   17719    UChar vB_addr  = ifieldRegB(theInstr);
   17720    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17721 
   17722    IRTemp vA    = newTemp(Ity_V128);
   17723    IRTemp vB    = newTemp(Ity_V128);
   17724    assign( vA, getVReg(vA_addr));
   17725    assign( vB, getVReg(vB_addr));
   17726 
   17727    if (opc1 != 0x4) {
   17728       vex_printf("dis_av_cipher(ppc)(instr)\n");
   17729       return False;
   17730    }
   17731    switch (opc2) {
   17732       case 0x508: // vcipher (Vector Inverser Cipher)
   17733          DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17734          putVReg( vD_addr,
   17735                   binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
   17736          return True;
   17737 
   17738       case 0x509: // vcipherlast (Vector Inverser Cipher Last)
   17739          DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17740          putVReg( vD_addr,
   17741                   binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
   17742          return True;
   17743 
   17744       case 0x548: // vncipher (Vector Inverser Cipher)
   17745          DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17746          putVReg( vD_addr,
   17747                   binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
   17748          return True;
   17749 
   17750       case 0x549: // vncipherlast (Vector Inverser Cipher Last)
   17751          DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17752          putVReg( vD_addr,
   17753                   binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
   17754          return True;
   17755 
   17756       case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
   17757        * subBytes transform)
   17758        */
   17759          DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
   17760          putVReg( vD_addr,
   17761                   unop(Iop_CipherSV128, mkexpr(vA) ) );
   17762          return True;
   17763 
   17764       default:
   17765          vex_printf("dis_av_cipher(ppc)(opc2)\n");
   17766          return False;
   17767    }
   17768    return True;
   17769 }
   17770 
   17771 /*
   17772   AltiVec Secure Hash Instructions
   17773 */
   17774 static Bool dis_av_hash ( UInt theInstr )
   17775 {
   17776    /* VX-Form */
   17777    UChar opc1     = ifieldOPC(theInstr);
   17778    UChar vRT_addr = ifieldRegDS(theInstr);
   17779    UChar vRA_addr  = ifieldRegA(theInstr);
   17780    UChar s_field  = IFIELD( theInstr, 11, 5 );  // st and six field
   17781    UChar st       = IFIELD( theInstr, 15, 1 );  // st
   17782    UChar six      = IFIELD( theInstr, 11, 4 );  // six field
   17783    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17784 
   17785    IRTemp vA    = newTemp(Ity_V128);
   17786    IRTemp dst    = newTemp(Ity_V128);
   17787    assign( vA, getVReg(vRA_addr));
   17788 
   17789    if (opc1 != 0x4) {
   17790       vex_printf("dis_av_hash(ppc)(instr)\n");
   17791       return False;
   17792    }
   17793 
   17794    switch (opc2) {
   17795       case 0x682:  // vshasigmaw
   17796          DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
   17797          assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
   17798          putVReg( vRT_addr, mkexpr(dst));
   17799          return True;
   17800 
   17801       case 0x6C2:  // vshasigmad,
   17802          DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
   17803          putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
   17804          return True;
   17805 
   17806       default:
   17807          vex_printf("dis_av_hash(ppc)(opc2)\n");
   17808          return False;
   17809    }
   17810    return True;
   17811 }
   17812 
   17813 /*
   17814  * This function is used by the Vector add/subtract [extended] modulo/carry
   17815  * instructions.
   17816  *   - For the non-extended add instructions, the cin arg is set to zero.
   17817  *   - For the extended add instructions, cin is the integer value of
   17818  *     src3.bit[127].
   17819  *   - For the non-extended subtract instructions, src1 is added to the one's
   17820  *     complement of src2 + 1.  We re-use the cin argument to hold the '1'
   17821  *     value for this operation.
   17822  *   - For the extended subtract instructions, cin is the integer value of src3.bit[127].
   17823  */
   17824 static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
   17825                                         IRExpr * cin, Bool modulo)
   17826 {
   17827    IRTemp _vecA_32   = IRTemp_INVALID;
   17828    IRTemp _vecB_32   = IRTemp_INVALID;
   17829    IRTemp res_32     = IRTemp_INVALID;
   17830    IRTemp result     = IRTemp_INVALID;
   17831    IRTemp tmp_result = IRTemp_INVALID;
   17832    IRTemp carry      = IRTemp_INVALID;
   17833    Int i;
   17834    IRExpr * _vecA_low64 =  unop( Iop_V128to64, vecA );
   17835    IRExpr * _vecB_low64 =  unop( Iop_V128to64, vecB );
   17836    IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
   17837    IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
   17838 
   17839    for (i = 0; i < 4; i++) {
   17840       _vecA_32 = newTemp(Ity_I32);
   17841       _vecB_32 = newTemp(Ity_I32);
   17842       res_32   = newTemp(Ity_I32);
   17843       switch (i) {
   17844       case 0:
   17845          assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
   17846          assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
   17847          break;
   17848       case 1:
   17849          assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
   17850          assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
   17851          break;
   17852       case 2:
   17853          assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
   17854          assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
   17855          break;
   17856       case 3:
   17857          assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
   17858          assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
   17859          break;
   17860       }
   17861 
   17862       assign(res_32, binop( Iop_Add32,
   17863                             binop( Iop_Add32,
   17864                                    binop ( Iop_Add32,
   17865                                            mkexpr(_vecA_32),
   17866                                            mkexpr(_vecB_32) ),
   17867                                    (i == 0) ? mkU32(0) : mkexpr(carry) ),
   17868                             (i == 0) ? cin : mkU32(0) ) );
   17869       if (modulo) {
   17870          result = newTemp(Ity_V128);
   17871          assign(result, binop( Iop_OrV128,
   17872                               (i == 0) ? binop( Iop_64HLtoV128,
   17873                                                 mkU64(0),
   17874                                                 mkU64(0) ) : mkexpr(tmp_result),
   17875                               binop( Iop_ShlV128,
   17876                                      binop( Iop_64HLtoV128,
   17877                                             mkU64(0),
   17878                                             binop( Iop_32HLto64,
   17879                                                    mkU32(0),
   17880                                                    mkexpr(res_32) ) ),
   17881                                      mkU8(i * 32) ) ) );
   17882          tmp_result = newTemp(Ity_V128);
   17883          assign(tmp_result, mkexpr(result));
   17884       }
   17885       carry = newTemp(Ity_I32);
   17886       assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U,
   17887                                             mkexpr(res_32),
   17888                                             mkexpr(_vecA_32 ) ) ) );
   17889    }
   17890    if (modulo)
   17891       return result;
   17892    else
   17893       return carry;
   17894 }
   17895 
   17896 
   17897 static Bool dis_av_quad ( UInt theInstr )
   17898 {
   17899    /* VX-Form */
   17900    UChar opc1     = ifieldOPC(theInstr);
   17901    UChar vRT_addr = ifieldRegDS(theInstr);
   17902    UChar vRA_addr = ifieldRegA(theInstr);
   17903    UChar vRB_addr = ifieldRegB(theInstr);
   17904    UChar vRC_addr;
   17905    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17906 
   17907    IRTemp vA    = newTemp(Ity_V128);
   17908    IRTemp vB    = newTemp(Ity_V128);
   17909    IRTemp vC    = IRTemp_INVALID;
   17910    IRTemp cin    = IRTemp_INVALID;
   17911    assign( vA, getVReg(vRA_addr));
   17912    assign( vB, getVReg(vRB_addr));
   17913 
   17914    if (opc1 != 0x4) {
   17915       vex_printf("dis_av_quad(ppc)(instr)\n");
   17916       return False;
   17917    }
   17918 
   17919    switch (opc2) {
   17920    case 0x140:  // vaddcuq
   17921      DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   17922      putVReg( vRT_addr, unop( Iop_32UtoV128,
   17923                               mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   17924                                                                mkexpr(vB),
   17925                                                                mkU32(0), False) ) ) );
   17926      return True;
   17927    case 0x100: // vadduqm
   17928       DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   17929       putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   17930                                                           mkexpr(vB), mkU32(0), True) ) );
   17931       return True;
   17932    case 0x540: // vsubcuq
   17933       DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   17934       putVReg( vRT_addr,
   17935                unop( Iop_32UtoV128,
   17936                      mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   17937                                                       unop( Iop_NotV128,
   17938                                                             mkexpr(vB) ),
   17939                                                       mkU32(1), False) ) ) );
   17940       return True;
   17941    case 0x500: // vsubuqm
   17942       DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   17943       putVReg( vRT_addr,
   17944                mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   17945                                                 unop( Iop_NotV128, mkexpr(vB) ),
   17946                                                 mkU32(1), True) ) );
   17947       return True;
   17948    case 0x054C: // vbpermq
   17949    {
   17950 #define BPERMD_IDX_MASK 0x00000000000000FFULL
   17951 #define BPERMD_BIT_MASK 0x8000000000000000ULL
   17952       int i;
   17953       IRExpr * vB_expr = mkexpr(vB);
   17954       IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
   17955       DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   17956       for (i = 0; i < 16; i++) {
   17957          IRTemp idx_tmp = newTemp( Ity_V128 );
   17958          IRTemp perm_bit = newTemp( Ity_V128 );
   17959          IRTemp idx = newTemp( Ity_I8 );
   17960          IRTemp idx_LT127 = newTemp( Ity_I1 );
   17961          IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
   17962 
   17963          assign( idx_tmp,
   17964                  binop( Iop_AndV128,
   17965                         binop( Iop_64HLtoV128,
   17966                                mkU64(0),
   17967                                mkU64(BPERMD_IDX_MASK) ),
   17968                         vB_expr ) );
   17969          assign( idx_LT127,
   17970                  binop( Iop_CmpEQ32,
   17971                         unop ( Iop_64to32,
   17972                                unop( Iop_V128to64, binop( Iop_ShrV128,
   17973                                                           mkexpr(idx_tmp),
   17974                                                           mkU8(7) ) ) ),
   17975                         mkU32(0) ) );
   17976 
   17977          /* Below, we set idx to determine which bit of vA to use for the
   17978           * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
   17979           */
   17980          assign( idx,
   17981                  binop( Iop_And8,
   17982                         unop( Iop_1Sto8,
   17983                               mkexpr(idx_LT127) ),
   17984                         unop( Iop_32to8,
   17985                               unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
   17986 
   17987          assign( idx_LT127_ity128,
   17988                  binop( Iop_64HLtoV128,
   17989                         mkU64(0),
   17990                         unop( Iop_32Uto64,
   17991                               unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
   17992          assign( perm_bit,
   17993                  binop( Iop_AndV128,
   17994                         mkexpr( idx_LT127_ity128 ),
   17995                         binop( Iop_ShrV128,
   17996                                binop( Iop_AndV128,
   17997                                       binop (Iop_64HLtoV128,
   17998                                              mkU64( BPERMD_BIT_MASK ),
   17999                                              mkU64(0)),
   18000                                       binop( Iop_ShlV128,
   18001                                              mkexpr( vA ),
   18002                                              mkexpr( idx ) ) ),
   18003                                mkU8( 127 ) ) ) );
   18004          res = binop( Iop_OrV128,
   18005                       res,
   18006                       binop( Iop_ShlV128,
   18007                              mkexpr( perm_bit ),
   18008                              mkU8( i + 64 ) ) );
   18009          vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
   18010       }
   18011       putVReg( vRT_addr, res);
   18012       return True;
   18013 #undef BPERMD_IDX_MASK
   18014 #undef BPERMD_BIT_MASK
   18015    }
   18016 
   18017    default:
   18018       break;  // fall through
   18019    }
   18020 
   18021    opc2     = IFIELD( theInstr, 0, 6 );
   18022    vRC_addr = ifieldRegC(theInstr);
   18023    vC = newTemp(Ity_V128);
   18024    cin = newTemp(Ity_I32);
   18025    switch (opc2) {
   18026       case 0x3D: // vaddecuq
   18027          assign( vC, getVReg(vRC_addr));
   18028          DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   18029              vRC_addr);
   18030          assign(cin, binop( Iop_And32,
   18031                             unop( Iop_64to32,
   18032                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   18033                             mkU32(1) ) );
   18034          putVReg( vRT_addr,
   18035                   unop( Iop_32UtoV128,
   18036                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
   18037                                                          mkexpr(cin),
   18038                                                          False) ) ) );
   18039          return True;
   18040       case 0x3C: // vaddeuqm
   18041          assign( vC, getVReg(vRC_addr));
   18042          DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   18043              vRC_addr);
   18044          assign(cin, binop( Iop_And32,
   18045                             unop( Iop_64to32,
   18046                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   18047                             mkU32(1) ) );
   18048          putVReg( vRT_addr,
   18049                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
   18050                                                    mkexpr(cin),
   18051                                                    True) ) );
   18052          return True;
   18053       case 0x3F: // vsubecuq
   18054          assign( vC, getVReg(vRC_addr));
   18055          DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   18056              vRC_addr);
   18057          assign(cin, binop( Iop_And32,
   18058                             unop( Iop_64to32,
   18059                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   18060                             mkU32(1) ) );
   18061          putVReg( vRT_addr,
   18062                   unop( Iop_32UtoV128,
   18063                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   18064                                                          unop( Iop_NotV128,
   18065                                                                mkexpr(vB) ),
   18066                                                          mkexpr(cin),
   18067                                                          False) ) ) );
   18068          return True;
   18069       case 0x3E: // vsubeuqm
   18070          assign( vC, getVReg(vRC_addr));
   18071          DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   18072              vRC_addr);
   18073          assign(cin, binop( Iop_And32,
   18074                             unop( Iop_64to32,
   18075                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   18076                             mkU32(1) ) );
   18077          putVReg( vRT_addr,
   18078                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   18079                                                    unop( Iop_NotV128, mkexpr(vB) ),
   18080                                                    mkexpr(cin),
   18081                                                    True) ) );
   18082          return True;
   18083       default:
   18084          vex_printf("dis_av_quad(ppc)(opc2.2)\n");
   18085          return False;
   18086    }
   18087 
   18088    return True;
   18089 }
   18090 
   18091 
   18092 /*
   18093   AltiVec BCD Arithmetic instructions.
   18094   These instructions modify CR6 for various conditions in the result,
   18095   including when an overflow occurs.  We could easily detect all conditions
   18096   except when an overflow occurs.  But since we can't be 100% accurate
   18097   in our emulation of CR6, it seems best to just not support it all.
   18098 */
   18099 static Bool dis_av_bcd ( UInt theInstr )
   18100 {
   18101    /* VX-Form */
   18102    UChar opc1     = ifieldOPC(theInstr);
   18103    UChar vRT_addr = ifieldRegDS(theInstr);
   18104    UChar vRA_addr = ifieldRegA(theInstr);
   18105    UChar vRB_addr = ifieldRegB(theInstr);
   18106    UChar ps       = IFIELD( theInstr, 9, 1 );
   18107    UInt  opc2     = IFIELD( theInstr, 0, 9 );
   18108 
   18109    IRTemp vA    = newTemp(Ity_V128);
   18110    IRTemp vB    = newTemp(Ity_V128);
   18111    IRTemp dst    = newTemp(Ity_V128);
   18112    assign( vA, getVReg(vRA_addr));
   18113    assign( vB, getVReg(vRB_addr));
   18114 
   18115    if (opc1 != 0x4) {
   18116       vex_printf("dis_av_bcd(ppc)(instr)\n");
   18117       return False;
   18118    }
   18119 
   18120    switch (opc2) {
   18121    case 0x1:  // bcdadd
   18122      DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
   18123      assign( dst, triop( Iop_BCDAdd, mkexpr( vA ),
   18124                          mkexpr( vB ), mkU8( ps ) ) );
   18125      putVReg( vRT_addr, mkexpr(dst));
   18126      return True;
   18127 
   18128    case 0x41:  // bcdsub
   18129      DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
   18130      assign( dst, triop( Iop_BCDSub, mkexpr( vA ),
   18131                          mkexpr( vB ), mkU8( ps ) ) );
   18132      putVReg( vRT_addr, mkexpr(dst));
   18133      return True;
   18134 
   18135    default:
   18136       vex_printf("dis_av_bcd(ppc)(opc2)\n");
   18137       return False;
   18138    }
   18139    return True;
   18140 }
   18141 
   18142 /*
   18143   AltiVec Floating Point Arithmetic Instructions
   18144 */
   18145 static Bool dis_av_fp_arith ( UInt theInstr )
   18146 {
   18147    /* VA-Form */
   18148    UChar opc1     = ifieldOPC(theInstr);
   18149    UChar vD_addr  = ifieldRegDS(theInstr);
   18150    UChar vA_addr  = ifieldRegA(theInstr);
   18151    UChar vB_addr  = ifieldRegB(theInstr);
   18152    UChar vC_addr  = ifieldRegC(theInstr);
   18153    UInt  opc2=0;
   18154 
   18155    IRTemp vA = newTemp(Ity_V128);
   18156    IRTemp vB = newTemp(Ity_V128);
   18157    IRTemp vC = newTemp(Ity_V128);
   18158    assign( vA, getVReg(vA_addr));
   18159    assign( vB, getVReg(vB_addr));
   18160    assign( vC, getVReg(vC_addr));
   18161 
   18162    if (opc1 != 0x4) {
   18163       vex_printf("dis_av_fp_arith(ppc)(instr)\n");
   18164       return False;
   18165    }
   18166 
   18167    IRTemp rm = newTemp(Ity_I32);
   18168    assign(rm, get_IR_roundingmode());
   18169 
   18170    opc2 = IFIELD( theInstr, 0, 6 );
   18171    switch (opc2) {
   18172    case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
   18173       DIP("vmaddfp v%d,v%d,v%d,v%d\n",
   18174           vD_addr, vA_addr, vC_addr, vB_addr);
   18175       putVReg( vD_addr,
   18176                triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
   18177                      mkexpr(vB),
   18178                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18179                            mkexpr(vA), mkexpr(vC))) );
   18180       return True;
   18181 
   18182    case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
   18183       DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
   18184           vD_addr, vA_addr, vC_addr, vB_addr);
   18185       putVReg( vD_addr,
   18186                triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
   18187                      mkexpr(vB),
   18188                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18189                            mkexpr(vA), mkexpr(vC))) );
   18190       return True;
   18191    }
   18192 
   18193    default:
   18194      break; // Fall through...
   18195    }
   18196 
   18197    opc2 = IFIELD( theInstr, 0, 11 );
   18198    switch (opc2) {
   18199    case 0x00A: // vaddfp (Add FP, AV p137)
   18200       DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   18201       putVReg( vD_addr, triop(Iop_Add32Fx4,
   18202                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
   18203       return True;
   18204 
   18205   case 0x04A: // vsubfp (Subtract FP, AV p261)
   18206       DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   18207       putVReg( vD_addr, triop(Iop_Sub32Fx4,
   18208                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
   18209       return True;
   18210 
   18211    case 0x40A: // vmaxfp (Maximum FP, AV p178)
   18212       DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   18213       putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
   18214       return True;
   18215 
   18216    case 0x44A: // vminfp (Minimum FP, AV p187)
   18217       DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   18218       putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
   18219       return True;
   18220 
   18221    default:
   18222       break; // Fall through...
   18223    }
   18224 
   18225 
   18226    if (vA_addr != 0) {
   18227       vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
   18228       return False;
   18229    }
   18230 
   18231    switch (opc2) {
   18232    case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
   18233       DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
   18234       putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) );
   18235       return True;
   18236 
   18237    case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
   18238       DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
   18239       putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) );
   18240       return True;
   18241 
   18242    case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
   18243       DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
   18244       DIP(" => not implemented\n");
   18245       return False;
   18246 
   18247    case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
   18248       DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
   18249       DIP(" => not implemented\n");
   18250       return False;
   18251 
   18252    default:
   18253       vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
   18254       return False;
   18255    }
   18256    return True;
   18257 }
   18258 
   18259 /*
   18260   AltiVec Floating Point Compare Instructions
   18261 */
   18262 static Bool dis_av_fp_cmp ( UInt theInstr )
   18263 {
   18264    /* VXR-Form */
   18265    UChar opc1     = ifieldOPC(theInstr);
   18266    UChar vD_addr  = ifieldRegDS(theInstr);
   18267    UChar vA_addr  = ifieldRegA(theInstr);
   18268    UChar vB_addr  = ifieldRegB(theInstr);
   18269    UChar flag_rC  = ifieldBIT10(theInstr);
   18270    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   18271 
   18272    Bool cmp_bounds = False;
   18273 
   18274    IRTemp vA = newTemp(Ity_V128);
   18275    IRTemp vB = newTemp(Ity_V128);
   18276    IRTemp vD = newTemp(Ity_V128);
   18277    assign( vA, getVReg(vA_addr));
   18278    assign( vB, getVReg(vB_addr));
   18279 
   18280    if (opc1 != 0x4) {
   18281       vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
   18282       return False;
   18283    }
   18284 
   18285    switch (opc2) {
   18286    case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
   18287       DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   18288                                       vD_addr, vA_addr, vB_addr);
   18289       assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   18290       break;
   18291 
   18292    case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
   18293       DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   18294                                       vD_addr, vA_addr, vB_addr);
   18295       assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   18296       break;
   18297 
   18298    case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
   18299       DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   18300                                       vD_addr, vA_addr, vB_addr);
   18301       assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   18302       break;
   18303 
   18304    case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
   18305       IRTemp gt      = newTemp(Ity_V128);
   18306       IRTemp lt      = newTemp(Ity_V128);
   18307       IRTemp zeros   = newTemp(Ity_V128);
   18308       DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   18309                                      vD_addr, vA_addr, vB_addr);
   18310       cmp_bounds = True;
   18311       assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
   18312 
   18313       /* Note: making use of fact that the ppc backend for compare insns
   18314          return zero'd lanes if either of the corresponding arg lanes is
   18315          a nan.
   18316 
   18317          Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
   18318          need this for the other compares too (vcmpeqfp etc)...
   18319          Better still, tighten down the spec for compare irops.
   18320        */
   18321       assign( gt, unop(Iop_NotV128,
   18322                        binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
   18323       assign( lt, unop(Iop_NotV128,
   18324                        binop(Iop_CmpGE32Fx4, mkexpr(vA),
   18325                              triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
   18326                                    mkexpr(zeros),
   18327                                    mkexpr(vB)))) );
   18328 
   18329       // finally, just shift gt,lt to correct position
   18330       assign( vD, binop(Iop_ShlN32x4,
   18331                         binop(Iop_OrV128,
   18332                               binop(Iop_AndV128, mkexpr(gt),
   18333                                     unop(Iop_Dup32x4, mkU32(0x2))),
   18334                               binop(Iop_AndV128, mkexpr(lt),
   18335                                     unop(Iop_Dup32x4, mkU32(0x1)))),
   18336                         mkU8(30)) );
   18337       break;
   18338    }
   18339 
   18340    default:
   18341       vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
   18342       return False;
   18343    }
   18344 
   18345    putVReg( vD_addr, mkexpr(vD) );
   18346 
   18347    if (flag_rC) {
   18348       set_AV_CR6( mkexpr(vD), !cmp_bounds );
   18349    }
   18350    return True;
   18351 }
   18352 
   18353 /*
   18354   AltiVec Floating Point Convert/Round Instructions
   18355 */
   18356 static Bool dis_av_fp_convert ( UInt theInstr )
   18357 {
   18358    /* VX-Form */
   18359    UChar opc1     = ifieldOPC(theInstr);
   18360    UChar vD_addr  = ifieldRegDS(theInstr);
   18361    UChar UIMM_5   = ifieldRegA(theInstr);
   18362    UChar vB_addr  = ifieldRegB(theInstr);
   18363    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   18364 
   18365    IRTemp vB        = newTemp(Ity_V128);
   18366    IRTemp vScale    = newTemp(Ity_V128);
   18367    IRTemp vInvScale = newTemp(Ity_V128);
   18368 
   18369    float scale, inv_scale;
   18370 
   18371    assign( vB, getVReg(vB_addr));
   18372 
   18373    /* scale = 2^UIMM, cast to float, reinterpreted as uint */
   18374    scale = (float)( (unsigned int) 1<<UIMM_5 );
   18375    assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
   18376    inv_scale = 1/scale;
   18377    assign( vInvScale,
   18378            unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
   18379 
   18380    if (opc1 != 0x4) {
   18381       vex_printf("dis_av_fp_convert(ppc)(instr)\n");
   18382       return False;
   18383    }
   18384 
   18385    switch (opc2) {
   18386    case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
   18387       DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18388       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18389                               unop(Iop_I32UtoFx4, mkexpr(vB)),
   18390                               mkexpr(vInvScale)) );
   18391       return True;
   18392 
   18393    case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
   18394       DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18395 
   18396       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18397                               unop(Iop_I32StoFx4, mkexpr(vB)),
   18398                               mkexpr(vInvScale)) );
   18399       return True;
   18400 
   18401    case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
   18402       DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18403       putVReg( vD_addr,
   18404                unop(Iop_QFtoI32Ux4_RZ,
   18405                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18406                           mkexpr(vB), mkexpr(vScale))) );
   18407       return True;
   18408 
   18409    case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
   18410       DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18411       putVReg( vD_addr,
   18412                unop(Iop_QFtoI32Sx4_RZ,
   18413                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18414                            mkexpr(vB), mkexpr(vScale))) );
   18415       return True;
   18416 
   18417    default:
   18418      break;    // Fall through...
   18419    }
   18420 
   18421    if (UIMM_5 != 0) {
   18422       vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
   18423       return False;
   18424    }
   18425 
   18426    switch (opc2) {
   18427    case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
   18428       DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
   18429       putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
   18430       break;
   18431 
   18432    case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
   18433       DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
   18434       putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
   18435       break;
   18436 
   18437    case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
   18438       DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
   18439       putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
   18440       break;
   18441 
   18442    case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
   18443       DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
   18444       putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
   18445       break;
   18446 
   18447    default:
   18448       vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
   18449       return False;
   18450    }
   18451    return True;
   18452 }
   18453 
   18454 static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
   18455                                        const VexAbiInfo* vbi,
   18456                                        /*OUT*/DisResult* dres,
   18457                                        Bool (*resteerOkFn)(void*,Addr),
   18458                                        void* callback_opaque )
   18459 {
   18460    UInt   opc2      = IFIELD( theInstr, 1, 10 );
   18461 
   18462    switch (opc2) {
   18463    case 0x28E: {        //tbegin.
   18464       /* The current implementation is to just fail the tbegin and execute
   18465        * the failure path.  The failure path is assumed to be functionaly
   18466        * equivalent to the transactional path with the needed data locking
   18467        * to ensure correctness.  The tend is just a noop and shouldn't
   18468        * actually get executed.
   18469        *   1) set cr0 to 0x2
   18470        *   2) Initialize TFHAR to CIA+4
   18471        *   3) Initialize TEXASR
   18472        *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
   18473        *   5) Continue executing at the next instruction.
   18474        */
   18475       UInt R = IFIELD( theInstr, 21, 1 );
   18476 
   18477       ULong tm_reason;
   18478       UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
   18479                                * or treclaim.
   18480                                */
   18481       UInt persistant = 1;    /* set persistant since we are always failing
   18482                                * the tbegin.
   18483                                */
   18484       UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
   18485                                  as the reason for failing the trasaction */
   18486       UInt tm_exact   = 1;    /* have exact address for failure */
   18487 
   18488       DIP("tbegin. %d\n", R);
   18489 
   18490       /* Set the CR0 field to indicate the tbegin failed.  Then let
   18491        * the code do the branch to the failure path.
   18492        *
   18493        * 000 || 0  Transaction initiation successful,
   18494        *           unnested (Transaction state of
   18495        *           Non-transactional prior to tbegin.)
   18496        * 010 || 0  Transaction initiation successful, nested
   18497        *           (Transaction state of Transactional
   18498        *           prior to tbegin.)
   18499        * 001 || 0  Transaction initiation unsuccessful,
   18500        *           (Transaction state of Suspended prior
   18501        *           to tbegin.)
   18502        */
   18503       putCR321( 0, mkU8( 0x2 ) );
   18504 
   18505       tm_reason = generate_TMreason( failure_code, persistant,
   18506                                      nest_overflow, tm_exact );
   18507 
   18508       storeTMfailure( guest_CIA_curr_instr, tm_reason,
   18509                       guest_CIA_curr_instr+4 );
   18510 
   18511       return True;
   18512 
   18513       break;
   18514    }
   18515 
   18516    case 0x2AE: {        //tend.
   18517       /* The tend. is just a noop.  Do nothing */
   18518       UInt A = IFIELD( theInstr, 25, 1 );
   18519 
   18520       DIP("tend. %d\n", A);
   18521       break;
   18522    }
   18523 
   18524    case 0x2EE: {        //tsr.
   18525       /* The tsr. is just a noop.  Do nothing */
   18526       UInt L = IFIELD( theInstr, 21, 1 );
   18527 
   18528       DIP("tsr. %d\n", L);
   18529       break;
   18530    }
   18531 
   18532    case 0x2CE: {        //tcheck.
   18533       /* The tcheck. is just a noop.  Do nothing */
   18534       UInt BF = IFIELD( theInstr, 25, 1 );
   18535 
   18536       DIP("tcheck. %d\n", BF);
   18537       break;
   18538    }
   18539 
   18540    case 0x30E: {        //tbortwc.
   18541       /* The tabortwc. is just a noop.  Do nothing */
   18542       UInt TO = IFIELD( theInstr, 25, 1 );
   18543       UInt RA = IFIELD( theInstr, 16, 5 );
   18544       UInt RB = IFIELD( theInstr, 11, 5 );
   18545 
   18546       DIP("tabortwc. %d,%d,%d\n", TO, RA, RB);
   18547       break;
   18548    }
   18549 
   18550    case 0x32E: {        //tbortdc.
   18551       /* The tabortdc. is just a noop.  Do nothing */
   18552       UInt TO = IFIELD( theInstr, 25, 1 );
   18553       UInt RA = IFIELD( theInstr, 16, 5 );
   18554       UInt RB = IFIELD( theInstr, 11, 5 );
   18555 
   18556       DIP("tabortdc. %d,%d,%d\n", TO, RA, RB);
   18557       break;
   18558    }
   18559 
   18560    case 0x34E: {        //tbortwci.
   18561       /* The tabortwci. is just a noop.  Do nothing */
   18562       UInt TO = IFIELD( theInstr, 25, 1 );
   18563       UInt RA = IFIELD( theInstr, 16, 5 );
   18564       UInt SI = IFIELD( theInstr, 11, 5 );
   18565 
   18566       DIP("tabortwci. %d,%d,%d\n", TO, RA, SI);
   18567       break;
   18568    }
   18569 
   18570    case 0x36E: {        //tbortdci.
   18571       /* The tabortdci. is just a noop.  Do nothing */
   18572       UInt TO = IFIELD( theInstr, 25, 1 );
   18573       UInt RA = IFIELD( theInstr, 16, 5 );
   18574       UInt SI = IFIELD( theInstr, 11, 5 );
   18575 
   18576       DIP("tabortdci. %d,%d,%d\n", TO, RA, SI);
   18577       break;
   18578    }
   18579 
   18580    case 0x38E: {        //tbort.
   18581       /* The tabort. is just a noop.  Do nothing */
   18582       UInt RA = IFIELD( theInstr, 16, 5 );
   18583 
   18584       DIP("tabort. %d\n", RA);
   18585       break;
   18586    }
   18587 
   18588    case 0x3AE: {        //treclaim.
   18589       /* The treclaim. is just a noop.  Do nothing */
   18590       UInt RA = IFIELD( theInstr, 16, 5 );
   18591 
   18592       DIP("treclaim. %d\n", RA);
   18593       break;
   18594    }
   18595 
   18596    case 0x3EE: {        //trechkpt.
   18597       /* The trechkpt. is just a noop.  Do nothing */
   18598       DIP("trechkpt.\n");
   18599       break;
   18600    }
   18601 
   18602    default:
   18603       vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
   18604       return False;
   18605    }
   18606 
   18607    return True;
   18608 }
   18609 
   18610 
   18611 /* The 0x3C primary opcode (VSX category) uses several different forms of
   18612  * extended opcodes:
   18613  *   o XX2-form:
   18614  *      - [10:2] (IBM notation [21:29])
   18615  *   o XX3-form variants:
   18616  *       - variant 1: [10:3] (IBM notation [21:28])
   18617  *       - variant 2: [9:3] (IBM notation [22:28])
   18618  *       - variant 3: [7:3] (IBM notation [24:28])
   18619  *   o XX-4 form:
   18620  *      - [10:6] (IBM notation [21:25])
   18621  *
   18622  * The XX2-form needs bit 0 masked from the standard extended opcode
   18623  * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
   18624  * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
   18625  * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
   18626  * front end since their encoding does not begin at bit 21 like the standard
   18627  * format.
   18628  *
   18629  * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
   18630  * secondary opcode for such VSX instructions.
   18631  *
   18632 */
   18633 
   18634 
   18635 struct vsx_insn {
   18636    UInt opcode;
   18637    const HChar * name;
   18638 };
   18639 
   18640 //  ATTENTION:  Keep this array sorted on the opcocde!!!
   18641 static struct vsx_insn vsx_all[] = {
   18642       { 0x0, "xsaddsp" },
   18643       { 0x4, "xsmaddasp" },
   18644       { 0x8, "xxsldwi" },
   18645       { 0x14, "xsrsqrtesp" },
   18646       { 0x16, "xssqrtsp" },
   18647       { 0x18, "xxsel" },
   18648       { 0x20, "xssubsp" },
   18649       { 0x24, "xsmaddmsp" },
   18650       { 0x28, "xxpermdi" },
   18651       { 0x34, "xsresp" },
   18652       { 0x40, "xsmulsp" },
   18653       { 0x44, "xsmsubasp" },
   18654       { 0x48, "xxmrghw" },
   18655       { 0x60, "xsdivsp" },
   18656       { 0x64, "xsmsubmsp" },
   18657       { 0x80, "xsadddp" },
   18658       { 0x84, "xsmaddadp" },
   18659       { 0x8c, "xscmpudp" },
   18660       { 0x90, "xscvdpuxws" },
   18661       { 0x92, "xsrdpi" },
   18662       { 0x94, "xsrsqrtedp" },
   18663       { 0x96, "xssqrtdp" },
   18664       { 0xa0, "xssubdp" },
   18665       { 0xa4, "xsmaddmdp" },
   18666       { 0xac, "xscmpodp" },
   18667       { 0xb0, "xscvdpsxws" },
   18668       { 0xb2, "xsrdpiz" },
   18669       { 0xb4, "xsredp" },
   18670       { 0xc0, "xsmuldp" },
   18671       { 0xc4, "xsmsubadp" },
   18672       { 0xc8, "xxmrglw" },
   18673       { 0xd2, "xsrdpip" },
   18674       { 0xd4, "xstsqrtdp" },
   18675       { 0xd6, "xsrdpic" },
   18676       { 0xe0, "xsdivdp" },
   18677       { 0xe4, "xsmsubmdp" },
   18678       { 0xf2, "xsrdpim" },
   18679       { 0xf4, "xstdivdp" },
   18680       { 0x100, "xvaddsp" },
   18681       { 0x104, "xvmaddasp" },
   18682       { 0x10c, "xvcmpeqsp" },
   18683       { 0x110, "xvcvspuxws" },
   18684       { 0x112, "xvrspi" },
   18685       { 0x114, "xvrsqrtesp" },
   18686       { 0x116, "xvsqrtsp" },
   18687       { 0x120, "xvsubsp" },
   18688       { 0x124, "xvmaddmsp" },
   18689       { 0x12c, "xvcmpgtsp" },
   18690       { 0x130, "xvcvspsxws" },
   18691       { 0x132, "xvrspiz" },
   18692       { 0x134, "xvresp" },
   18693       { 0x140, "xvmulsp" },
   18694       { 0x144, "xvmsubasp" },
   18695       { 0x148, "xxspltw" },
   18696       { 0x14c, "xvcmpgesp" },
   18697       { 0x150, "xvcvuxwsp" },
   18698       { 0x152, "xvrspip" },
   18699       { 0x154, "xvtsqrtsp" },
   18700       { 0x156, "xvrspic" },
   18701       { 0x160, "xvdivsp" },
   18702       { 0x164, "xvmsubmsp" },
   18703       { 0x170, "xvcvsxwsp" },
   18704       { 0x172, "xvrspim" },
   18705       { 0x174, "xvtdivsp" },
   18706       { 0x180, "xvadddp" },
   18707       { 0x184, "xvmaddadp" },
   18708       { 0x18c, "xvcmpeqdp" },
   18709       { 0x190, "xvcvdpuxws" },
   18710       { 0x192, "xvrdpi" },
   18711       { 0x194, "xvrsqrtedp" },
   18712       { 0x196, "xvsqrtdp" },
   18713       { 0x1a0, "xvsubdp" },
   18714       { 0x1a4, "xvmaddmdp" },
   18715       { 0x1ac, "xvcmpgtdp" },
   18716       { 0x1b0, "xvcvdpsxws" },
   18717       { 0x1b2, "xvrdpiz" },
   18718       { 0x1b4, "xvredp" },
   18719       { 0x1c0, "xvmuldp" },
   18720       { 0x1c4, "xvmsubadp" },
   18721       { 0x1cc, "xvcmpgedp" },
   18722       { 0x1d0, "xvcvuxwdp" },
   18723       { 0x1d2, "xvrdpip" },
   18724       { 0x1d4, "xvtsqrtdp" },
   18725       { 0x1d6, "xvrdpic" },
   18726       { 0x1e0, "xvdivdp" },
   18727       { 0x1e4, "xvmsubmdp" },
   18728       { 0x1f0, "xvcvsxwdp" },
   18729       { 0x1f2, "xvrdpim" },
   18730       { 0x1f4, "xvtdivdp" },
   18731       { 0x204, "xsnmaddasp" },
   18732       { 0x208, "xxland" },
   18733       { 0x212, "xscvdpsp" },
   18734       { 0x216, "xscvdpspn" },
   18735       { 0x224, "xsnmaddmsp" },
   18736       { 0x228, "xxlandc" },
   18737       { 0x232, "xxrsp" },
   18738       { 0x244, "xsnmsubasp" },
   18739       { 0x248, "xxlor" },
   18740       { 0x250, "xscvuxdsp" },
   18741       { 0x264, "xsnmsubmsp" },
   18742       { 0x268, "xxlxor" },
   18743       { 0x270, "xscvsxdsp" },
   18744       { 0x280, "xsmaxdp" },
   18745       { 0x284, "xsnmaddadp" },
   18746       { 0x288, "xxlnor" },
   18747       { 0x290, "xscvdpuxds" },
   18748       { 0x292, "xscvspdp" },
   18749       { 0x296, "xscvspdpn" },
   18750       { 0x2a0, "xsmindp" },
   18751       { 0x2a4, "xsnmaddmdp" },
   18752       { 0x2a8, "xxlorc" },
   18753       { 0x2b0, "xscvdpsxds" },
   18754       { 0x2b2, "xsabsdp" },
   18755       { 0x2c0, "xscpsgndp" },
   18756       { 0x2c4, "xsnmsubadp" },
   18757       { 0x2c8, "xxlnand" },
   18758       { 0x2d0, "xscvuxddp" },
   18759       { 0x2d2, "xsnabsdp" },
   18760       { 0x2e4, "xsnmsubmdp" },
   18761       { 0x2e8, "xxleqv" },
   18762       { 0x2f0, "xscvsxddp" },
   18763       { 0x2f2, "xsnegdp" },
   18764       { 0x300, "xvmaxsp" },
   18765       { 0x304, "xvnmaddasp" },
   18766       { 0x30c, "xvcmpeqsp." },
   18767       { 0x310, "xvcvspuxds" },
   18768       { 0x312, "xvcvdpsp" },
   18769       { 0x320, "xvminsp" },
   18770       { 0x324, "xvnmaddmsp" },
   18771       { 0x32c, "xvcmpgtsp." },
   18772       { 0x330, "xvcvspsxds" },
   18773       { 0x332, "xvabssp" },
   18774       { 0x340, "xvcpsgnsp" },
   18775       { 0x344, "xvnmsubasp" },
   18776       { 0x34c, "xvcmpgesp." },
   18777       { 0x350, "xvcvuxdsp" },
   18778       { 0x352, "xvnabssp" },
   18779       { 0x364, "xvnmsubmsp" },
   18780       { 0x370, "xvcvsxdsp" },
   18781       { 0x372, "xvnegsp" },
   18782       { 0x380, "xvmaxdp" },
   18783       { 0x384, "xvnmaddadp" },
   18784       { 0x38c, "xvcmpeqdp." },
   18785       { 0x390, "xvcvdpuxds" },
   18786       { 0x392, "xvcvspdp" },
   18787       { 0x3a0, "xvmindp" },
   18788       { 0x3a4, "xvnmaddmdp" },
   18789       { 0x3ac, "xvcmpgtdp." },
   18790       { 0x3b0, "xvcvdpsxds" },
   18791       { 0x3b2, "xvabsdp" },
   18792       { 0x3c0, "xvcpsgndp" },
   18793       { 0x3c4, "xvnmsubadp" },
   18794       { 0x3cc, "xvcmpgedp." },
   18795       { 0x3d0, "xvcvuxddp" },
   18796       { 0x3d2, "xvnabsdp" },
   18797       { 0x3e4, "xvnmsubmdp" },
   18798       { 0x3f0, "xvcvsxddp" },
   18799       { 0x3f2, "xvnegdp" }
   18800 };
   18801 #define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all)
   18802 
   18803 
   18804 // ATTENTION: This search function assumes vsx_all array is sorted.
   18805 static Int findVSXextOpCode(UInt opcode)
   18806 {
   18807    Int low, mid, high;
   18808    low = 0;
   18809    high = VSX_ALL_LEN - 1;
   18810    while (low <= high) {
   18811       mid = (low + high)/2;
   18812       if (opcode < vsx_all[mid].opcode)
   18813          high = mid - 1;
   18814       else if (opcode > vsx_all[mid].opcode)
   18815          low = mid + 1;
   18816       else
   18817          return mid;
   18818    }
   18819    return -1;
   18820 }
   18821 
   18822 
   18823 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
   18824  * passed, and we then try to match it up with one of the VSX forms
   18825  * below.
   18826  */
   18827 static UInt get_VSX60_opc2(UInt opc2_full)
   18828 {
   18829 #define XX2_MASK 0x000003FE
   18830 #define XX3_1_MASK 0x000003FC
   18831 #define XX3_2_MASK 0x000001FC
   18832 #define XX3_3_MASK 0x0000007C
   18833 #define XX4_MASK 0x00000018
   18834    Int ret;
   18835    UInt vsxExtOpcode = 0;
   18836 
   18837    if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
   18838       vsxExtOpcode = vsx_all[ret].opcode;
   18839    else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
   18840       vsxExtOpcode = vsx_all[ret].opcode;
   18841    else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
   18842       vsxExtOpcode = vsx_all[ret].opcode;
   18843    else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
   18844       vsxExtOpcode = vsx_all[ret].opcode;
   18845    else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
   18846       vsxExtOpcode = vsx_all[ret].opcode;
   18847 
   18848    return vsxExtOpcode;
   18849 }
   18850 
   18851 /*------------------------------------------------------------*/
   18852 /*--- Disassemble a single instruction                     ---*/
   18853 /*------------------------------------------------------------*/
   18854 
   18855 /* Disassemble a single instruction into IR.  The instruction
   18856    is located in host memory at &guest_code[delta]. */
   18857 
   18858 static
   18859 DisResult disInstr_PPC_WRK (
   18860              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr ),
   18861              Bool         resteerCisOk,
   18862              void*        callback_opaque,
   18863              Long         delta64,
   18864              const VexArchInfo* archinfo,
   18865              const VexAbiInfo*  abiinfo,
   18866              Bool         sigill_diag
   18867           )
   18868 {
   18869    UChar     opc1;
   18870    UInt      opc2;
   18871    DisResult dres;
   18872    UInt      theInstr;
   18873    IRType    ty = mode64 ? Ity_I64 : Ity_I32;
   18874    Bool      allow_F  = False;
   18875    Bool      allow_V  = False;
   18876    Bool      allow_FX = False;
   18877    Bool      allow_GX = False;
   18878    Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
   18879    Bool      allow_DFP = False;
   18880    Bool      allow_isa_2_07 = False;
   18881    UInt      hwcaps = archinfo->hwcaps;
   18882    Long      delta;
   18883 
   18884    /* What insn variants are we supporting today? */
   18885    if (mode64) {
   18886       allow_F  = True;
   18887       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
   18888       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
   18889       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
   18890       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
   18891       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
   18892       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
   18893    } else {
   18894       allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
   18895       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
   18896       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
   18897       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
   18898       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
   18899       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
   18900       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
   18901    }
   18902 
   18903    /* The running delta */
   18904    delta = (Long)mkSzAddr(ty, (ULong)delta64);
   18905 
   18906    /* Set result defaults. */
   18907    dres.whatNext    = Dis_Continue;
   18908    dres.len         = 0;
   18909    dres.continueAt  = 0;
   18910    dres.jk_StopHere = Ijk_INVALID;
   18911 
   18912    /* At least this is simple on PPC32: insns are all 4 bytes long, and
   18913       4-aligned.  So just fish the whole thing out of memory right now
   18914       and have done. */
   18915    theInstr = getUIntPPCendianly( &guest_code[delta] );
   18916 
   18917    if (0) vex_printf("insn: 0x%x\n", theInstr);
   18918 
   18919    DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
   18920 
   18921    /* Spot "Special" instructions (see comment at top of file). */
   18922    {
   18923       const UChar* code = guest_code + delta;
   18924       /* Spot the 16-byte preamble:
   18925          32-bit mode:
   18926             5400183E  rlwinm 0,0,3,0,31
   18927             5400683E  rlwinm 0,0,13,0,31
   18928             5400E83E  rlwinm 0,0,29,0,31
   18929             5400983E  rlwinm 0,0,19,0,31
   18930          64-bit mode:
   18931             78001800  rotldi 0,0,3
   18932             78006800  rotldi 0,0,13
   18933             7800E802  rotldi 0,0,61
   18934             78009802  rotldi 0,0,51
   18935       */
   18936       UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
   18937       UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
   18938       UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
   18939       UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
   18940       Bool is_special_preamble = False;
   18941       if (getUIntPPCendianly(code+ 0) == word1 &&
   18942           getUIntPPCendianly(code+ 4) == word2 &&
   18943           getUIntPPCendianly(code+ 8) == word3 &&
   18944           getUIntPPCendianly(code+12) == word4) {
   18945          is_special_preamble = True;
   18946       } else if (! mode64 &&
   18947                  getUIntPPCendianly(code+ 0) == 0x54001800 &&
   18948                  getUIntPPCendianly(code+ 4) == 0x54006800 &&
   18949                  getUIntPPCendianly(code+ 8) == 0x5400E800 &&
   18950                  getUIntPPCendianly(code+12) == 0x54009800) {
   18951          static Bool reported = False;
   18952          if (!reported) {
   18953             vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
   18954             vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
   18955             reported = True;
   18956          }
   18957          is_special_preamble = True;
   18958       }
   18959       if (is_special_preamble) {
   18960          /* Got a "Special" instruction preamble.  Which one is it? */
   18961          if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
   18962             /* %R3 = client_request ( %R4 ) */
   18963             DIP("r3 = client_request ( %%r4 )\n");
   18964             delta += 20;
   18965             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
   18966             dres.jk_StopHere = Ijk_ClientReq;
   18967             dres.whatNext    = Dis_StopHere;
   18968             goto decode_success;
   18969          }
   18970          else
   18971          if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
   18972             /* %R3 = guest_NRADDR */
   18973             DIP("r3 = guest_NRADDR\n");
   18974             delta += 20;
   18975             dres.len = 20;
   18976             putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
   18977             goto decode_success;
   18978          }
   18979          else
   18980          if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
   18981             delta += 20;
   18982             if (host_endness == VexEndnessLE) {
   18983                 /*  branch-and-link-to-noredir %R12 */
   18984                 DIP("branch-and-link-to-noredir r12\n");
   18985                 putGST( PPC_GST_LR,
   18986                         mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
   18987                 putGST( PPC_GST_CIA, getIReg(12));
   18988             } else {
   18989                 /*  branch-and-link-to-noredir %R11 */
   18990                 DIP("branch-and-link-to-noredir r11\n");
   18991                 putGST( PPC_GST_LR,
   18992                         mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
   18993                 putGST( PPC_GST_CIA, getIReg(11));
   18994             }
   18995             dres.jk_StopHere = Ijk_NoRedir;
   18996             dres.whatNext    = Dis_StopHere;
   18997             goto decode_success;
   18998          }
   18999          else
   19000          if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
   19001             /* %R3 = guest_NRADDR_GPR2 */
   19002             DIP("r3 = guest_NRADDR_GPR2\n");
   19003             delta += 20;
   19004             dres.len = 20;
   19005             putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
   19006             goto decode_success;
   19007          }
   19008          else
   19009          if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
   19010             DIP("IR injection\n");
   19011             if (host_endness == VexEndnessBE)
   19012                vex_inject_ir(irsb, Iend_BE);
   19013             else
   19014                vex_inject_ir(irsb, Iend_LE);
   19015 
   19016             delta += 20;
   19017             dres.len = 20;
   19018 
   19019             // Invalidate the current insn. The reason is that the IRop we're
   19020             // injecting here can change. In which case the translation has to
   19021             // be redone. For ease of handling, we simply invalidate all the
   19022             // time.
   19023 
   19024             stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
   19025             stmt(IRStmt_Put(OFFB_CMLEN,   mkSzImm(ty, 20)));
   19026 
   19027             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
   19028             dres.whatNext    = Dis_StopHere;
   19029             dres.jk_StopHere = Ijk_InvalICache;
   19030             goto decode_success;
   19031          }
   19032          /* We don't know what it is.  Set opc1/opc2 so decode_failure
   19033             can print the insn following the Special-insn preamble. */
   19034          theInstr = getUIntPPCendianly(code+16);
   19035          opc1     = ifieldOPC(theInstr);
   19036          opc2     = ifieldOPClo10(theInstr);
   19037          goto decode_failure;
   19038          /*NOTREACHED*/
   19039       }
   19040    }
   19041 
   19042    opc1 = ifieldOPC(theInstr);
   19043    opc2 = ifieldOPClo10(theInstr);
   19044 
   19045    // Note: all 'reserved' bits must be cleared, else invalid
   19046    switch (opc1) {
   19047 
   19048    /* Integer Arithmetic Instructions */
   19049    case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
   19050    case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
   19051       if (dis_int_arith( theInstr )) goto decode_success;
   19052       goto decode_failure;
   19053 
   19054    /* Integer Compare Instructions */
   19055    case 0x0B: case 0x0A: // cmpi, cmpli
   19056       if (dis_int_cmp( theInstr )) goto decode_success;
   19057       goto decode_failure;
   19058 
   19059    /* Integer Logical Instructions */
   19060    case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
   19061    case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
   19062       if (dis_int_logic( theInstr )) goto decode_success;
   19063       goto decode_failure;
   19064 
   19065    /* Integer Rotate Instructions */
   19066    case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
   19067       if (dis_int_rot( theInstr )) goto decode_success;
   19068       goto decode_failure;
   19069 
   19070    /* 64bit Integer Rotate Instructions */
   19071    case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
   19072       if (!mode64) goto decode_failure;
   19073       if (dis_int_rot( theInstr )) goto decode_success;
   19074       goto decode_failure;
   19075 
   19076    /* Integer Load Instructions */
   19077    case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
   19078    case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
   19079    case 0x20: case 0x21:            // lwz,  lwzu
   19080       if (dis_int_load( theInstr )) goto decode_success;
   19081       goto decode_failure;
   19082 
   19083    /* Integer Store Instructions */
   19084    case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
   19085    case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
   19086       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   19087       goto decode_failure;
   19088 
   19089    /* Integer Load and Store Multiple Instructions */
   19090    case 0x2E: case 0x2F: // lmw, stmw
   19091       if (dis_int_ldst_mult( theInstr )) goto decode_success;
   19092       goto decode_failure;
   19093 
   19094    /* Branch Instructions */
   19095    case 0x12: case 0x10: // b, bc
   19096       if (dis_branch(theInstr, abiinfo, &dres,
   19097                                resteerOkFn, callback_opaque))
   19098          goto decode_success;
   19099       goto decode_failure;
   19100 
   19101    /* System Linkage Instructions */
   19102    case 0x11: // sc
   19103       if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
   19104       goto decode_failure;
   19105 
   19106    /* Trap Instructions */
   19107    case 0x02:    // tdi
   19108       if (!mode64) goto decode_failure;
   19109       if (dis_trapi(theInstr, &dres)) goto decode_success;
   19110       goto decode_failure;
   19111 
   19112    case 0x03:   // twi
   19113       if (dis_trapi(theInstr, &dres)) goto decode_success;
   19114       goto decode_failure;
   19115 
   19116    /* Floating Point Load Instructions */
   19117    case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
   19118    case 0x33:                       // lfdu
   19119       if (!allow_F) goto decode_noF;
   19120       if (dis_fp_load( theInstr )) goto decode_success;
   19121       goto decode_failure;
   19122 
   19123    /* Floating Point Store Instructions */
   19124    case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
   19125    case 0x37:                       // stfdux
   19126       if (!allow_F) goto decode_noF;
   19127       if (dis_fp_store( theInstr )) goto decode_success;
   19128       goto decode_failure;
   19129 
   19130       /* Floating Point Load Double Pair Instructions */
   19131    case 0x39: case 0x3D:
   19132       if (!allow_F) goto decode_noF;
   19133       if (dis_fp_pair( theInstr )) goto decode_success;
   19134       goto decode_failure;
   19135 
   19136    /* 128-bit Integer Load */
   19137    case 0x38:  // lq
   19138       if (dis_int_load( theInstr )) goto decode_success;
   19139       goto decode_failure;
   19140 
   19141    /* 64bit Integer Loads */
   19142    case 0x3A:  // ld, ldu, lwa
   19143       if (!mode64) goto decode_failure;
   19144       if (dis_int_load( theInstr )) goto decode_success;
   19145       goto decode_failure;
   19146 
   19147    case 0x3B:
   19148       if (!allow_F) goto decode_noF;
   19149       opc2 = ifieldOPClo10(theInstr);
   19150 
   19151       switch (opc2) {
   19152          case 0x2:    // dadd - DFP Add
   19153          case 0x202:  // dsub - DFP Subtract
   19154          case 0x22:   // dmul - DFP Mult
   19155          case 0x222:  // ddiv - DFP Divide
   19156             if (!allow_DFP) goto decode_noDFP;
   19157             if (dis_dfp_arith( theInstr ))
   19158                goto decode_success;
   19159          case 0x82:   // dcmpo, DFP comparison ordered instruction
   19160          case 0x282:  // dcmpu, DFP comparison unordered instruction
   19161             if (!allow_DFP) goto decode_noDFP;
   19162             if (dis_dfp_compare( theInstr ) )
   19163                goto decode_success;
   19164             goto decode_failure;
   19165          case 0x102: // dctdp  - DFP convert to DFP long
   19166          case 0x302: // drsp   - DFP round to dfp short
   19167          case 0x122: // dctfix - DFP convert to fixed
   19168             if (!allow_DFP) goto decode_noDFP;
   19169             if (dis_dfp_fmt_conv( theInstr ))
   19170                goto decode_success;
   19171             goto decode_failure;
   19172          case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
   19173             if (!allow_VX)
   19174                goto decode_failure;
   19175             if (dis_dfp_fmt_conv( theInstr ))
   19176                goto decode_success;
   19177             goto decode_failure;
   19178          case 0x2A2: // dtstsf - DFP number of significant digits
   19179             if (!allow_DFP) goto decode_noDFP;
   19180             if (dis_dfp_significant_digits(theInstr))
   19181                goto decode_success;
   19182             goto decode_failure;
   19183          case 0x142: // ddedpd   DFP Decode DPD to BCD
   19184          case 0x342: // denbcd   DFP Encode BCD to DPD
   19185             if (!allow_DFP) goto decode_noDFP;
   19186             if (dis_dfp_bcd(theInstr))
   19187                goto decode_success;
   19188             goto decode_failure;
   19189          case 0x162:  // dxex - Extract exponent
   19190          case 0x362:  // diex - Insert exponent
   19191             if (!allow_DFP) goto decode_noDFP;
   19192             if (dis_dfp_extract_insert( theInstr ) )
   19193                goto decode_success;
   19194             goto decode_failure;
   19195          case 0x3CE: // fcfidus (implemented as native insn)
   19196             if (!allow_VX)
   19197                goto decode_noVX;
   19198             if (dis_fp_round( theInstr ))
   19199                goto decode_success;
   19200             goto decode_failure;
   19201          case 0x34E: // fcfids
   19202             if (dis_fp_round( theInstr ))
   19203                goto decode_success;
   19204             goto decode_failure;
   19205       }
   19206 
   19207       opc2 = ifieldOPClo9( theInstr );
   19208       switch (opc2) {
   19209       case 0x42: // dscli, DFP shift left
   19210       case 0x62: // dscri, DFP shift right
   19211          if (!allow_DFP) goto decode_noDFP;
   19212          if (dis_dfp_shift( theInstr ))
   19213             goto decode_success;
   19214          goto decode_failure;
   19215       case 0xc2:  // dtstdc, DFP test data class
   19216       case 0xe2:  // dtstdg, DFP test data group
   19217          if (!allow_DFP) goto decode_noDFP;
   19218          if (dis_dfp_class_test( theInstr ))
   19219             goto decode_success;
   19220          goto decode_failure;
   19221       }
   19222 
   19223       opc2 = ifieldOPClo8( theInstr );
   19224       switch (opc2) {
   19225       case 0x3:   // dqua  - DFP Quantize
   19226       case 0x23:  // drrnd - DFP Reround
   19227       case 0x43:  // dquai - DFP Quantize immediate
   19228          if (!allow_DFP) goto decode_noDFP;
   19229          if (dis_dfp_quantize_sig_rrnd( theInstr ) )
   19230             goto decode_success;
   19231          goto decode_failure;
   19232       case 0xA2: // dtstex - DFP Test exponent
   19233          if (!allow_DFP) goto decode_noDFP;
   19234          if (dis_dfp_exponent_test( theInstr ) )
   19235             goto decode_success;
   19236          goto decode_failure;
   19237       case 0x63: // drintx - Round to an integer value
   19238       case 0xE3: // drintn - Round to an integer value
   19239          if (!allow_DFP) goto decode_noDFP;
   19240          if (dis_dfp_round( theInstr ) ) {
   19241             goto decode_success;
   19242          }
   19243          goto decode_failure;
   19244       default:
   19245          break;  /* fall through to next opc2 check */
   19246       }
   19247 
   19248       opc2 = IFIELD(theInstr, 1, 5);
   19249       switch (opc2) {
   19250       /* Floating Point Arith Instructions */
   19251       case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
   19252       case 0x19:                       // fmuls
   19253          if (dis_fp_arith(theInstr)) goto decode_success;
   19254          goto decode_failure;
   19255       case 0x16:                       // fsqrts
   19256          if (!allow_FX) goto decode_noFX;
   19257          if (dis_fp_arith(theInstr)) goto decode_success;
   19258          goto decode_failure;
   19259       case 0x18:                       // fres
   19260          if (!allow_GX) goto decode_noGX;
   19261          if (dis_fp_arith(theInstr)) goto decode_success;
   19262          goto decode_failure;
   19263 
   19264       /* Floating Point Mult-Add Instructions */
   19265       case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
   19266       case 0x1F:                       // fnmadds
   19267          if (dis_fp_multadd(theInstr)) goto decode_success;
   19268          goto decode_failure;
   19269 
   19270       case 0x1A:                       // frsqrtes
   19271          if (!allow_GX) goto decode_noGX;
   19272          if (dis_fp_arith(theInstr)) goto decode_success;
   19273          goto decode_failure;
   19274 
   19275       default:
   19276          goto decode_failure;
   19277       }
   19278       break;
   19279 
   19280    case 0x3C: // VSX instructions (except load/store)
   19281    {
   19282       // All of these VSX instructions use some VMX facilities, so
   19283       // if allow_V is not set, we'll skip trying to decode.
   19284       if (!allow_V) goto decode_noVX;
   19285 
   19286       UInt vsxOpc2 = get_VSX60_opc2(opc2);
   19287       /* The vsxOpc2 returned is the "normalized" value, representing the
   19288        * instructions secondary opcode as taken from the standard secondary
   19289        * opcode field [21:30] (IBM notatition), even if the actual field
   19290        * is non-standard.  These normalized values are given in the opcode
   19291        * appendices of the ISA 2.06 document.
   19292        */
   19293 
   19294       switch (vsxOpc2) {
   19295          case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
   19296          case 0x018: case 0x148: // xxsel, xxspltw
   19297             if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
   19298             goto decode_failure;
   19299          case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
   19300          case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc
   19301          case 0x2C8: case 0x2E8: // xxlnand, xxleqv
   19302             if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
   19303             goto decode_failure;
   19304          case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
   19305          case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
   19306          case 0x280: case 0x2A0: // xsmaxdp, xsmindp
   19307          case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
   19308          case 0x034: case 0x014: // xsresp, xsrsqrtesp
   19309          case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
   19310          case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
   19311          case 0x092: case 0x232: // xsrdpi, xsrsp
   19312             if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
   19313             goto decode_failure;
   19314          case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   19315             if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
   19316             goto decode_failure;
   19317          case 0x0:   case 0x020: // xsaddsp, xssubsp
   19318          case 0x080:             // xsadddp
   19319          case 0x060: case 0x0E0: // xsdivsp, xsdivdp
   19320          case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
   19321          case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
   19322          case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
   19323          case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
   19324          case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
   19325          case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
   19326          case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
   19327          case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
   19328          case 0x040: case 0x0C0: // xsmulsp, xsmuldp
   19329          case 0x0A0:             // xssubdp
   19330          case 0x016: case 0x096: // xssqrtsp,xssqrtdp
   19331          case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
   19332             if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
   19333             goto decode_failure;
   19334          case 0x180: // xvadddp
   19335          case 0x1E0: // xvdivdp
   19336          case 0x1C0: // xvmuldp
   19337          case 0x1A0: // xvsubdp
   19338          case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
   19339          case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
   19340          case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
   19341          case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
   19342          case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
   19343          case 0x196: // xvsqrtdp
   19344             if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
   19345             goto decode_failure;
   19346          case 0x100: // xvaddsp
   19347          case 0x160: // xvdivsp
   19348          case 0x140: // xvmulsp
   19349          case 0x120: // xvsubsp
   19350          case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
   19351          case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
   19352          case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
   19353          case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
   19354          case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
   19355          case 0x116: // xvsqrtsp
   19356             if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
   19357             goto decode_failure;
   19358 
   19359          case 0x250:             // xscvuxdsp
   19360          case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
   19361          case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
   19362          case 0x090: // xscvdpuxws
   19363             // The above VSX conversion instructions employ some ISA 2.06
   19364             // floating point conversion instructions under the covers,
   19365             // so if allow_VX (which means "supports ISA 2.06") is not set,
   19366             // we'll skip the decode.
   19367             if (!allow_VX) goto decode_noVX;
   19368             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
   19369             goto decode_failure;
   19370 
   19371          case 0x2B0: // xscvdpsxds
   19372          case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
   19373          case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
   19374          case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
   19375          case 0x212: case 0x216: // xscvdpsp, xscvdpspn
   19376          case 0x292: case 0x296: // xscvspdp, xscvspdpn
   19377          case 0x312: // xvcvdpsp
   19378          case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
   19379          case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
   19380          case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
   19381          case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
   19382          case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
   19383          case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
   19384             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
   19385             goto decode_failure;
   19386 
   19387          case 0x18C: case 0x38C: // xvcmpeqdp[.]
   19388          case 0x10C: case 0x30C: // xvcmpeqsp[.]
   19389          case 0x14C: case 0x34C: // xvcmpgesp[.]
   19390          case 0x12C: case 0x32C: // xvcmpgtsp[.]
   19391          case 0x1CC: case 0x3CC: // xvcmpgedp[.]
   19392          case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
   19393              if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
   19394              goto decode_failure;
   19395 
   19396          case 0x134:  // xvresp
   19397          case 0x1B4:  // xvredp
   19398          case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
   19399          case 0x380: case 0x3A0: // xvmaxdp, xvmindp
   19400          case 0x300: case 0x320: // xvmaxsp, xvminsp
   19401          case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
   19402          case 0x3B2: case 0x332: // xvabsdp, xvabssp
   19403          case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
   19404          case 0x192: case 0x1D6: // xvrdpi, xvrdpic
   19405          case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
   19406          case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
   19407          case 0x112: case 0x156: // xvrspi, xvrspic
   19408          case 0x172: case 0x152: // xvrspim, xvrspip
   19409          case 0x132: // xvrspiz
   19410             if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
   19411             goto decode_failure;
   19412 
   19413          default:
   19414             goto decode_failure;
   19415       }
   19416       break;
   19417    }
   19418 
   19419    /* 64bit Integer Stores */
   19420    case 0x3E:  // std, stdu, stq
   19421       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   19422       goto decode_failure;
   19423 
   19424    case 0x3F:
   19425       if (!allow_F) goto decode_noF;
   19426       /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
   19427          so we can simply fall through the first switch statement */
   19428 
   19429       opc2 = IFIELD(theInstr, 1, 5);
   19430       switch (opc2) {
   19431       /* Floating Point Arith Instructions */
   19432       case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
   19433       case 0x19:                       // fmul
   19434          if (dis_fp_arith(theInstr)) goto decode_success;
   19435          goto decode_failure;
   19436       case 0x16:                       // fsqrt
   19437          if (!allow_FX) goto decode_noFX;
   19438          if (dis_fp_arith(theInstr)) goto decode_success;
   19439          goto decode_failure;
   19440       case 0x17: case 0x1A:            // fsel, frsqrte
   19441          if (!allow_GX) goto decode_noGX;
   19442          if (dis_fp_arith(theInstr)) goto decode_success;
   19443          goto decode_failure;
   19444 
   19445       /* Floating Point Mult-Add Instructions */
   19446       case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
   19447       case 0x1F:                       // fnmadd
   19448          if (dis_fp_multadd(theInstr)) goto decode_success;
   19449          goto decode_failure;
   19450 
   19451       case 0x18:                       // fre
   19452          if (!allow_GX) goto decode_noGX;
   19453          if (dis_fp_arith(theInstr)) goto decode_success;
   19454          goto decode_failure;
   19455 
   19456       default:
   19457          break; // Fall through
   19458       }
   19459 
   19460       opc2 = IFIELD(theInstr, 1, 10);
   19461       switch (opc2) {
   19462       /* 128-bit DFP instructions */
   19463       case 0x2:    // daddq - DFP Add
   19464       case 0x202:  // dsubq - DFP Subtract
   19465       case 0x22:   // dmulq - DFP Mult
   19466       case 0x222:  // ddivq - DFP Divide
   19467          if (!allow_DFP) goto decode_noDFP;
   19468          if (dis_dfp_arithq( theInstr ))
   19469             goto decode_success;
   19470          goto decode_failure;
   19471       case 0x162:  // dxexq - DFP Extract exponent
   19472       case 0x362:  // diexq - DFP Insert exponent
   19473          if (!allow_DFP) goto decode_noDFP;
   19474          if (dis_dfp_extract_insertq( theInstr ))
   19475             goto decode_success;
   19476          goto decode_failure;
   19477 
   19478       case 0x82:   // dcmpoq, DFP comparison ordered instruction
   19479       case 0x282:  // dcmpuq, DFP comparison unordered instruction
   19480          if (!allow_DFP) goto decode_noDFP;
   19481          if (dis_dfp_compare( theInstr ) )
   19482             goto decode_success;
   19483          goto decode_failure;
   19484 
   19485       case 0x102: // dctqpq  - DFP convert to DFP extended
   19486       case 0x302: // drdpq   - DFP round to dfp Long
   19487       case 0x122: // dctfixq - DFP convert to fixed quad
   19488       case 0x322: // dcffixq - DFP convert from fixed quad
   19489          if (!allow_DFP) goto decode_noDFP;
   19490          if (dis_dfp_fmt_convq( theInstr ))
   19491             goto decode_success;
   19492          goto decode_failure;
   19493 
   19494       case 0x2A2: // dtstsfq - DFP number of significant digits
   19495          if (!allow_DFP) goto decode_noDFP;
   19496          if (dis_dfp_significant_digits(theInstr))
   19497             goto decode_success;
   19498          goto decode_failure;
   19499 
   19500       case 0x142: // ddedpdq   DFP Decode DPD to BCD
   19501       case 0x342: // denbcdq   DFP Encode BCD to DPD
   19502          if (!allow_DFP) goto decode_noDFP;
   19503          if (dis_dfp_bcdq(theInstr))
   19504             goto decode_success;
   19505          goto decode_failure;
   19506 
   19507       /* Floating Point Compare Instructions */
   19508       case 0x000: // fcmpu
   19509       case 0x020: // fcmpo
   19510          if (dis_fp_cmp(theInstr)) goto decode_success;
   19511          goto decode_failure;
   19512 
   19513       case 0x080: // ftdiv
   19514       case 0x0A0: // ftsqrt
   19515          if (dis_fp_tests(theInstr)) goto decode_success;
   19516          goto decode_failure;
   19517 
   19518       /* Floating Point Rounding/Conversion Instructions */
   19519       case 0x00C: // frsp
   19520       case 0x00E: // fctiw
   19521       case 0x00F: // fctiwz
   19522       case 0x32E: // fctid
   19523       case 0x32F: // fctidz
   19524       case 0x34E: // fcfid
   19525          if (dis_fp_round(theInstr)) goto decode_success;
   19526          goto decode_failure;
   19527       case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
   19528       case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
   19529          if (!allow_VX) goto decode_noVX;
   19530          if (dis_fp_round(theInstr)) goto decode_success;
   19531          goto decode_failure;
   19532 
   19533       /* Power6 rounding stuff */
   19534       case 0x1E8: // frim
   19535       case 0x1C8: // frip
   19536       case 0x188: // frin
   19537       case 0x1A8: // friz
   19538          /* A hack to check for P6 capability . . . */
   19539          if ((allow_F && allow_V && allow_FX && allow_GX) &&
   19540              (dis_fp_round(theInstr)))
   19541             goto decode_success;
   19542          goto decode_failure;
   19543 
   19544       /* Floating Point Move Instructions */
   19545       case 0x008: // fcpsgn
   19546       case 0x028: // fneg
   19547       case 0x048: // fmr
   19548       case 0x088: // fnabs
   19549       case 0x108: // fabs
   19550          if (dis_fp_move( theInstr )) goto decode_success;
   19551          goto decode_failure;
   19552 
   19553       case 0x3c6: case 0x346:          // fmrgew, fmrgow
   19554          if (dis_fp_merge( theInstr )) goto decode_success;
   19555          goto decode_failure;
   19556 
   19557       /* Floating Point Status/Control Register Instructions */
   19558       case 0x026: // mtfsb1
   19559       case 0x040: // mcrfs
   19560       case 0x046: // mtfsb0
   19561       case 0x086: // mtfsfi
   19562       case 0x247: // mffs
   19563       case 0x2C7: // mtfsf
   19564          // Some of the above instructions need to know more about the
   19565          // ISA level supported by the host.
   19566          if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
   19567          goto decode_failure;
   19568 
   19569       default:
   19570          break; // Fall through...
   19571       }
   19572 
   19573       opc2 = ifieldOPClo9( theInstr );
   19574       switch (opc2) {
   19575       case 0x42: // dscli, DFP shift left
   19576       case 0x62: // dscri, DFP shift right
   19577          if (!allow_DFP) goto decode_noDFP;
   19578          if (dis_dfp_shiftq( theInstr ))
   19579             goto decode_success;
   19580          goto decode_failure;
   19581       case 0xc2:  // dtstdc, DFP test data class
   19582       case 0xe2:  // dtstdg, DFP test data group
   19583          if (!allow_DFP) goto decode_noDFP;
   19584          if (dis_dfp_class_test( theInstr ))
   19585             goto decode_success;
   19586          goto decode_failure;
   19587       default:
   19588          break;
   19589       }
   19590 
   19591       opc2 = ifieldOPClo8( theInstr );
   19592       switch (opc2) {
   19593       case 0x3:   // dquaq  - DFP Quantize Quad
   19594       case 0x23:  // drrndq - DFP Reround Quad
   19595       case 0x43:  // dquaiq - DFP Quantize immediate Quad
   19596          if (!allow_DFP) goto decode_noDFP;
   19597          if (dis_dfp_quantize_sig_rrndq( theInstr ))
   19598             goto decode_success;
   19599          goto decode_failure;
   19600       case 0xA2: // dtstexq - DFP Test exponent Quad
   19601          if (dis_dfp_exponent_test( theInstr ) )
   19602             goto decode_success;
   19603          goto decode_failure;
   19604       case 0x63:  // drintxq - DFP Round to an integer value
   19605       case 0xE3:  // drintnq - DFP Round to an integer value
   19606          if (!allow_DFP) goto decode_noDFP;
   19607          if (dis_dfp_roundq( theInstr ))
   19608             goto decode_success;
   19609          goto decode_failure;
   19610 
   19611       default:
   19612          goto decode_failure;
   19613       }
   19614       break;
   19615 
   19616    case 0x13:
   19617       switch (opc2) {
   19618 
   19619       /* Condition Register Logical Instructions */
   19620       case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
   19621       case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
   19622       case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
   19623          if (dis_cond_logic( theInstr )) goto decode_success;
   19624          goto decode_failure;
   19625 
   19626       /* Branch Instructions */
   19627       case 0x210: case 0x010: // bcctr, bclr
   19628          if (dis_branch(theInstr, abiinfo, &dres,
   19629                                   resteerOkFn, callback_opaque))
   19630             goto decode_success;
   19631          goto decode_failure;
   19632 
   19633       /* Memory Synchronization Instructions */
   19634       case 0x096: // isync
   19635          if (dis_memsync( theInstr )) goto decode_success;
   19636          goto decode_failure;
   19637 
   19638       default:
   19639          goto decode_failure;
   19640       }
   19641       break;
   19642 
   19643 
   19644    case 0x1F:
   19645 
   19646       /* For arith instns, bit10 is the OE flag (overflow enable) */
   19647 
   19648       opc2 = IFIELD(theInstr, 1, 9);
   19649       switch (opc2) {
   19650       /* Integer Arithmetic Instructions */
   19651       case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
   19652       case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
   19653       case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
   19654       case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
   19655       case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
   19656       case 0x0C8: // subfze
   19657          if (dis_int_arith( theInstr )) goto decode_success;
   19658          goto decode_failure;
   19659 
   19660       case 0x18B: // divweu (implemented as native insn)
   19661       case 0x1AB: // divwe (implemented as native insn)
   19662          if (!allow_VX) goto decode_noVX;
   19663          if (dis_int_arith( theInstr )) goto decode_success;
   19664          goto decode_failure;
   19665 
   19666       /* 64bit Integer Arithmetic */
   19667       case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
   19668       case 0x1C9: case 0x1E9: // divdu, divd
   19669          if (!mode64) goto decode_failure;
   19670          if (dis_int_arith( theInstr )) goto decode_success;
   19671          goto decode_failure;
   19672 
   19673       case 0x1A9: //  divde (implemented as native insn)
   19674       case 0x189: //  divdeuo (implemented as native insn)
   19675          if (!allow_VX) goto decode_noVX;
   19676          if (!mode64) goto decode_failure;
   19677          if (dis_int_arith( theInstr )) goto decode_success;
   19678          goto decode_failure;
   19679 
   19680       case 0x1FC:                         // cmpb
   19681          if (dis_int_logic( theInstr )) goto decode_success;
   19682          goto decode_failure;
   19683 
   19684       default:
   19685          break;  // Fall through...
   19686       }
   19687 
   19688       /* All remaining opcodes use full 10 bits. */
   19689 
   19690       opc2 = IFIELD(theInstr, 1, 10);
   19691       switch (opc2) {
   19692       /* Integer Compare Instructions  */
   19693       case 0x000: case 0x020: // cmp, cmpl
   19694          if (dis_int_cmp( theInstr )) goto decode_success;
   19695          goto decode_failure;
   19696 
   19697       /* Integer Logical Instructions */
   19698       case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
   19699       case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
   19700       case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
   19701       case 0x19C: case 0x13C:             // orc,  xor
   19702       case 0x2DF: case 0x25F:            // mftgpr, mffgpr
   19703          if (dis_int_logic( theInstr )) goto decode_success;
   19704          goto decode_failure;
   19705 
   19706       case 0x28E: case 0x2AE:             // tbegin., tend.
   19707       case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
   19708       case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
   19709       case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
   19710       if (dis_transactional_memory( theInstr,
   19711                                     getUIntPPCendianly( &guest_code[delta + 4]),
   19712                                     abiinfo, &dres,
   19713                                     resteerOkFn, callback_opaque))
   19714             goto decode_success;
   19715          goto decode_failure;
   19716 
   19717       /* 64bit Integer Logical Instructions */
   19718       case 0x3DA: case 0x03A: // extsw, cntlzd
   19719          if (!mode64) goto decode_failure;
   19720          if (dis_int_logic( theInstr )) goto decode_success;
   19721          goto decode_failure;
   19722 
   19723          /* 64bit Integer Parity Instructions */
   19724       case 0xba: // prtyd
   19725          if (!mode64) goto decode_failure;
   19726          if (dis_int_parity( theInstr )) goto decode_success;
   19727          goto decode_failure;
   19728 
   19729       case 0x9a: // prtyw
   19730          if (dis_int_parity( theInstr )) goto decode_success;
   19731          goto decode_failure;
   19732 
   19733       /* Integer Shift Instructions */
   19734       case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
   19735       case 0x218:                         // srw
   19736          if (dis_int_shift( theInstr )) goto decode_success;
   19737          goto decode_failure;
   19738 
   19739       /* 64bit Integer Shift Instructions */
   19740       case 0x01B: case 0x31A: // sld, srad
   19741       case 0x33A: case 0x33B: // sradi
   19742       case 0x21B:             // srd
   19743          if (!mode64) goto decode_failure;
   19744          if (dis_int_shift( theInstr )) goto decode_success;
   19745          goto decode_failure;
   19746 
   19747       /* Integer Load Instructions */
   19748       case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
   19749       case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
   19750       case 0x017: case 0x037:             // lwzx,  lwzux
   19751          if (dis_int_load( theInstr )) goto decode_success;
   19752          goto decode_failure;
   19753 
   19754       /* 64bit Integer Load Instructions */
   19755       case 0x035: case 0x015:             // ldux,  ldx
   19756       case 0x175: case 0x155:             // lwaux, lwax
   19757          if (!mode64) goto decode_failure;
   19758          if (dis_int_load( theInstr )) goto decode_success;
   19759          goto decode_failure;
   19760 
   19761       /* Integer Store Instructions */
   19762       case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
   19763       case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
   19764          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   19765          goto decode_failure;
   19766 
   19767       /* 64bit Integer Store Instructions */
   19768       case 0x0B5: case 0x095: // stdux, stdx
   19769          if (!mode64) goto decode_failure;
   19770          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   19771          goto decode_failure;
   19772 
   19773       /* Integer Load and Store with Byte Reverse Instructions */
   19774       case 0x214: case 0x294: // ldbrx, stdbrx
   19775          if (!mode64) goto decode_failure;
   19776          if (dis_int_ldst_rev( theInstr )) goto decode_success;
   19777          goto decode_failure;
   19778 
   19779       case 0x216: case 0x316: case 0x296:    // lwbrx, lhbrx, stwbrx
   19780       case 0x396:                            // sthbrx
   19781          if (dis_int_ldst_rev( theInstr )) goto decode_success;
   19782          goto decode_failure;
   19783 
   19784       /* Integer Load and Store String Instructions */
   19785       case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
   19786       case 0x295: {                       // stswx
   19787          Bool stopHere = False;
   19788          Bool ok = dis_int_ldst_str( theInstr, &stopHere );
   19789          if (!ok) goto decode_failure;
   19790          if (stopHere) {
   19791             putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
   19792             dres.jk_StopHere = Ijk_Boring;
   19793             dres.whatNext    = Dis_StopHere;
   19794          }
   19795          goto decode_success;
   19796       }
   19797 
   19798       /* Memory Synchronization Instructions */
   19799       case 0x034: case 0x074:             // lbarx, lharx
   19800       case 0x2B6: case 0x2D6:             // stbcx, sthcx
   19801          if (!allow_isa_2_07) goto decode_noP8;
   19802          if (dis_memsync( theInstr )) goto decode_success;
   19803          goto decode_failure;
   19804 
   19805       case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
   19806       case 0x256:                         // sync
   19807          if (dis_memsync( theInstr )) goto decode_success;
   19808          goto decode_failure;
   19809 
   19810       /* 64bit Memory Synchronization Instructions */
   19811       case 0x054: case 0x0D6: // ldarx, stdcx.
   19812          if (!mode64) goto decode_failure;
   19813          if (dis_memsync( theInstr )) goto decode_success;
   19814          goto decode_failure;
   19815 
   19816       case 0x114: case 0x0B6: // lqarx, stqcx.
   19817          if (dis_memsync( theInstr )) goto decode_success;
   19818          goto decode_failure;
   19819 
   19820       /* Processor Control Instructions */
   19821       case 0x33:  case 0x73: // mfvsrd, mfvsrwz
   19822       case 0xB3:  case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
   19823       case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
   19824       case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
   19825       case 0x220:                         // mcrxrt
   19826          if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
   19827          goto decode_failure;
   19828 
   19829       /* Cache Management Instructions */
   19830       case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
   19831       case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
   19832       case 0x3D6:                         // icbi
   19833          if (dis_cache_manage( theInstr, &dres, archinfo ))
   19834             goto decode_success;
   19835          goto decode_failure;
   19836 
   19837 //zz       /* External Control Instructions */
   19838 //zz       case 0x136: case 0x1B6: // eciwx, ecowx
   19839 //zz          DIP("external control op => not implemented\n");
   19840 //zz          goto decode_failure;
   19841 
   19842       /* Trap Instructions */
   19843       case 0x004:             // tw
   19844          if (dis_trap(theInstr, &dres)) goto decode_success;
   19845          goto decode_failure;
   19846 
   19847       case 0x044:             // td
   19848          if (!mode64) goto decode_failure;
   19849          if (dis_trap(theInstr, &dres)) goto decode_success;
   19850          goto decode_failure;
   19851 
   19852       /* Floating Point Load Instructions */
   19853       case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
   19854       case 0x277:                         // lfdux
   19855          if (!allow_F) goto decode_noF;
   19856          if (dis_fp_load( theInstr )) goto decode_success;
   19857          goto decode_failure;
   19858 
   19859       /* Floating Point Store Instructions */
   19860       case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
   19861       case 0x2F7:                         // stfdu, stfiwx
   19862          if (!allow_F) goto decode_noF;
   19863          if (dis_fp_store( theInstr )) goto decode_success;
   19864          goto decode_failure;
   19865       case 0x3D7:                         // stfiwx
   19866          if (!allow_F) goto decode_noF;
   19867          if (!allow_GX) goto decode_noGX;
   19868          if (dis_fp_store( theInstr )) goto decode_success;
   19869          goto decode_failure;
   19870 
   19871          /* Floating Point Double Pair Indexed Instructions */
   19872       case 0x317: // lfdpx (Power6)
   19873       case 0x397: // stfdpx (Power6)
   19874          if (!allow_F) goto decode_noF;
   19875          if (dis_fp_pair(theInstr)) goto decode_success;
   19876          goto decode_failure;
   19877 
   19878       case 0x357:                         // lfiwax
   19879          if (!allow_F) goto decode_noF;
   19880          if (dis_fp_load( theInstr )) goto decode_success;
   19881          goto decode_failure;
   19882 
   19883       case 0x377:                         // lfiwzx
   19884          if (!allow_F) goto decode_noF;
   19885          if (dis_fp_load( theInstr )) goto decode_success;
   19886          goto decode_failure;
   19887 
   19888       /* AltiVec instructions */
   19889 
   19890       /* AV Cache Control - Data streams */
   19891       case 0x156: case 0x176: case 0x336: // dst, dstst, dss
   19892          if (!allow_V) goto decode_noV;
   19893          if (dis_av_datastream( theInstr )) goto decode_success;
   19894          goto decode_failure;
   19895 
   19896       /* AV Load */
   19897       case 0x006: case 0x026:             // lvsl, lvsr
   19898       case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
   19899       case 0x067: case 0x167:             // lvx, lvxl
   19900          if (!allow_V) goto decode_noV;
   19901          if (dis_av_load( abiinfo, theInstr )) goto decode_success;
   19902          goto decode_failure;
   19903 
   19904       /* AV Store */
   19905       case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
   19906       case 0x0E7: case 0x1E7:             // stvx, stvxl
   19907          if (!allow_V) goto decode_noV;
   19908          if (dis_av_store( theInstr )) goto decode_success;
   19909          goto decode_failure;
   19910 
   19911       /* VSX Load */
   19912       case 0x00C: // lxsiwzx
   19913       case 0x04C: // lxsiwax
   19914       case 0x20C: // lxsspx
   19915       case 0x24C: // lxsdx
   19916       case 0x34C: // lxvd2x
   19917       case 0x14C: // lxvdsx
   19918       case 0x30C: // lxvw4x
   19919         // All of these VSX load instructions use some VMX facilities, so
   19920         // if allow_V is not set, we'll skip trying to decode.
   19921         if (!allow_V) goto decode_noV;
   19922 
   19923 	if (dis_vx_load( theInstr )) goto decode_success;
   19924           goto decode_failure;
   19925 
   19926       /* VSX Store */
   19927       case 0x08C: // stxsiwx
   19928       case 0x28C: // stxsspx
   19929       case 0x2CC: // stxsdx
   19930       case 0x3CC: // stxvd2x
   19931       case 0x38C: // stxvw4x
   19932         // All of these VSX store instructions use some VMX facilities, so
   19933         // if allow_V is not set, we'll skip trying to decode.
   19934         if (!allow_V) goto decode_noV;
   19935 
   19936 	if (dis_vx_store( theInstr )) goto decode_success;
   19937     	  goto decode_failure;
   19938 
   19939       /* Miscellaneous ISA 2.06 instructions */
   19940       case 0x1FA: // popcntd
   19941       case 0x17A: // popcntw
   19942       case 0x7A:  // popcntb
   19943 	  if (dis_int_logic( theInstr )) goto decode_success;
   19944     	  goto decode_failure;
   19945 
   19946       case 0x0FC: // bpermd
   19947          if (!mode64) goto decode_failure;
   19948          if (dis_int_logic( theInstr )) goto decode_success;
   19949          goto decode_failure;
   19950 
   19951       default:
   19952          /* Deal with some other cases that we would otherwise have
   19953             punted on. */
   19954          /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
   19955          /* only decode this insn when reserved bit 0 (31 in IBM's
   19956             notation) is zero */
   19957          if (IFIELD(theInstr, 0, 6) == (15<<1)) {
   19958             UInt rT = ifieldRegDS( theInstr );
   19959             UInt rA = ifieldRegA( theInstr );
   19960             UInt rB = ifieldRegB( theInstr );
   19961             UInt bi = ifieldRegC( theInstr );
   19962             putIReg(
   19963                rT,
   19964                IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
   19965                            rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
   19966                                    : getIReg(rA),
   19967                            getIReg(rB))
   19968 
   19969             );
   19970             DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
   19971             goto decode_success;
   19972          }
   19973          goto decode_failure;
   19974       }
   19975       break;
   19976 
   19977 
   19978    case 0x04:
   19979       /* AltiVec instructions */
   19980 
   19981       opc2 = IFIELD(theInstr, 0, 6);
   19982       switch (opc2) {
   19983       /* AV Mult-Add, Mult-Sum */
   19984       case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
   19985       case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
   19986       case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
   19987          if (!allow_V) goto decode_noV;
   19988          if (dis_av_multarith( theInstr )) goto decode_success;
   19989          goto decode_failure;
   19990 
   19991       /* AV Permutations */
   19992       case 0x2A:                       // vsel
   19993       case 0x2B:                       // vperm
   19994       case 0x2C:                       // vsldoi
   19995          if (!allow_V) goto decode_noV;
   19996          if (dis_av_permute( theInstr )) goto decode_success;
   19997          goto decode_failure;
   19998 
   19999       case 0x2D:                       // vpermxor
   20000          if (!allow_isa_2_07) goto decode_noP8;
   20001          if (dis_av_permute( theInstr )) goto decode_success;
   20002          goto decode_failure;
   20003 
   20004       /* AV Floating Point Mult-Add/Sub */
   20005       case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
   20006          if (!allow_V) goto decode_noV;
   20007          if (dis_av_fp_arith( theInstr )) goto decode_success;
   20008          goto decode_failure;
   20009 
   20010       case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
   20011       case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
   20012          if (!allow_V) goto decode_noV;
   20013          if (dis_av_quad( theInstr)) goto decode_success;
   20014          goto decode_failure;
   20015 
   20016       default:
   20017          break;  // Fall through...
   20018       }
   20019 
   20020       opc2 = IFIELD(theInstr, 0, 9);
   20021       switch (opc2) {
   20022       /* BCD arithmetic */
   20023       case 0x1: case 0x41:             // bcdadd, bcdsub
   20024          if (!allow_isa_2_07) goto decode_noP8;
   20025          if (dis_av_bcd( theInstr )) goto decode_success;
   20026          goto decode_failure;
   20027 
   20028       default:
   20029          break;  // Fall through...
   20030       }
   20031 
   20032       opc2 = IFIELD(theInstr, 0, 11);
   20033       switch (opc2) {
   20034       /* AV Arithmetic */
   20035       case 0x180:                         // vaddcuw
   20036       case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
   20037       case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
   20038       case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
   20039       case 0x580:                         // vsubcuw
   20040       case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
   20041       case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
   20042       case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
   20043       case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
   20044       case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
   20045       case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
   20046       case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
   20047       case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
   20048       case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
   20049       case 0x008: case 0x048:             // vmuloub, vmulouh
   20050       case 0x108: case 0x148:             // vmulosb, vmulosh
   20051       case 0x208: case 0x248:             // vmuleub, vmuleuh
   20052       case 0x308: case 0x348:             // vmulesb, vmulesh
   20053       case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
   20054       case 0x688: case 0x788:             // vsum2sws, vsumsws
   20055          if (!allow_V) goto decode_noV;
   20056          if (dis_av_arith( theInstr )) goto decode_success;
   20057          goto decode_failure;
   20058 
   20059       case 0x088: case 0x089:             // vmulouw, vmuluwm
   20060       case 0x0C0: case 0x0C2:             // vaddudm, vmaxud
   20061       case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
   20062       case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
   20063       case 0x4C0:                         // vsubudm
   20064          if (!allow_isa_2_07) goto decode_noP8;
   20065          if (dis_av_arith( theInstr )) goto decode_success;
   20066          goto decode_failure;
   20067 
   20068       /* AV Polynomial Vector Multiply Add */
   20069       case 0x408: case 0x448:            // vpmsumb, vpmsumd
   20070       case 0x488: case 0x4C8:            // vpmsumw, vpmsumh
   20071          if (!allow_isa_2_07) goto decode_noP8;
   20072          if (dis_av_polymultarith( theInstr )) goto decode_success;
   20073          goto decode_failure;
   20074 
   20075       /* AV Rotate, Shift */
   20076       case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
   20077       case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
   20078       case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
   20079       case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
   20080       case 0x1C4: case 0x2C4:             // vsl, vsr
   20081       case 0x40C: case 0x44C:             // vslo, vsro
   20082          if (!allow_V) goto decode_noV;
   20083          if (dis_av_shift( theInstr )) goto decode_success;
   20084          goto decode_failure;
   20085 
   20086       case 0x0C4:                         // vrld
   20087       case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
   20088           if (!allow_isa_2_07) goto decode_noP8;
   20089           if (dis_av_shift( theInstr )) goto decode_success;
   20090           goto decode_failure;
   20091 
   20092       /* AV Logic */
   20093       case 0x404: case 0x444: case 0x484: // vand, vandc, vor
   20094       case 0x4C4: case 0x504:             // vxor, vnor
   20095          if (!allow_V) goto decode_noV;
   20096          if (dis_av_logic( theInstr )) goto decode_success;
   20097          goto decode_failure;
   20098 
   20099       case 0x544:                         // vorc
   20100       case 0x584: case 0x684:             // vnand, veqv
   20101          if (!allow_isa_2_07) goto decode_noP8;
   20102          if (dis_av_logic( theInstr )) goto decode_success;
   20103          goto decode_failure;
   20104 
   20105       /* AV Processor Control */
   20106       case 0x604: case 0x644:             // mfvscr, mtvscr
   20107          if (!allow_V) goto decode_noV;
   20108          if (dis_av_procctl( theInstr )) goto decode_success;
   20109          goto decode_failure;
   20110 
   20111       /* AV Floating Point Arithmetic */
   20112       case 0x00A: case 0x04A:             // vaddfp, vsubfp
   20113       case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
   20114       case 0x1CA:                         // vlogefp
   20115       case 0x40A: case 0x44A:             // vmaxfp, vminfp
   20116          if (!allow_V) goto decode_noV;
   20117          if (dis_av_fp_arith( theInstr )) goto decode_success;
   20118          goto decode_failure;
   20119 
   20120       /* AV Floating Point Round/Convert */
   20121       case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
   20122       case 0x2CA:                         // vrfim
   20123       case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
   20124       case 0x3CA:                         // vctsxs
   20125          if (!allow_V) goto decode_noV;
   20126          if (dis_av_fp_convert( theInstr )) goto decode_success;
   20127          goto decode_failure;
   20128 
   20129       /* AV Merge, Splat */
   20130       case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
   20131       case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
   20132       case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
   20133       case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
   20134          if (!allow_V) goto decode_noV;
   20135          if (dis_av_permute( theInstr )) goto decode_success;
   20136          goto decode_failure;
   20137 
   20138       case 0x68C: case 0x78C:             // vmrgow, vmrgew
   20139           if (!allow_isa_2_07) goto decode_noP8;
   20140           if (dis_av_permute( theInstr )) goto decode_success;
   20141           goto decode_failure;
   20142 
   20143       /* AV Pack, Unpack */
   20144       case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
   20145       case 0x0CE:                         // vpkuwus
   20146       case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
   20147       case 0x1CE:                         // vpkswss
   20148       case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
   20149       case 0x2CE:                         // vupklsh
   20150       case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
   20151           if (!allow_V) goto decode_noV;
   20152           if (dis_av_pack( theInstr )) goto decode_success;
   20153           goto decode_failure;
   20154 
   20155       case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
   20156       case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
   20157          if (!allow_isa_2_07) goto decode_noP8;
   20158          if (dis_av_pack( theInstr )) goto decode_success;
   20159          goto decode_failure;
   20160 
   20161       case 0x508: case 0x509:             // vcipher, vcipherlast
   20162       case 0x548: case 0x549:             // vncipher, vncipherlast
   20163       case 0x5C8:                         // vsbox
   20164          if (!allow_isa_2_07) goto decode_noP8;
   20165          if (dis_av_cipher( theInstr )) goto decode_success;
   20166          goto decode_failure;
   20167 
   20168       case 0x6C2: case 0x682:             // vshasigmaw, vshasigmad
   20169          if (!allow_isa_2_07) goto decode_noP8;
   20170          if (dis_av_hash( theInstr )) goto decode_success;
   20171          goto decode_failure;
   20172 
   20173       case 0x702: case 0x742:             // vclzb, vclzh
   20174       case 0x782: case 0x7c2:             // vclzw, vclzd
   20175          if (!allow_isa_2_07) goto decode_noP8;
   20176          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   20177          goto decode_failure;
   20178 
   20179       case 0x703: case 0x743:             // vpopcntb, vpopcnth
   20180       case 0x783: case 0x7c3:             // vpopcntw, vpopcntd
   20181          if (!allow_isa_2_07) goto decode_noP8;
   20182          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   20183          goto decode_failure;
   20184 
   20185       case 0x50c:                         // vgbbd
   20186          if (!allow_isa_2_07) goto decode_noP8;
   20187          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   20188          goto decode_failure;
   20189 
   20190       case 0x140: case 0x100:             // vaddcuq, vadduqm
   20191       case 0x540: case 0x500:             // vsubcuq, vsubuqm
   20192       case 0x54C:                         // vbpermq
   20193          if (!allow_V) goto decode_noV;
   20194          if (dis_av_quad( theInstr)) goto decode_success;
   20195          goto decode_failure;
   20196 
   20197       default:
   20198          break;  // Fall through...
   20199       }
   20200 
   20201       opc2 = IFIELD(theInstr, 0, 10);
   20202       switch (opc2) {
   20203 
   20204       /* AV Compare */
   20205       case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
   20206       case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
   20207       case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
   20208          if (!allow_V) goto decode_noV;
   20209          if (dis_av_cmp( theInstr )) goto decode_success;
   20210          goto decode_failure;
   20211 
   20212       case 0x0C7:                         // vcmpequd
   20213       case 0x2C7:                         // vcmpgtud
   20214       case 0x3C7:                         // vcmpgtsd
   20215           if (!allow_isa_2_07) goto decode_noP8;
   20216           if (dis_av_cmp( theInstr )) goto decode_success;
   20217           goto decode_failure;
   20218 
   20219       /* AV Floating Point Compare */
   20220       case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
   20221       case 0x3C6:                         // vcmpbfp
   20222          if (!allow_V) goto decode_noV;
   20223          if (dis_av_fp_cmp( theInstr )) goto decode_success;
   20224          goto decode_failure;
   20225 
   20226       default:
   20227          goto decode_failure;
   20228       }
   20229       break;
   20230 
   20231    default:
   20232       goto decode_failure;
   20233 
   20234    decode_noF:
   20235       vassert(!allow_F);
   20236       vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
   20237 		 "can't be handled by Valgrind on this host.  This instruction\n"
   20238 		 "requires a host that supports Floating Point instructions.\n",
   20239 		 theInstr);
   20240       goto not_supported;
   20241    decode_noV:
   20242       vassert(!allow_V);
   20243       vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
   20244 		 "that can't be handled by Valgrind.  If this instruction is an\n"
   20245 		 "Altivec instruction, Valgrind must be run on a host that supports"
   20246 		 "AltiVec instructions.  If the application was compiled for e500, then\n"
   20247 		 "unfortunately Valgrind does not yet support e500 instructions.\n",
   20248 		 theInstr);
   20249       goto not_supported;
   20250    decode_noVX:
   20251       vassert(!allow_VX);
   20252       vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
   20253 		 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
   20254 		 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
   20255 		 theInstr);
   20256       goto not_supported;
   20257    decode_noFX:
   20258       vassert(!allow_FX);
   20259       vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
   20260 		 "that can't be handled by Valgrind on this host. This instruction\n"
   20261 		 "requires a host that supports the General Purpose-Optional instructions.\n",
   20262 		 theInstr);
   20263       goto not_supported;
   20264    decode_noGX:
   20265       vassert(!allow_GX);
   20266       vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
   20267 		 "that can't be handled by Valgrind on this host. This instruction\n"
   20268 		 "requires a host that supports the Graphic-Optional instructions.\n",
   20269 		 theInstr);
   20270       goto not_supported;
   20271    decode_noDFP:
   20272       vassert(!allow_DFP);
   20273       vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
   20274 		 "that can't be handled by Valgrind on this host.  This instruction\n"
   20275 		 "requires a host that supports DFP instructions.\n",
   20276 		 theInstr);
   20277       goto not_supported;
   20278    decode_noP8:
   20279       vassert(!allow_isa_2_07);
   20280       vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
   20281 		 "by Valgrind on this host.  This instruction requires a host that\n"
   20282 		 "supports Power 8 instructions.\n",
   20283 		 theInstr);
   20284       goto not_supported;
   20285 
   20286 
   20287    decode_failure:
   20288    /* All decode failures end up here. */
   20289    opc2 = (theInstr) & 0x7FF;
   20290    if (sigill_diag) {
   20291       vex_printf("disInstr(ppc): unhandled instruction: "
   20292                  "0x%x\n", theInstr);
   20293       vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
   20294                  opc1, opc1, opc2, opc2);
   20295    }
   20296 
   20297    not_supported:
   20298    /* Tell the dispatcher that this insn cannot be decoded, and so has
   20299       not been executed, and (is currently) the next to be executed.
   20300       CIA should be up-to-date since it made so at the start of each
   20301       insn, but nevertheless be paranoid and update it again right
   20302       now. */
   20303    putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
   20304    dres.len         = 0;
   20305    dres.whatNext    = Dis_StopHere;
   20306    dres.jk_StopHere = Ijk_NoDecode;
   20307    dres.continueAt  = 0;
   20308    return dres;
   20309    } /* switch (opc) for the main (primary) opcode switch. */
   20310 
   20311   decode_success:
   20312    /* All decode successes end up here. */
   20313    switch (dres.whatNext) {
   20314       case Dis_Continue:
   20315          putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
   20316          break;
   20317       case Dis_ResteerU:
   20318       case Dis_ResteerC:
   20319          putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
   20320          break;
   20321       case Dis_StopHere:
   20322          break;
   20323       default:
   20324          vassert(0);
   20325    }
   20326    DIP("\n");
   20327 
   20328    if (dres.len == 0) {
   20329       dres.len = 4;
   20330    } else {
   20331       vassert(dres.len == 20);
   20332    }
   20333    return dres;
   20334 }
   20335 
   20336 #undef DIP
   20337 #undef DIS
   20338 
   20339 
   20340 /*------------------------------------------------------------*/
   20341 /*--- Top-level fn                                         ---*/
   20342 /*------------------------------------------------------------*/
   20343 
   20344 /* Disassemble a single instruction into IR.  The instruction
   20345    is located in host memory at &guest_code[delta]. */
   20346 
   20347 DisResult disInstr_PPC ( IRSB*        irsb_IN,
   20348                          Bool         (*resteerOkFn) ( void*, Addr ),
   20349                          Bool         resteerCisOk,
   20350                          void*        callback_opaque,
   20351                          const UChar* guest_code_IN,
   20352                          Long         delta,
   20353                          Addr         guest_IP,
   20354                          VexArch      guest_arch,
   20355                          const VexArchInfo* archinfo,
   20356                          const VexAbiInfo*  abiinfo,
   20357                          VexEndness   host_endness_IN,
   20358                          Bool         sigill_diag_IN )
   20359 {
   20360    IRType     ty;
   20361    DisResult  dres;
   20362    UInt       mask32, mask64;
   20363    UInt hwcaps_guest = archinfo->hwcaps;
   20364 
   20365    vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
   20366 
   20367    /* global -- ick */
   20368    mode64 = guest_arch == VexArchPPC64;
   20369    ty = mode64 ? Ity_I64 : Ity_I32;
   20370    if (!mode64 && (host_endness_IN == VexEndnessLE)) {
   20371       vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
   20372       dres.len         = 0;
   20373       dres.whatNext    = Dis_StopHere;
   20374       dres.jk_StopHere = Ijk_NoDecode;
   20375       dres.continueAt   = 0;
   20376       return dres;
   20377    }
   20378 
   20379    /* do some sanity checks */
   20380    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
   20381             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
   20382             | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
   20383 
   20384    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
   20385             | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
   20386             | VEX_HWCAPS_PPC64_ISA2_07;
   20387 
   20388    if (mode64) {
   20389       vassert((hwcaps_guest & mask32) == 0);
   20390    } else {
   20391       vassert((hwcaps_guest & mask64) == 0);
   20392    }
   20393 
   20394    /* Set globals (see top of this file) */
   20395    guest_code           = guest_code_IN;
   20396    irsb                 = irsb_IN;
   20397    host_endness         = host_endness_IN;
   20398 
   20399    guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
   20400    guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
   20401 
   20402    dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
   20403                              delta, archinfo, abiinfo, sigill_diag_IN);
   20404 
   20405    return dres;
   20406 }
   20407 
   20408 
   20409 /*------------------------------------------------------------*/
   20410 /*--- Unused stuff                                         ---*/
   20411 /*------------------------------------------------------------*/
   20412 
   20413 ///* A potentially more memcheck-friendly implementation of Clz32, with
   20414 //   the boundary case Clz32(0) = 32, which is what ppc requires. */
   20415 //
   20416 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
   20417 //{
   20418 //   /* Welcome ... to SSA R Us. */
   20419 //   IRTemp n1  = newTemp(Ity_I32);
   20420 //   IRTemp n2  = newTemp(Ity_I32);
   20421 //   IRTemp n3  = newTemp(Ity_I32);
   20422 //   IRTemp n4  = newTemp(Ity_I32);
   20423 //   IRTemp n5  = newTemp(Ity_I32);
   20424 //   IRTemp n6  = newTemp(Ity_I32);
   20425 //   IRTemp n7  = newTemp(Ity_I32);
   20426 //   IRTemp n8  = newTemp(Ity_I32);
   20427 //   IRTemp n9  = newTemp(Ity_I32);
   20428 //   IRTemp n10 = newTemp(Ity_I32);
   20429 //   IRTemp n11 = newTemp(Ity_I32);
   20430 //   IRTemp n12 = newTemp(Ity_I32);
   20431 //
   20432 //   /* First, propagate the most significant 1-bit into all lower
   20433 //      positions in the word. */
   20434 //   /* unsigned int clz ( unsigned int n )
   20435 //      {
   20436 //         n |= (n >> 1);
   20437 //         n |= (n >> 2);
   20438 //         n |= (n >> 4);
   20439 //         n |= (n >> 8);
   20440 //         n |= (n >> 16);
   20441 //         return bitcount(~n);
   20442 //      }
   20443 //   */
   20444 //   assign(n1, mkexpr(arg));
   20445 //   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
   20446 //   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
   20447 //   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
   20448 //   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
   20449 //   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
   20450 //   /* This gives a word of the form 0---01---1.  Now invert it, giving
   20451 //      a word of the form 1---10---0, then do a population-count idiom
   20452 //      (to count the 1s, which is the number of leading zeroes, or 32
   20453 //      if the original word was 0. */
   20454 //   assign(n7, unop(Iop_Not32, mkexpr(n6)));
   20455 //
   20456 //   /* unsigned int bitcount ( unsigned int n )
   20457 //      {
   20458 //         n = n - ((n >> 1) & 0x55555555);
   20459 //         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
   20460 //         n = (n + (n >> 4)) & 0x0F0F0F0F;
   20461 //         n = n + (n >> 8);
   20462 //         n = (n + (n >> 16)) & 0x3F;
   20463 //         return n;
   20464 //      }
   20465 //   */
   20466 //   assign(n8,
   20467 //          binop(Iop_Sub32,
   20468 //                mkexpr(n7),
   20469 //                binop(Iop_And32,
   20470 //                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
   20471 //                      mkU32(0x55555555))));
   20472 //   assign(n9,
   20473 //          binop(Iop_Add32,
   20474 //                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
   20475 //                binop(Iop_And32,
   20476 //                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
   20477 //                      mkU32(0x33333333))));
   20478 //   assign(n10,
   20479 //          binop(Iop_And32,
   20480 //                binop(Iop_Add32,
   20481 //                      mkexpr(n9),
   20482 //                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
   20483 //                mkU32(0x0F0F0F0F)));
   20484 //   assign(n11,
   20485 //          binop(Iop_Add32,
   20486 //                mkexpr(n10),
   20487 //                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
   20488 //   assign(n12,
   20489 //          binop(Iop_Add32,
   20490 //                mkexpr(n11),
   20491 //                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
   20492 //   return
   20493 //      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
   20494 //}
   20495 
   20496 /*--------------------------------------------------------------------*/
   20497 /*--- end                                         guest_ppc_toIR.c ---*/
   20498 /*--------------------------------------------------------------------*/
   20499