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