1
2
3/*--------------------------------------------------------------------*/
4/*--- begin                                       guest_ppc_toIR.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
10
11   Copyright (C) 2004-2011 OpenWorks LLP
12      info@open-works.net
13
14   This program is free software; you can redistribute it and/or
15   modify it under the terms of the GNU General Public License as
16   published by the Free Software Foundation; either version 2 of the
17   License, or (at your option) any later version.
18
19   This program is distributed in the hope that it will be useful, but
20   WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22   General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, write to the Free Software
26   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27   02110-1301, USA.
28
29   The GNU General Public License is contained in the file COPYING.
30
31   Neither the names of the U.S. Department of Energy nor the
32   University of California nor the names of its contributors may be
33   used to endorse or promote products derived from this software
34   without prior written permission.
35*/
36
37/* TODO 18/Nov/05:
38
39   Spot rld... cases which are simply left/right shifts and emit
40   Shl64/Shr64 accordingly.
41
42   Altivec
43   - datastream insns
44   - lvxl,stvxl: load/store with 'least recently used' hint
45   - vexptefp, vlogefp
46
47   LIMITATIONS:
48
49   Various, including:
50
51   - Some invalid forms of lswi and lswx are accepted when they should
52     not be.
53
54   - Floating Point:
55     - All exceptions disabled in FPSCR
56     - condition codes not set in FPSCR
57
58   - Altivec floating point:
59     - vmaddfp, vnmsubfp
60       Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
61       system default of Non-Java mode, we get some small errors
62       (lowest bit only).
63       This is because Non-Java mode brutally hacks denormalised results
64       to zero, whereas we keep maximum accuracy.  However, using
65       Non-Java mode would give us more inaccuracy, as our intermediate
66       results would then be zeroed, too.
67
68   - AbiHints for the stack red zone are only emitted for
69       unconditional calls and returns (bl, blr).  They should also be
70       emitted for conditional calls and returns, but we don't have a
71       way to express that right now.  Ah well.
72*/
73
74/* "Special" instructions.
75
76   This instruction decoder can decode four special instructions
77   which mean nothing natively (are no-ops as far as regs/mem are
78   concerned) but have meaning for supporting Valgrind.  A special
79   instruction is flagged by a 16-byte preamble:
80
81      32-bit mode: 54001800 54006800 5400E800 54009800
82                   (rlwinm 0,0,3,0,0; rlwinm 0,0,13,0,0;
83                    rlwinm 0,0,29,0,0; rlwinm 0,0,19,0,0)
84
85      64-bit mode: 78001800 78006800 7800E802 78009802
86                   (rotldi 0,0,3; rotldi 0,0,13;
87                    rotldi 0,0,61; rotldi 0,0,51)
88
89   Following that, one of the following 3 are allowed
90   (standard interpretation in parentheses):
91
92      7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
93      7C421378 (or 2,2,2)   %R3 = guest_NRADDR
94      7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11
95      7C842378 (or 4,4,4)   %R3 = guest_NRADDR_GPR2
96
97   Any other bytes following the 16-byte preamble are illegal and
98   constitute a failure in instruction decoding.  This all assumes
99   that the preamble will never occur except in specific code
100   fragments designed for Valgrind to catch.
101*/
102
103
104/* Translates PPC32/64 code to IR. */
105
106/* References
107
108#define PPC32
109   "PowerPC Microprocessor Family:
110    The Programming Environments Manual for 32-Bit Microprocessors"
111    02/21/2000
112    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
113
114#define PPC64
115   "PowerPC Microprocessor Family:
116    Programming Environments Manual for 64-Bit Microprocessors"
117    06/10/2003
118   http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
119
120#define AV
121   "PowerPC Microprocessor Family:
122    AltiVec(TM) Technology Programming Environments Manual"
123    07/10/2003
124   http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
125*/
126
127#include "libvex_basictypes.h"
128#include "libvex_ir.h"
129#include "libvex.h"
130#include "libvex_guest_ppc32.h"
131#include "libvex_guest_ppc64.h"
132
133#include "main_util.h"
134#include "main_globals.h"
135#include "guest_generic_bb_to_IR.h"
136#include "guest_ppc_defs.h"
137
138
139/*------------------------------------------------------------*/
140/*--- Globals                                              ---*/
141/*------------------------------------------------------------*/
142
143/* These are set at the start of the translation of an insn, right
144   down in disInstr_PPC, so that we don't have to pass them around
145   endlessly.  They are all constant during the translation of any
146   given insn. */
147
148/* We need to know this to do sub-register accesses correctly. */
149static Bool host_is_bigendian;
150
151/* Pointer to the guest code area. */
152static UChar* guest_code;
153
154/* The guest address corresponding to guest_code[0]. */
155static Addr64 guest_CIA_bbstart;
156
157/* The guest address for the instruction currently being
158   translated. */
159static Addr64 guest_CIA_curr_instr;
160
161/* The IRSB* into which we're generating code. */
162static IRSB* irsb;
163
164/* Is our guest binary 32 or 64bit?  Set at each call to
165   disInstr_PPC below. */
166static Bool mode64 = False;
167
168// Given a pointer to a function as obtained by "& functionname" in C,
169// produce a pointer to the actual entry point for the function.  For
170// most platforms it's the identity function.  Unfortunately, on
171// ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and
172// ppc64-aix5.
173static void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f )
174{
175   if (vbi->host_ppc_calls_use_fndescrs) {
176      /* f is a pointer to a 3-word function descriptor, of which the
177         first word is the entry address. */
178      /* note, this is correct even with cross-jitting, since this is
179         purely a host issue, not a guest one. */
180      HWord* fdescr = (HWord*)f;
181      return (void*)(fdescr[0]);
182   } else {
183      /* Simple; "& f" points directly at the code for f. */
184      return f;
185   }
186}
187
188#define SIGN_BIT  0x8000000000000000ULL
189#define SIGN_MASK 0x7fffffffffffffffULL
190#define SIGN_BIT32  0x80000000
191#define SIGN_MASK32 0x7fffffff
192
193
194/*------------------------------------------------------------*/
195/*--- Debugging output                                     ---*/
196/*------------------------------------------------------------*/
197
198#define DIP(format, args...)           \
199   if (vex_traceflags & VEX_TRACE_FE)  \
200      vex_printf(format, ## args)
201
202#define DIS(buf, format, args...)      \
203   if (vex_traceflags & VEX_TRACE_FE)  \
204      vex_sprintf(buf, format, ## args)
205
206
207/*------------------------------------------------------------*/
208/*--- Offsets of various parts of the ppc32/64 guest state ---*/
209/*------------------------------------------------------------*/
210
211#define offsetofPPCGuestState(_x) \
212   (mode64 ? offsetof(VexGuestPPC64State, _x) : \
213             offsetof(VexGuestPPC32State, _x))
214
215#define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
216#define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
217#define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
218#define OFFB_LR          offsetofPPCGuestState(guest_LR)
219#define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
220#define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
221#define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
222#define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
223#define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
224#define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
225#define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
226#define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
227#define OFFB_EMWARN      offsetofPPCGuestState(guest_EMWARN)
228#define OFFB_TISTART     offsetofPPCGuestState(guest_TISTART)
229#define OFFB_TILEN       offsetofPPCGuestState(guest_TILEN)
230#define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
231#define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
232
233
234/*------------------------------------------------------------*/
235/*--- Extract instruction fields                          --- */
236/*------------------------------------------------------------*/
237
238/* Extract field from insn, given idx (zero = lsb) and field length */
239#define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
240
241/* Extract primary opcode, instr[31:26] */
242static UChar ifieldOPC( UInt instr ) {
243   return toUChar( IFIELD( instr, 26, 6 ) );
244}
245
246/* Extract 10-bit secondary opcode, instr[10:1] */
247static UInt ifieldOPClo10 ( UInt instr) {
248   return IFIELD( instr, 1, 10 );
249}
250
251/* Extract 9-bit secondary opcode, instr[9:1] */
252static UInt ifieldOPClo9 ( UInt instr) {
253   return IFIELD( instr, 1, 9 );
254}
255
256/* Extract 5-bit secondary opcode, instr[5:1] */
257static UInt ifieldOPClo5 ( UInt instr) {
258   return IFIELD( instr, 1, 5 );
259}
260
261/* Extract RD (destination register) field, instr[25:21] */
262static UChar ifieldRegDS( UInt instr ) {
263   return toUChar( IFIELD( instr, 21, 5 ) );
264}
265
266/* Extract XT (destination register) field, instr[0,25:21] */
267static UChar ifieldRegXT ( UInt instr )
268{
269  UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
270  UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
271  return (upper_bit << 5) | lower_bits;
272}
273
274/* Extract XS (store source register) field, instr[0,25:21] */
275static inline UChar ifieldRegXS ( UInt instr )
276{
277  return ifieldRegXT ( instr );
278}
279
280/* Extract RA (1st source register) field, instr[20:16] */
281static UChar ifieldRegA ( UInt instr ) {
282   return toUChar( IFIELD( instr, 16, 5 ) );
283}
284
285/* Extract XA (1st source register) field, instr[2,20:16] */
286static UChar ifieldRegXA ( UInt instr )
287{
288  UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
289  UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
290  return (upper_bit << 5) | lower_bits;
291}
292
293/* Extract RB (2nd source register) field, instr[15:11] */
294static UChar ifieldRegB ( UInt instr ) {
295   return toUChar( IFIELD( instr, 11, 5 ) );
296}
297
298/* Extract XB (2nd source register) field, instr[1,15:11] */
299static UChar ifieldRegXB ( UInt instr )
300{
301  UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
302  UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
303  return (upper_bit << 5) | lower_bits;
304}
305
306/* Extract RC (3rd source register) field, instr[10:6] */
307static UChar ifieldRegC ( UInt instr ) {
308   return toUChar( IFIELD( instr, 6, 5 ) );
309}
310
311/* Extract XC (3rd source register) field, instr[3,10:6] */
312static UChar ifieldRegXC ( UInt instr )
313{
314  UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
315  UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
316  return (upper_bit << 5) | lower_bits;
317}
318
319/* Extract bit 10, instr[10] */
320static UChar ifieldBIT10 ( UInt instr ) {
321   return toUChar( IFIELD( instr, 10, 1 ) );
322}
323
324/* Extract 2nd lowest bit, instr[1] */
325static UChar ifieldBIT1 ( UInt instr ) {
326   return toUChar( IFIELD( instr, 1, 1 ) );
327}
328
329/* Extract lowest bit, instr[0] */
330static UChar ifieldBIT0 ( UInt instr ) {
331   return toUChar( instr & 0x1 );
332}
333
334/* Extract unsigned bottom half, instr[15:0] */
335static UInt ifieldUIMM16 ( UInt instr ) {
336   return instr & 0xFFFF;
337}
338
339/* Extract unsigned bottom 26 bits, instr[25:0] */
340static UInt ifieldUIMM26 ( UInt instr ) {
341   return instr & 0x3FFFFFF;
342}
343
344/* Extract DM field, instr[9:8] */
345static UChar ifieldDM ( UInt instr ) {
346   return toUChar( IFIELD( instr, 8, 2 ) );
347}
348
349/* Extract SHW field, instr[9:8] */
350static inline UChar ifieldSHW ( UInt instr )
351{
352  return ifieldDM ( instr );
353}
354
355/*------------------------------------------------------------*/
356/*--- Guest-state identifiers                              ---*/
357/*------------------------------------------------------------*/
358
359typedef enum {
360    PPC_GST_CIA,    // Current Instruction Address
361    PPC_GST_LR,     // Link Register
362    PPC_GST_CTR,    // Count Register
363    PPC_GST_XER,    // Overflow, carry flags, byte count
364    PPC_GST_CR,     // Condition Register
365    PPC_GST_FPSCR,  // Floating Point Status/Control Register
366    PPC_GST_VRSAVE, // Vector Save/Restore Register
367    PPC_GST_VSCR,   // Vector Status and Control Register
368    PPC_GST_EMWARN, // Emulation warnings
369    PPC_GST_TISTART,// For icbi: start of area to invalidate
370    PPC_GST_TILEN,  // For icbi: length of area to invalidate
371    PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
372    PPC_GST_SPRG3_RO, // SPRG3
373    PPC_GST_MAX
374} PPC_GST;
375
376#define MASK_FPSCR_RN   0x3
377#define MASK_FPSCR_FPRF 0x1F000
378#define MASK_VSCR_VALID 0x00010001
379
380
381/*------------------------------------------------------------*/
382/*---  FP Helpers                                          ---*/
383/*------------------------------------------------------------*/
384
385/* Produce the 32-bit pattern corresponding to the supplied
386   float. */
387static UInt float_to_bits ( Float f )
388{
389   union { UInt i; Float f; } u;
390   vassert(4 == sizeof(UInt));
391   vassert(4 == sizeof(Float));
392   vassert(4 == sizeof(u));
393   u.f = f;
394   return u.i;
395}
396
397
398/*------------------------------------------------------------*/
399/*--- Misc Helpers                                         ---*/
400/*------------------------------------------------------------*/
401
402/* Generate mask with 1's from 'begin' through 'end',
403   wrapping if begin > end.
404   begin->end works from right to left, 0=lsb
405*/
406static UInt MASK32( UInt begin, UInt end )
407{
408   UInt m1, m2, mask;
409   vassert(begin < 32);
410   vassert(end < 32);
411   m1   = ((UInt)(-1)) << begin;
412   m2   = ((UInt)(-1)) << end << 1;
413   mask = m1 ^ m2;
414   if (begin > end) mask = ~mask;  // wrap mask
415   return mask;
416}
417
418/* ditto for 64bit mask */
419static ULong MASK64( UInt begin, UInt end )
420{
421   ULong m1, m2, mask;
422   vassert(begin < 64);
423   vassert(end < 64);
424   m1   = ((ULong)(-1)) << begin;
425   m2   = ((ULong)(-1)) << end << 1;
426   mask = m1 ^ m2;
427   if (begin > end) mask = ~mask;  // wrap mask
428   return mask;
429}
430
431static Addr64 nextInsnAddr( void )
432{
433   return guest_CIA_curr_instr + 4;
434}
435
436
437/*------------------------------------------------------------*/
438/*--- Helper bits and pieces for deconstructing the        ---*/
439/*--- ppc32/64 insn stream.                                ---*/
440/*------------------------------------------------------------*/
441
442/* Add a statement to the list held by "irsb". */
443static void stmt ( IRStmt* st )
444{
445   addStmtToIRSB( irsb, st );
446}
447
448/* Generate a new temporary of the given type. */
449static IRTemp newTemp ( IRType ty )
450{
451   vassert(isPlausibleIRType(ty));
452   return newIRTemp( irsb->tyenv, ty );
453}
454
455/* Various simple conversions */
456
457static UChar extend_s_5to8 ( UChar x )
458{
459   return toUChar((((Int)x) << 27) >> 27);
460}
461
462static UInt extend_s_8to32( UChar x )
463{
464   return (UInt)((((Int)x) << 24) >> 24);
465}
466
467static UInt extend_s_16to32 ( UInt x )
468{
469   return (UInt)((((Int)x) << 16) >> 16);
470}
471
472static ULong extend_s_16to64 ( UInt x )
473{
474   return (ULong)((((Long)x) << 48) >> 48);
475}
476
477static ULong extend_s_26to64 ( UInt x )
478{
479   return (ULong)((((Long)x) << 38) >> 38);
480}
481
482static ULong extend_s_32to64 ( UInt x )
483{
484   return (ULong)((((Long)x) << 32) >> 32);
485}
486
487/* Do a big-endian load of a 32-bit word, regardless of the endianness
488   of the underlying host. */
489static UInt getUIntBigendianly ( UChar* p )
490{
491   UInt w = 0;
492   w = (w << 8) | p[0];
493   w = (w << 8) | p[1];
494   w = (w << 8) | p[2];
495   w = (w << 8) | p[3];
496   return w;
497}
498
499
500/*------------------------------------------------------------*/
501/*--- Helpers for constructing IR.                         ---*/
502/*------------------------------------------------------------*/
503
504static void assign ( IRTemp dst, IRExpr* e )
505{
506   stmt( IRStmt_WrTmp(dst, e) );
507}
508
509/* This generates a normal (non store-conditional) store. */
510static void storeBE ( IRExpr* addr, IRExpr* data )
511{
512   IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
513   vassert(tyA == Ity_I32 || tyA == Ity_I64);
514   stmt( IRStmt_Store(Iend_BE, addr, data) );
515}
516
517static IRExpr* unop ( IROp op, IRExpr* a )
518{
519   return IRExpr_Unop(op, a);
520}
521
522static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
523{
524   return IRExpr_Binop(op, a1, a2);
525}
526
527static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
528{
529   return IRExpr_Triop(op, a1, a2, a3);
530}
531
532static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
533                              IRExpr* a3, IRExpr* a4 )
534{
535   return IRExpr_Qop(op, a1, a2, a3, a4);
536}
537
538static IRExpr* mkexpr ( IRTemp tmp )
539{
540   return IRExpr_RdTmp(tmp);
541}
542
543static IRExpr* mkU8 ( UChar i )
544{
545   return IRExpr_Const(IRConst_U8(i));
546}
547
548static IRExpr* mkU16 ( UInt i )
549{
550   return IRExpr_Const(IRConst_U16(i));
551}
552
553static IRExpr* mkU32 ( UInt i )
554{
555   return IRExpr_Const(IRConst_U32(i));
556}
557
558static IRExpr* mkU64 ( ULong i )
559{
560   return IRExpr_Const(IRConst_U64(i));
561}
562
563static IRExpr* mkV128 ( UShort i )
564{
565   vassert(i == 0 || i == 0xffff);
566   return IRExpr_Const(IRConst_V128(i));
567}
568
569/* This generates a normal (non load-linked) load. */
570static IRExpr* loadBE ( IRType ty, IRExpr* addr )
571{
572   return IRExpr_Load(Iend_BE, ty, addr);
573}
574
575static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
576{
577   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
578   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
579   return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
580                                          unop(Iop_1Uto32, arg2)));
581}
582
583static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
584{
585   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
586   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
587   return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
588                                           unop(Iop_1Uto32, arg2)));
589}
590
591/* expand V128_8Ux16 to 2x V128_16Ux8's */
592static void expand8Ux16( IRExpr* vIn,
593                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
594{
595   IRTemp ones8x16 = newTemp(Ity_V128);
596
597   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
598   vassert(vEvn && *vEvn == IRTemp_INVALID);
599   vassert(vOdd && *vOdd == IRTemp_INVALID);
600   *vEvn = newTemp(Ity_V128);
601   *vOdd = newTemp(Ity_V128);
602
603   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
604   assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
605   assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
606                        binop(Iop_ShrV128, vIn, mkU8(8))) );
607}
608
609/* expand V128_8Sx16 to 2x V128_16Sx8's */
610static void expand8Sx16( IRExpr* vIn,
611                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
612{
613   IRTemp ones8x16 = newTemp(Ity_V128);
614
615   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
616   vassert(vEvn && *vEvn == IRTemp_INVALID);
617   vassert(vOdd && *vOdd == IRTemp_INVALID);
618   *vEvn = newTemp(Ity_V128);
619   *vOdd = newTemp(Ity_V128);
620
621   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
622   assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
623   assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
624                        binop(Iop_ShrV128, vIn, mkU8(8))) );
625}
626
627/* expand V128_16Uto8 to 2x V128_32Ux4's */
628static void expand16Ux8( IRExpr* vIn,
629                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
630{
631   IRTemp ones16x8 = newTemp(Ity_V128);
632
633   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
634   vassert(vEvn && *vEvn == IRTemp_INVALID);
635   vassert(vOdd && *vOdd == IRTemp_INVALID);
636   *vEvn = newTemp(Ity_V128);
637   *vOdd = newTemp(Ity_V128);
638
639   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
640   assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
641   assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
642                        binop(Iop_ShrV128, vIn, mkU8(16))) );
643}
644
645/* expand V128_16Sto8 to 2x V128_32Sx4's */
646static void expand16Sx8( IRExpr* vIn,
647                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
648{
649   IRTemp ones16x8 = newTemp(Ity_V128);
650
651   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
652   vassert(vEvn && *vEvn == IRTemp_INVALID);
653   vassert(vOdd && *vOdd == IRTemp_INVALID);
654   *vEvn = newTemp(Ity_V128);
655   *vOdd = newTemp(Ity_V128);
656
657   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
658   assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
659   assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
660                       binop(Iop_ShrV128, vIn, mkU8(16))) );
661}
662
663/* break V128 to 4xF64's*/
664static void breakV128to4xF64( IRExpr* t128,
665                              /*OUTs*/
666                              IRTemp* t3, IRTemp* t2,
667                              IRTemp* t1, IRTemp* t0 )
668{
669   IRTemp hi64 = newTemp(Ity_I64);
670   IRTemp lo64 = newTemp(Ity_I64);
671
672   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
673   vassert(t0 && *t0 == IRTemp_INVALID);
674   vassert(t1 && *t1 == IRTemp_INVALID);
675   vassert(t2 && *t2 == IRTemp_INVALID);
676   vassert(t3 && *t3 == IRTemp_INVALID);
677   *t0 = newTemp(Ity_F64);
678   *t1 = newTemp(Ity_F64);
679   *t2 = newTemp(Ity_F64);
680   *t3 = newTemp(Ity_F64);
681
682   assign( hi64, unop(Iop_V128HIto64, t128) );
683   assign( lo64, unop(Iop_V128to64,   t128) );
684   assign( *t3,
685           unop( Iop_F32toF64,
686                 unop( Iop_ReinterpI32asF32,
687                       unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
688   assign( *t2,
689           unop( Iop_F32toF64,
690                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
691   assign( *t1,
692           unop( Iop_F32toF64,
693                 unop( Iop_ReinterpI32asF32,
694                       unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
695   assign( *t0,
696           unop( Iop_F32toF64,
697                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
698}
699
700
701/* break V128 to 4xI32's, then sign-extend to I64's */
702static void breakV128to4x64S( IRExpr* t128,
703                              /*OUTs*/
704                              IRTemp* t3, IRTemp* t2,
705                              IRTemp* t1, IRTemp* t0 )
706{
707   IRTemp hi64 = newTemp(Ity_I64);
708   IRTemp lo64 = newTemp(Ity_I64);
709
710   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
711   vassert(t0 && *t0 == IRTemp_INVALID);
712   vassert(t1 && *t1 == IRTemp_INVALID);
713   vassert(t2 && *t2 == IRTemp_INVALID);
714   vassert(t3 && *t3 == IRTemp_INVALID);
715   *t0 = newTemp(Ity_I64);
716   *t1 = newTemp(Ity_I64);
717   *t2 = newTemp(Ity_I64);
718   *t3 = newTemp(Ity_I64);
719
720   assign( hi64, unop(Iop_V128HIto64, t128) );
721   assign( lo64, unop(Iop_V128to64,   t128) );
722   assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
723   assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
724   assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
725   assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
726}
727
728/* break V128 to 4xI32's, then zero-extend to I64's */
729static void breakV128to4x64U ( IRExpr* t128,
730                               /*OUTs*/
731                               IRTemp* t3, IRTemp* t2,
732                               IRTemp* t1, IRTemp* t0 )
733{
734   IRTemp hi64 = newTemp(Ity_I64);
735   IRTemp lo64 = newTemp(Ity_I64);
736
737   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
738   vassert(t0 && *t0 == IRTemp_INVALID);
739   vassert(t1 && *t1 == IRTemp_INVALID);
740   vassert(t2 && *t2 == IRTemp_INVALID);
741   vassert(t3 && *t3 == IRTemp_INVALID);
742   *t0 = newTemp(Ity_I64);
743   *t1 = newTemp(Ity_I64);
744   *t2 = newTemp(Ity_I64);
745   *t3 = newTemp(Ity_I64);
746
747   assign( hi64, unop(Iop_V128HIto64, t128) );
748   assign( lo64, unop(Iop_V128to64,   t128) );
749   assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
750   assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
751   assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
752   assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
753}
754
755static void breakV128to4x32( IRExpr* t128,
756                              /*OUTs*/
757                              IRTemp* t3, IRTemp* t2,
758                              IRTemp* t1, IRTemp* t0 )
759{
760   IRTemp hi64 = newTemp(Ity_I64);
761   IRTemp lo64 = newTemp(Ity_I64);
762
763   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
764   vassert(t0 && *t0 == IRTemp_INVALID);
765   vassert(t1 && *t1 == IRTemp_INVALID);
766   vassert(t2 && *t2 == IRTemp_INVALID);
767   vassert(t3 && *t3 == IRTemp_INVALID);
768   *t0 = newTemp(Ity_I32);
769   *t1 = newTemp(Ity_I32);
770   *t2 = newTemp(Ity_I32);
771   *t3 = newTemp(Ity_I32);
772
773   assign( hi64, unop(Iop_V128HIto64, t128) );
774   assign( lo64, unop(Iop_V128to64,   t128) );
775   assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
776   assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
777   assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
778   assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
779}
780
781
782/* Signed saturating narrow 64S to 32 */
783static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
784{
785   IRTemp hi32 = newTemp(Ity_I32);
786   IRTemp lo32 = newTemp(Ity_I32);
787
788   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
789
790   assign( hi32, unop(Iop_64HIto32, t64));
791   assign( lo32, unop(Iop_64to32,   t64));
792
793   return IRExpr_Mux0X(
794             /* if (hi32 == (lo32 >>s 31)) */
795             unop(Iop_1Uto8,
796                  binop(Iop_CmpEQ32, mkexpr(hi32),
797                        binop( Iop_Sar32, mkexpr(lo32), mkU8(31)))),
798             /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
799             binop(Iop_Add32, mkU32(0x7FFFFFFF),
800                   binop(Iop_Shr32, mkexpr(hi32), mkU8(31))),
801             /* then: within signed-32 range: lo half good enough */
802             mkexpr(lo32) );
803}
804
805/* Unsigned saturating narrow 64S to 32 */
806static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
807{
808   IRTemp hi32 = newTemp(Ity_I32);
809   IRTemp lo32 = newTemp(Ity_I32);
810
811   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
812
813   assign( hi32, unop(Iop_64HIto32, t64));
814   assign( lo32, unop(Iop_64to32,   t64));
815
816   return IRExpr_Mux0X(
817            /* if (top 32 bits of t64 are 0) */
818            unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0))),
819            /* else: positive saturate -> 0xFFFFFFFF */
820            mkU32(0xFFFFFFFF),
821            /* then: within unsigned-32 range: lo half good enough */
822            mkexpr(lo32) );
823}
824
825/* Signed saturate narrow 64->32, combining to V128 */
826static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
827                                 IRExpr* t1, IRExpr* t0 )
828{
829   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
830   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
831   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
832   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
833   return binop(Iop_64HLtoV128,
834                binop(Iop_32HLto64,
835                      mkQNarrow64Sto32( t3 ),
836                      mkQNarrow64Sto32( t2 )),
837                binop(Iop_32HLto64,
838                      mkQNarrow64Sto32( t1 ),
839                      mkQNarrow64Sto32( t0 )));
840}
841
842/* Unsigned saturate narrow 64->32, combining to V128 */
843static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
844                                 IRExpr* t1, IRExpr* t0 )
845{
846   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
847   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
848   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
849   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
850   return binop(Iop_64HLtoV128,
851                binop(Iop_32HLto64,
852                      mkQNarrow64Uto32( t3 ),
853                      mkQNarrow64Uto32( t2 )),
854                binop(Iop_32HLto64,
855                      mkQNarrow64Uto32( t1 ),
856                      mkQNarrow64Uto32( t0 )));
857}
858
859/* Simulate irops Iop_MullOdd*, since we don't have them  */
860#define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
861      binop(Iop_MullEven8Ux16, \
862            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
863            binop(Iop_ShrV128, expr_vB, mkU8(8)))
864
865#define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
866      binop(Iop_MullEven8Sx16, \
867            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
868            binop(Iop_ShrV128, expr_vB, mkU8(8)))
869
870#define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
871      binop(Iop_MullEven16Ux8, \
872            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
873            binop(Iop_ShrV128, expr_vB, mkU8(16)))
874
875#define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
876      binop(Iop_MullEven16Sx8, \
877            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
878            binop(Iop_ShrV128, expr_vB, mkU8(16)))
879
880static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
881{
882   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
883   return unop(Iop_32Sto64, unop(Iop_64to32, src));
884}
885
886static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
887{
888   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
889   return unop(Iop_32Uto64, unop(Iop_64to32, src));
890}
891
892static IROp mkSzOp ( IRType ty, IROp op8 )
893{
894   Int adj;
895   vassert(ty == Ity_I8  || ty == Ity_I16 ||
896           ty == Ity_I32 || ty == Ity_I64);
897   vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
898           op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
899           op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
900           op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
901           op8 == Iop_Not8 );
902   adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
903   return adj + op8;
904}
905
906/* Make sure we get valid 32 and 64bit addresses */
907static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
908{
909   vassert(ty == Ity_I32 || ty == Ity_I64);
910   return ( ty == Ity_I64 ?
911            (Addr64)addr :
912            (Addr64)extend_s_32to64( toUInt(addr) ) );
913}
914
915/* sz, ULong -> IRExpr */
916static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
917{
918   vassert(ty == Ity_I32 || ty == Ity_I64);
919   return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
920}
921
922/* sz, ULong -> IRConst */
923static IRConst* mkSzConst ( IRType ty, ULong imm64 )
924{
925   vassert(ty == Ity_I32 || ty == Ity_I64);
926   return ( ty == Ity_I64 ?
927            IRConst_U64(imm64) :
928            IRConst_U32((UInt)imm64) );
929}
930
931/* Sign extend imm16 -> IRExpr* */
932static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
933{
934   vassert(ty == Ity_I32 || ty == Ity_I64);
935   return ( ty == Ity_I64 ?
936            mkU64(extend_s_16to64(imm16)) :
937            mkU32(extend_s_16to32(imm16)) );
938}
939
940/* Sign extend imm32 -> IRExpr* */
941static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
942{
943   vassert(ty == Ity_I32 || ty == Ity_I64);
944   return ( ty == Ity_I64 ?
945            mkU64(extend_s_32to64(imm32)) :
946            mkU32(imm32) );
947}
948
949/* IR narrows I32/I64 -> I8/I16/I32 */
950static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
951{
952   vassert(ty == Ity_I32 || ty == Ity_I64);
953   return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
954}
955
956static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
957{
958   vassert(ty == Ity_I32 || ty == Ity_I64);
959   return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
960}
961
962static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
963{
964   vassert(ty == Ity_I32 || ty == Ity_I64);
965   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
966}
967
968/* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
969static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
970{
971   IROp op;
972   vassert(ty == Ity_I32 || ty == Ity_I64);
973   if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
974   else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
975   return unop(op, src);
976}
977
978static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
979{
980   IROp op;
981   vassert(ty == Ity_I32 || ty == Ity_I64);
982   if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
983   else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
984   return unop(op, src);
985}
986
987static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
988{
989   vassert(ty == Ity_I32 || ty == Ity_I64);
990   if (ty == Ity_I32)
991      return src;
992   return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
993}
994
995
996static Int integerGuestRegOffset ( UInt archreg )
997{
998   vassert(archreg < 32);
999
1000   // jrs: probably not necessary; only matters if we reference sub-parts
1001   // of the ppc registers, but that isn't the case
1002   // later: this might affect Altivec though?
1003   vassert(host_is_bigendian);
1004
1005   switch (archreg) {
1006   case  0: return offsetofPPCGuestState(guest_GPR0);
1007   case  1: return offsetofPPCGuestState(guest_GPR1);
1008   case  2: return offsetofPPCGuestState(guest_GPR2);
1009   case  3: return offsetofPPCGuestState(guest_GPR3);
1010   case  4: return offsetofPPCGuestState(guest_GPR4);
1011   case  5: return offsetofPPCGuestState(guest_GPR5);
1012   case  6: return offsetofPPCGuestState(guest_GPR6);
1013   case  7: return offsetofPPCGuestState(guest_GPR7);
1014   case  8: return offsetofPPCGuestState(guest_GPR8);
1015   case  9: return offsetofPPCGuestState(guest_GPR9);
1016   case 10: return offsetofPPCGuestState(guest_GPR10);
1017   case 11: return offsetofPPCGuestState(guest_GPR11);
1018   case 12: return offsetofPPCGuestState(guest_GPR12);
1019   case 13: return offsetofPPCGuestState(guest_GPR13);
1020   case 14: return offsetofPPCGuestState(guest_GPR14);
1021   case 15: return offsetofPPCGuestState(guest_GPR15);
1022   case 16: return offsetofPPCGuestState(guest_GPR16);
1023   case 17: return offsetofPPCGuestState(guest_GPR17);
1024   case 18: return offsetofPPCGuestState(guest_GPR18);
1025   case 19: return offsetofPPCGuestState(guest_GPR19);
1026   case 20: return offsetofPPCGuestState(guest_GPR20);
1027   case 21: return offsetofPPCGuestState(guest_GPR21);
1028   case 22: return offsetofPPCGuestState(guest_GPR22);
1029   case 23: return offsetofPPCGuestState(guest_GPR23);
1030   case 24: return offsetofPPCGuestState(guest_GPR24);
1031   case 25: return offsetofPPCGuestState(guest_GPR25);
1032   case 26: return offsetofPPCGuestState(guest_GPR26);
1033   case 27: return offsetofPPCGuestState(guest_GPR27);
1034   case 28: return offsetofPPCGuestState(guest_GPR28);
1035   case 29: return offsetofPPCGuestState(guest_GPR29);
1036   case 30: return offsetofPPCGuestState(guest_GPR30);
1037   case 31: return offsetofPPCGuestState(guest_GPR31);
1038   default: break;
1039   }
1040   vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1041}
1042
1043static IRExpr* getIReg ( UInt archreg )
1044{
1045   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1046   vassert(archreg < 32);
1047   return IRExpr_Get( integerGuestRegOffset(archreg), ty );
1048}
1049
1050/* Ditto, but write to a reg instead. */
1051static void putIReg ( UInt archreg, IRExpr* e )
1052{
1053   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1054   vassert(archreg < 32);
1055   vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
1056   stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
1057}
1058
1059
1060/* Floating point egisters are mapped to VSX registers[0..31]. */
1061static Int floatGuestRegOffset ( UInt archreg )
1062{
1063   vassert(archreg < 32);
1064
1065   switch (archreg) {
1066   case  0: return offsetofPPCGuestState(guest_VSR0);
1067   case  1: return offsetofPPCGuestState(guest_VSR1);
1068   case  2: return offsetofPPCGuestState(guest_VSR2);
1069   case  3: return offsetofPPCGuestState(guest_VSR3);
1070   case  4: return offsetofPPCGuestState(guest_VSR4);
1071   case  5: return offsetofPPCGuestState(guest_VSR5);
1072   case  6: return offsetofPPCGuestState(guest_VSR6);
1073   case  7: return offsetofPPCGuestState(guest_VSR7);
1074   case  8: return offsetofPPCGuestState(guest_VSR8);
1075   case  9: return offsetofPPCGuestState(guest_VSR9);
1076   case 10: return offsetofPPCGuestState(guest_VSR10);
1077   case 11: return offsetofPPCGuestState(guest_VSR11);
1078   case 12: return offsetofPPCGuestState(guest_VSR12);
1079   case 13: return offsetofPPCGuestState(guest_VSR13);
1080   case 14: return offsetofPPCGuestState(guest_VSR14);
1081   case 15: return offsetofPPCGuestState(guest_VSR15);
1082   case 16: return offsetofPPCGuestState(guest_VSR16);
1083   case 17: return offsetofPPCGuestState(guest_VSR17);
1084   case 18: return offsetofPPCGuestState(guest_VSR18);
1085   case 19: return offsetofPPCGuestState(guest_VSR19);
1086   case 20: return offsetofPPCGuestState(guest_VSR20);
1087   case 21: return offsetofPPCGuestState(guest_VSR21);
1088   case 22: return offsetofPPCGuestState(guest_VSR22);
1089   case 23: return offsetofPPCGuestState(guest_VSR23);
1090   case 24: return offsetofPPCGuestState(guest_VSR24);
1091   case 25: return offsetofPPCGuestState(guest_VSR25);
1092   case 26: return offsetofPPCGuestState(guest_VSR26);
1093   case 27: return offsetofPPCGuestState(guest_VSR27);
1094   case 28: return offsetofPPCGuestState(guest_VSR28);
1095   case 29: return offsetofPPCGuestState(guest_VSR29);
1096   case 30: return offsetofPPCGuestState(guest_VSR30);
1097   case 31: return offsetofPPCGuestState(guest_VSR31);
1098   default: break;
1099   }
1100   vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1101}
1102
1103static IRExpr* getFReg ( UInt archreg )
1104{
1105   vassert(archreg < 32);
1106   return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1107}
1108
1109/* Ditto, but write to a reg instead. */
1110static void putFReg ( UInt archreg, IRExpr* e )
1111{
1112   vassert(archreg < 32);
1113   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1114   stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1115}
1116
1117static Int vsxGuestRegOffset ( UInt archreg )
1118{
1119   vassert(archreg < 64);
1120   switch (archreg) {
1121   case  0: return offsetofPPCGuestState(guest_VSR0);
1122   case  1: return offsetofPPCGuestState(guest_VSR1);
1123   case  2: return offsetofPPCGuestState(guest_VSR2);
1124   case  3: return offsetofPPCGuestState(guest_VSR3);
1125   case  4: return offsetofPPCGuestState(guest_VSR4);
1126   case  5: return offsetofPPCGuestState(guest_VSR5);
1127   case  6: return offsetofPPCGuestState(guest_VSR6);
1128   case  7: return offsetofPPCGuestState(guest_VSR7);
1129   case  8: return offsetofPPCGuestState(guest_VSR8);
1130   case  9: return offsetofPPCGuestState(guest_VSR9);
1131   case 10: return offsetofPPCGuestState(guest_VSR10);
1132   case 11: return offsetofPPCGuestState(guest_VSR11);
1133   case 12: return offsetofPPCGuestState(guest_VSR12);
1134   case 13: return offsetofPPCGuestState(guest_VSR13);
1135   case 14: return offsetofPPCGuestState(guest_VSR14);
1136   case 15: return offsetofPPCGuestState(guest_VSR15);
1137   case 16: return offsetofPPCGuestState(guest_VSR16);
1138   case 17: return offsetofPPCGuestState(guest_VSR17);
1139   case 18: return offsetofPPCGuestState(guest_VSR18);
1140   case 19: return offsetofPPCGuestState(guest_VSR19);
1141   case 20: return offsetofPPCGuestState(guest_VSR20);
1142   case 21: return offsetofPPCGuestState(guest_VSR21);
1143   case 22: return offsetofPPCGuestState(guest_VSR22);
1144   case 23: return offsetofPPCGuestState(guest_VSR23);
1145   case 24: return offsetofPPCGuestState(guest_VSR24);
1146   case 25: return offsetofPPCGuestState(guest_VSR25);
1147   case 26: return offsetofPPCGuestState(guest_VSR26);
1148   case 27: return offsetofPPCGuestState(guest_VSR27);
1149   case 28: return offsetofPPCGuestState(guest_VSR28);
1150   case 29: return offsetofPPCGuestState(guest_VSR29);
1151   case 30: return offsetofPPCGuestState(guest_VSR30);
1152   case 31: return offsetofPPCGuestState(guest_VSR31);
1153   case 32: return offsetofPPCGuestState(guest_VSR32);
1154   case 33: return offsetofPPCGuestState(guest_VSR33);
1155   case 34: return offsetofPPCGuestState(guest_VSR34);
1156   case 35: return offsetofPPCGuestState(guest_VSR35);
1157   case 36: return offsetofPPCGuestState(guest_VSR36);
1158   case 37: return offsetofPPCGuestState(guest_VSR37);
1159   case 38: return offsetofPPCGuestState(guest_VSR38);
1160   case 39: return offsetofPPCGuestState(guest_VSR39);
1161   case 40: return offsetofPPCGuestState(guest_VSR40);
1162   case 41: return offsetofPPCGuestState(guest_VSR41);
1163   case 42: return offsetofPPCGuestState(guest_VSR42);
1164   case 43: return offsetofPPCGuestState(guest_VSR43);
1165   case 44: return offsetofPPCGuestState(guest_VSR44);
1166   case 45: return offsetofPPCGuestState(guest_VSR45);
1167   case 46: return offsetofPPCGuestState(guest_VSR46);
1168   case 47: return offsetofPPCGuestState(guest_VSR47);
1169   case 48: return offsetofPPCGuestState(guest_VSR48);
1170   case 49: return offsetofPPCGuestState(guest_VSR49);
1171   case 50: return offsetofPPCGuestState(guest_VSR50);
1172   case 51: return offsetofPPCGuestState(guest_VSR51);
1173   case 52: return offsetofPPCGuestState(guest_VSR52);
1174   case 53: return offsetofPPCGuestState(guest_VSR53);
1175   case 54: return offsetofPPCGuestState(guest_VSR54);
1176   case 55: return offsetofPPCGuestState(guest_VSR55);
1177   case 56: return offsetofPPCGuestState(guest_VSR56);
1178   case 57: return offsetofPPCGuestState(guest_VSR57);
1179   case 58: return offsetofPPCGuestState(guest_VSR58);
1180   case 59: return offsetofPPCGuestState(guest_VSR59);
1181   case 60: return offsetofPPCGuestState(guest_VSR60);
1182   case 61: return offsetofPPCGuestState(guest_VSR61);
1183   case 62: return offsetofPPCGuestState(guest_VSR62);
1184   case 63: return offsetofPPCGuestState(guest_VSR63);
1185   default: break;
1186   }
1187   vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1188}
1189
1190/* Vector registers are mapped to VSX registers[32..63]. */
1191static Int vectorGuestRegOffset ( UInt archreg )
1192{
1193   vassert(archreg < 32);
1194
1195   switch (archreg) {
1196   case  0: return offsetofPPCGuestState(guest_VSR32);
1197   case  1: return offsetofPPCGuestState(guest_VSR33);
1198   case  2: return offsetofPPCGuestState(guest_VSR34);
1199   case  3: return offsetofPPCGuestState(guest_VSR35);
1200   case  4: return offsetofPPCGuestState(guest_VSR36);
1201   case  5: return offsetofPPCGuestState(guest_VSR37);
1202   case  6: return offsetofPPCGuestState(guest_VSR38);
1203   case  7: return offsetofPPCGuestState(guest_VSR39);
1204   case  8: return offsetofPPCGuestState(guest_VSR40);
1205   case  9: return offsetofPPCGuestState(guest_VSR41);
1206   case 10: return offsetofPPCGuestState(guest_VSR42);
1207   case 11: return offsetofPPCGuestState(guest_VSR43);
1208   case 12: return offsetofPPCGuestState(guest_VSR44);
1209   case 13: return offsetofPPCGuestState(guest_VSR45);
1210   case 14: return offsetofPPCGuestState(guest_VSR46);
1211   case 15: return offsetofPPCGuestState(guest_VSR47);
1212   case 16: return offsetofPPCGuestState(guest_VSR48);
1213   case 17: return offsetofPPCGuestState(guest_VSR49);
1214   case 18: return offsetofPPCGuestState(guest_VSR50);
1215   case 19: return offsetofPPCGuestState(guest_VSR51);
1216   case 20: return offsetofPPCGuestState(guest_VSR52);
1217   case 21: return offsetofPPCGuestState(guest_VSR53);
1218   case 22: return offsetofPPCGuestState(guest_VSR54);
1219   case 23: return offsetofPPCGuestState(guest_VSR55);
1220   case 24: return offsetofPPCGuestState(guest_VSR56);
1221   case 25: return offsetofPPCGuestState(guest_VSR57);
1222   case 26: return offsetofPPCGuestState(guest_VSR58);
1223   case 27: return offsetofPPCGuestState(guest_VSR59);
1224   case 28: return offsetofPPCGuestState(guest_VSR60);
1225   case 29: return offsetofPPCGuestState(guest_VSR61);
1226   case 30: return offsetofPPCGuestState(guest_VSR62);
1227   case 31: return offsetofPPCGuestState(guest_VSR63);
1228   default: break;
1229   }
1230   vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1231}
1232
1233static IRExpr* getVReg ( UInt archreg )
1234{
1235   vassert(archreg < 32);
1236   return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1237}
1238
1239/* Ditto, but write to a reg instead. */
1240static void putVReg ( UInt archreg, IRExpr* e )
1241{
1242   vassert(archreg < 32);
1243   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1244   stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1245}
1246
1247/* Get contents of VSX guest register */
1248static IRExpr* getVSReg ( UInt archreg )
1249{
1250   vassert(archreg < 64);
1251   return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
1252}
1253
1254/* Ditto, but write to a VSX reg instead. */
1255static void putVSReg ( UInt archreg, IRExpr* e )
1256{
1257   vassert(archreg < 64);
1258   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1259   stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
1260}
1261
1262
1263static Int guestCR321offset ( UInt cr )
1264{
1265   switch (cr) {
1266   case 0: return offsetofPPCGuestState(guest_CR0_321 );
1267   case 1: return offsetofPPCGuestState(guest_CR1_321 );
1268   case 2: return offsetofPPCGuestState(guest_CR2_321 );
1269   case 3: return offsetofPPCGuestState(guest_CR3_321 );
1270   case 4: return offsetofPPCGuestState(guest_CR4_321 );
1271   case 5: return offsetofPPCGuestState(guest_CR5_321 );
1272   case 6: return offsetofPPCGuestState(guest_CR6_321 );
1273   case 7: return offsetofPPCGuestState(guest_CR7_321 );
1274   default: vpanic("guestCR321offset(ppc)");
1275   }
1276}
1277
1278static Int guestCR0offset ( UInt cr )
1279{
1280   switch (cr) {
1281   case 0: return offsetofPPCGuestState(guest_CR0_0 );
1282   case 1: return offsetofPPCGuestState(guest_CR1_0 );
1283   case 2: return offsetofPPCGuestState(guest_CR2_0 );
1284   case 3: return offsetofPPCGuestState(guest_CR3_0 );
1285   case 4: return offsetofPPCGuestState(guest_CR4_0 );
1286   case 5: return offsetofPPCGuestState(guest_CR5_0 );
1287   case 6: return offsetofPPCGuestState(guest_CR6_0 );
1288   case 7: return offsetofPPCGuestState(guest_CR7_0 );
1289   default: vpanic("guestCR3offset(ppc)");
1290   }
1291}
1292
1293/* Generate an IR sequence to do a popcount operation on the supplied
1294   IRTemp, and return a new IRTemp holding the result.  'ty' may be
1295   Ity_I32 or Ity_I64 only. */
1296static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src )
1297{
1298   Int i, shift[6];
1299   IRTemp mask[6];
1300   IRTemp old = IRTemp_INVALID;
1301   IRTemp nyu = IRTemp_INVALID;
1302
1303   vassert(ty == Ity_I64 || ty == Ity_I32);
1304
1305   if (ty == Ity_I32) {
1306      for (i = 0; i < 5; i++) {
1307         mask[i]  = newTemp(ty);
1308         shift[i] = 1 << i;
1309      }
1310      assign(mask[0], mkU32(0x55555555));
1311      assign(mask[1], mkU32(0x33333333));
1312      assign(mask[2], mkU32(0x0F0F0F0F));
1313      assign(mask[3], mkU32(0x00FF00FF));
1314      assign(mask[4], mkU32(0x0000FFFF));
1315      old = src;
1316      for (i = 0; i < 5; i++) {
1317         nyu = newTemp(ty);
1318         assign(nyu,
1319                binop(Iop_Add32,
1320                      binop(Iop_And32,
1321                            mkexpr(old),
1322                            mkexpr(mask[i])),
1323                      binop(Iop_And32,
1324                            binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1325                            mkexpr(mask[i]))));
1326         old = nyu;
1327      }
1328      return nyu;
1329   }
1330// else, ty == Ity_I64
1331   for (i = 0; i < 6; i++) {
1332      mask[i] = newTemp( Ity_I64 );
1333      shift[i] = 1 << i;
1334   }
1335   assign( mask[0], mkU64( 0x5555555555555555ULL ) );
1336   assign( mask[1], mkU64( 0x3333333333333333ULL ) );
1337   assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
1338   assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
1339   assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
1340   assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
1341   old = src;
1342   for (i = 0; i < 6; i++) {
1343      nyu = newTemp( Ity_I64 );
1344      assign( nyu,
1345              binop( Iop_Add64,
1346                     binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
1347                     binop( Iop_And64,
1348                            binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
1349                            mkexpr( mask[i] ) ) ) );
1350      old = nyu;
1351   }
1352   return nyu;
1353}
1354
1355
1356// ROTL(src32/64, rot_amt5/6)
1357static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1358                                          IRExpr* rot_amt )
1359{
1360   IRExpr *mask, *rot;
1361   vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1362
1363   if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1364      // rot = (src << rot_amt) | (src >> (64-rot_amt))
1365      mask = binop(Iop_And8, rot_amt, mkU8(63));
1366      rot  = binop(Iop_Or64,
1367                binop(Iop_Shl64, src, mask),
1368                binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1369   } else {
1370      // rot = (src << rot_amt) | (src >> (32-rot_amt))
1371      mask = binop(Iop_And8, rot_amt, mkU8(31));
1372      rot  = binop(Iop_Or32,
1373                binop(Iop_Shl32, src, mask),
1374                binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
1375   }
1376   /* Note: the MuxOX is not merely an optimisation; it's needed
1377      because otherwise the Shr is a shift by the word size when
1378      mask denotes zero.  For rotates by immediates, a lot of
1379      this junk gets folded out. */
1380   return IRExpr_Mux0X( mask, /*     zero rotate */ src,
1381                              /* non-zero rotate */ rot );
1382}
1383
1384/* Standard effective address calc: (rA + rB) */
1385static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1386{
1387   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1388   vassert(rA < 32);
1389   vassert(rB < 32);
1390   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1391}
1392
1393/* Standard effective address calc: (rA + simm) */
1394static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1395{
1396   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1397   vassert(rA < 32);
1398   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
1399                mkSzExtendS16(ty, simm16));
1400}
1401
1402/* Standard effective address calc: (rA|0) */
1403static IRExpr* ea_rAor0 ( UInt rA )
1404{
1405   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1406   vassert(rA < 32);
1407   if (rA == 0) {
1408      return mkSzImm(ty, 0);
1409   } else {
1410      return getIReg(rA);
1411   }
1412}
1413
1414/* Standard effective address calc: (rA|0) + rB */
1415static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1416{
1417   vassert(rA < 32);
1418   vassert(rB < 32);
1419   return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1420}
1421
1422/* Standard effective address calc: (rA|0) + simm16 */
1423static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
1424{
1425   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1426   vassert(rA < 32);
1427   if (rA == 0) {
1428      return mkSzExtendS16(ty, simm16);
1429   } else {
1430      return ea_rA_simm( rA, simm16 );
1431   }
1432}
1433
1434
1435/* Align effective address */
1436static IRExpr* addr_align( IRExpr* addr, UChar align )
1437{
1438   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1439   Long mask;
1440   switch (align) {
1441   case 1:  return addr;                    // byte aligned
1442   case 2:  mask = ((Long)-1) << 1; break;  // half-word aligned
1443   case 4:  mask = ((Long)-1) << 2; break;  // word aligned
1444   case 16: mask = ((Long)-1) << 4; break;  // quad-word aligned
1445   default:
1446      vex_printf("addr_align: align = %u\n", align);
1447      vpanic("addr_align(ppc)");
1448   }
1449
1450   vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1451   return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
1452}
1453
1454
1455/* Exit the trace if ADDR (intended to be a guest memory address) is
1456   not ALIGN-aligned, generating a request for a SIGBUS followed by a
1457   restart of the current insn. */
1458static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1459{
1460   vassert(align == 4 || align == 8);
1461   if (mode64) {
1462      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1463      stmt(
1464         IRStmt_Exit(
1465            binop(Iop_CmpNE64,
1466                  binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1467                  mkU64(0)),
1468            Ijk_SigBUS,
1469            IRConst_U64( guest_CIA_curr_instr )
1470         )
1471      );
1472   } else {
1473      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1474      stmt(
1475         IRStmt_Exit(
1476            binop(Iop_CmpNE32,
1477                  binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1478                  mkU32(0)),
1479            Ijk_SigBUS,
1480            IRConst_U32( guest_CIA_curr_instr )
1481         )
1482      );
1483   }
1484}
1485
1486
1487/* Generate AbiHints which mark points at which the ELF or PowerOpen
1488   ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1489   N) becomes undefined.  That is at function calls and returns.  ELF
1490   ppc32 doesn't have this "feature" (how fortunate for it).  nia is
1491   the address of the next instruction to be executed.
1492*/
1493static void make_redzone_AbiHint ( VexAbiInfo* vbi,
1494                                   IRTemp nia, HChar* who )
1495{
1496   Int szB = vbi->guest_stack_redzone_size;
1497   if (0) vex_printf("AbiHint: %s\n", who);
1498   vassert(szB >= 0);
1499   if (szB > 0) {
1500      if (mode64) {
1501         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1502         stmt( IRStmt_AbiHint(
1503                  binop(Iop_Sub64, getIReg(1), mkU64(szB)),
1504                  szB,
1505                  mkexpr(nia)
1506         ));
1507      } else {
1508         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1509         stmt( IRStmt_AbiHint(
1510                  binop(Iop_Sub32, getIReg(1), mkU32(szB)),
1511                  szB,
1512                  mkexpr(nia)
1513         ));
1514      }
1515   }
1516}
1517
1518
1519/*------------------------------------------------------------*/
1520/*--- Helpers for condition codes.                         ---*/
1521/*------------------------------------------------------------*/
1522
1523/* Condition register layout.
1524
1525   In the hardware, CR is laid out like this.  The leftmost end is the
1526   most significant bit in the register; however the IBM documentation
1527   numbers the bits backwards for some reason.
1528
1529   CR0      CR1    ..........   CR6       CR7
1530   0 .. 3   .......................  28 .. 31    (IBM bit numbering)
1531   31  28                             3    0     (normal bit numbering)
1532
1533   Each CR field is 4 bits:  [<,>,==,SO]
1534
1535   Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1536
1537   Indexing from BI to guest state:
1538
1539     let    n = BI / 4
1540          off = BI % 4
1541     this references CR n:
1542
1543        off==0   ->  guest_CRn_321 >> 3
1544        off==1   ->  guest_CRn_321 >> 2
1545        off==2   ->  guest_CRn_321 >> 1
1546        off==3   ->  guest_CRn_SO
1547
1548   Bear in mind the only significant bit in guest_CRn_SO is bit 0
1549   (normal notation) and in guest_CRn_321 the significant bits are
1550   3, 2 and 1 (normal notation).
1551*/
1552
1553static void putCR321 ( UInt cr, IRExpr* e )
1554{
1555   vassert(cr < 8);
1556   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1557   stmt( IRStmt_Put(guestCR321offset(cr), e) );
1558}
1559
1560static void putCR0 ( UInt cr, IRExpr* e )
1561{
1562   vassert(cr < 8);
1563   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1564   stmt( IRStmt_Put(guestCR0offset(cr), e) );
1565}
1566
1567static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1568{
1569   vassert(cr < 8);
1570   return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1571}
1572
1573static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1574{
1575   vassert(cr < 8);
1576   return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1577}
1578
1579/* Fetch the specified CR bit (as per IBM/hardware notation) and
1580   return it at the bottom of an I32; the top 31 bits are guaranteed
1581   to be zero. */
1582static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1583{
1584   UInt n   = bi / 4;
1585   UInt off = bi % 4;
1586   vassert(bi < 32);
1587   if (off == 3) {
1588      /* Fetch the SO bit for this CR field */
1589      /* Note: And32 is redundant paranoia iff guest state only has 0
1590         or 1 in that slot. */
1591      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1592   } else {
1593      /* Fetch the <, > or == bit for this CR field */
1594      return binop( Iop_And32,
1595                    binop( Iop_Shr32,
1596                           unop(Iop_8Uto32, getCR321(n)),
1597                           mkU8(toUChar(3-off)) ),
1598                    mkU32(1) );
1599   }
1600}
1601
1602/* Dually, write the least significant bit of BIT to the specified CR
1603   bit.  Indexing as per getCRbit. */
1604static void putCRbit ( UInt bi, IRExpr* bit )
1605{
1606   UInt    n, off;
1607   IRExpr* safe;
1608   vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
1609   safe = binop(Iop_And32, bit, mkU32(1));
1610   n   = bi / 4;
1611   off = bi % 4;
1612   vassert(bi < 32);
1613   if (off == 3) {
1614      /* This is the SO bit for this CR field */
1615      putCR0(n, unop(Iop_32to8, safe));
1616   } else {
1617      off = 3 - off;
1618      vassert(off == 1 || off == 2 || off == 3);
1619      putCR321(
1620         n,
1621         unop( Iop_32to8,
1622               binop( Iop_Or32,
1623                      /* old value with field masked out */
1624                      binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
1625                                       mkU32(~(1 << off))),
1626                      /* new value in the right place */
1627                      binop(Iop_Shl32, safe, mkU8(toUChar(off)))
1628               )
1629         )
1630      );
1631   }
1632}
1633
1634/* Fetch the specified CR bit (as per IBM/hardware notation) and
1635   return it somewhere in an I32; it does not matter where, but
1636   whichever bit it is, all other bits are guaranteed to be zero.  In
1637   other words, the I32-typed expression will be zero if the bit is
1638   zero and nonzero if the bit is 1.  Write into *where the index
1639   of where the bit will be. */
1640
1641static
1642IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
1643{
1644   UInt n   = bi / 4;
1645   UInt off = bi % 4;
1646   vassert(bi < 32);
1647   if (off == 3) {
1648      /* Fetch the SO bit for this CR field */
1649      /* Note: And32 is redundant paranoia iff guest state only has 0
1650         or 1 in that slot. */
1651      *where = 0;
1652      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1653   } else {
1654      /* Fetch the <, > or == bit for this CR field */
1655      *where = 3-off;
1656      return binop( Iop_And32,
1657                    unop(Iop_8Uto32, getCR321(n)),
1658                    mkU32(1 << (3-off)) );
1659   }
1660}
1661
1662/* Set the CR0 flags following an arithmetic operation.
1663   (Condition Register CR0 Field Definition, PPC32 p60)
1664*/
1665static IRExpr* getXER_SO ( void );
1666static void set_CR0 ( IRExpr* result )
1667{
1668   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
1669           typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
1670   if (mode64) {
1671      putCR321( 0, unop(Iop_64to8,
1672                        binop(Iop_CmpORD64S, result, mkU64(0))) );
1673   } else {
1674      putCR321( 0, unop(Iop_32to8,
1675                        binop(Iop_CmpORD32S, result, mkU32(0))) );
1676   }
1677   putCR0( 0, getXER_SO() );
1678}
1679
1680
1681/* Set the CR6 flags following an AltiVec compare operation.
1682 * NOTE: This also works for VSX single-precision compares.
1683 * */
1684static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
1685{
1686   /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
1687      all_ones  = (v[0] && v[1] && v[2] && v[3])
1688      all_zeros = ~(v[0] || v[1] || v[2] || v[3])
1689   */
1690   IRTemp v0 = newTemp(Ity_V128);
1691   IRTemp v1 = newTemp(Ity_V128);
1692   IRTemp v2 = newTemp(Ity_V128);
1693   IRTemp v3 = newTemp(Ity_V128);
1694   IRTemp rOnes  = newTemp(Ity_I8);
1695   IRTemp rZeros = newTemp(Ity_I8);
1696
1697   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
1698
1699   assign( v0, result );
1700   assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
1701   assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
1702   assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
1703
1704   assign( rZeros, unop(Iop_1Uto8,
1705       binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1706             unop(Iop_Not32,
1707                  unop(Iop_V128to32,
1708                       binop(Iop_OrV128,
1709                             binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
1710                             binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
1711                  ))) );
1712
1713   if (test_all_ones) {
1714      assign( rOnes, unop(Iop_1Uto8,
1715         binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1716               unop(Iop_V128to32,
1717                    binop(Iop_AndV128,
1718                          binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
1719                          binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
1720                    ))) );
1721      putCR321( 6, binop(Iop_Or8,
1722                         binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
1723                         binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
1724   } else {
1725      putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
1726   }
1727   putCR0( 6, mkU8(0) );
1728}
1729
1730
1731
1732/*------------------------------------------------------------*/
1733/*--- Helpers for XER flags.                               ---*/
1734/*------------------------------------------------------------*/
1735
1736static void putXER_SO ( IRExpr* e )
1737{
1738   IRExpr* so;
1739   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1740   so = binop(Iop_And8, e, mkU8(1));
1741   stmt( IRStmt_Put( OFFB_XER_SO, so ) );
1742}
1743
1744static void putXER_OV ( IRExpr* e )
1745{
1746   IRExpr* ov;
1747   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1748   ov = binop(Iop_And8, e, mkU8(1));
1749   stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
1750}
1751
1752static void putXER_CA ( IRExpr* e )
1753{
1754   IRExpr* ca;
1755   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1756   ca = binop(Iop_And8, e, mkU8(1));
1757   stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
1758}
1759
1760static void putXER_BC ( IRExpr* e )
1761{
1762   IRExpr* bc;
1763   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1764   bc = binop(Iop_And8, e, mkU8(0x7F));
1765   stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
1766}
1767
1768static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
1769{
1770   return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
1771}
1772
1773static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
1774{
1775   return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
1776}
1777
1778static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
1779{
1780   return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
1781}
1782
1783static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
1784{
1785   return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
1786}
1787
1788static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
1789{
1790   IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
1791   return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
1792}
1793
1794static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
1795{
1796   return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
1797}
1798
1799static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
1800{
1801   IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
1802   return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
1803}
1804
1805
1806/* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
1807   %XER.SO accordingly. */
1808
1809static void set_XER_OV_32( UInt op, IRExpr* res,
1810                           IRExpr* argL, IRExpr* argR )
1811{
1812   IRTemp  t64;
1813   IRExpr* xer_ov;
1814   vassert(op < PPCG_FLAG_OP_NUMBER);
1815   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
1816   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
1817   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
1818
1819#  define INT32_MIN 0x80000000
1820
1821#  define XOR2(_aa,_bb) \
1822      binop(Iop_Xor32,(_aa),(_bb))
1823
1824#  define XOR3(_cc,_dd,_ee) \
1825      binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
1826
1827#  define AND3(_ff,_gg,_hh) \
1828      binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
1829
1830#define NOT(_jj) \
1831      unop(Iop_Not32, (_jj))
1832
1833   switch (op) {
1834   case /* 0  */ PPCG_FLAG_OP_ADD:
1835   case /* 1  */ PPCG_FLAG_OP_ADDE:
1836      /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
1837      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
1838      xer_ov
1839         = AND3( XOR3(argL,argR,mkU32(-1)),
1840                 XOR2(argL,res),
1841                 mkU32(INT32_MIN) );
1842      /* xer_ov can only be 0 or 1<<31 */
1843      xer_ov
1844         = binop(Iop_Shr32, xer_ov, mkU8(31) );
1845      break;
1846
1847   case /* 2  */ PPCG_FLAG_OP_DIVW:
1848      /* (argL == INT32_MIN && argR == -1) || argR == 0 */
1849      xer_ov
1850         = mkOR1(
1851              mkAND1(
1852                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
1853                 binop(Iop_CmpEQ32, argR, mkU32(-1))
1854              ),
1855              binop(Iop_CmpEQ32, argR, mkU32(0) )
1856           );
1857      xer_ov
1858         = unop(Iop_1Uto32, xer_ov);
1859      break;
1860
1861   case /* 3  */ PPCG_FLAG_OP_DIVWU:
1862      /* argR == 0 */
1863      xer_ov
1864         = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
1865      break;
1866
1867   case /* 4  */ PPCG_FLAG_OP_MULLW:
1868      /* OV true if result can't be represented in 32 bits
1869         i.e sHi != sign extension of sLo */
1870      t64 = newTemp(Ity_I64);
1871      assign( t64, binop(Iop_MullS32, argL, argR) );
1872      xer_ov
1873         = binop( Iop_CmpNE32,
1874                  unop(Iop_64HIto32, mkexpr(t64)),
1875                  binop( Iop_Sar32,
1876                         unop(Iop_64to32, mkexpr(t64)),
1877                         mkU8(31))
1878                  );
1879      xer_ov
1880         = unop(Iop_1Uto32, xer_ov);
1881      break;
1882
1883   case /* 5  */ PPCG_FLAG_OP_NEG:
1884      /* argL == INT32_MIN */
1885      xer_ov
1886         = unop( Iop_1Uto32,
1887                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
1888      break;
1889
1890   case /* 6  */ PPCG_FLAG_OP_SUBF:
1891   case /* 7  */ PPCG_FLAG_OP_SUBFC:
1892   case /* 8  */ PPCG_FLAG_OP_SUBFE:
1893      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
1894      xer_ov
1895         = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
1896                 XOR2(NOT(argL),res),
1897                 mkU32(INT32_MIN) );
1898      /* xer_ov can only be 0 or 1<<31 */
1899      xer_ov
1900         = binop(Iop_Shr32, xer_ov, mkU8(31) );
1901      break;
1902
1903   case PPCG_FLAG_OP_DIVWEU:
1904      xer_ov
1905               = binop( Iop_Or32,
1906                        unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
1907                        unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
1908      break;
1909
1910   case PPCG_FLAG_OP_DIVWE:
1911
1912      /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
1913       * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
1914       * an overflow is implied.
1915       */
1916      xer_ov = binop( Iop_Or32,
1917                      unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
1918                      unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
1919                              mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
1920                                      binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
1921      break;
1922
1923
1924
1925   default:
1926      vex_printf("set_XER_OV: op = %u\n", op);
1927      vpanic("set_XER_OV(ppc)");
1928   }
1929
1930   /* xer_ov MUST denote either 0 or 1, no other value allowed */
1931   putXER_OV( unop(Iop_32to8, xer_ov) );
1932
1933   /* Update the summary overflow */
1934   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
1935
1936#  undef INT32_MIN
1937#  undef AND3
1938#  undef XOR3
1939#  undef XOR2
1940#  undef NOT
1941}
1942
1943static void set_XER_OV_64( UInt op, IRExpr* res,
1944                           IRExpr* argL, IRExpr* argR )
1945{
1946   IRExpr* xer_ov;
1947   vassert(op < PPCG_FLAG_OP_NUMBER);
1948   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
1949   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
1950   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
1951
1952#  define INT64_MIN 0x8000000000000000ULL
1953
1954#  define XOR2(_aa,_bb) \
1955      binop(Iop_Xor64,(_aa),(_bb))
1956
1957#  define XOR3(_cc,_dd,_ee) \
1958      binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
1959
1960#  define AND3(_ff,_gg,_hh) \
1961      binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
1962
1963#define NOT(_jj) \
1964      unop(Iop_Not64, (_jj))
1965
1966   switch (op) {
1967   case /* 0  */ PPCG_FLAG_OP_ADD:
1968   case /* 1  */ PPCG_FLAG_OP_ADDE:
1969      /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
1970      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
1971      xer_ov
1972         = AND3( XOR3(argL,argR,mkU64(-1)),
1973                 XOR2(argL,res),
1974                 mkU64(INT64_MIN) );
1975      /* xer_ov can only be 0 or 1<<63 */
1976      xer_ov
1977         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
1978      break;
1979
1980   case /* 2  */ PPCG_FLAG_OP_DIVW:
1981      /* (argL == INT64_MIN && argR == -1) || argR == 0 */
1982      xer_ov
1983         = mkOR1(
1984              mkAND1(
1985                 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
1986                 binop(Iop_CmpEQ64, argR, mkU64(-1))
1987              ),
1988              binop(Iop_CmpEQ64, argR, mkU64(0) )
1989           );
1990      break;
1991
1992   case /* 3  */ PPCG_FLAG_OP_DIVWU:
1993      /* argR == 0 */
1994      xer_ov
1995         = binop(Iop_CmpEQ64, argR, mkU64(0));
1996      break;
1997
1998   case /* 4  */ PPCG_FLAG_OP_MULLW: {
1999      /* OV true if result can't be represented in 64 bits
2000         i.e sHi != sign extension of sLo */
2001      xer_ov
2002         = binop( Iop_CmpNE32,
2003                  unop(Iop_64HIto32, res),
2004                  binop( Iop_Sar32,
2005                         unop(Iop_64to32, res),
2006                         mkU8(31))
2007                  );
2008      break;
2009   }
2010
2011   case /* 5  */ PPCG_FLAG_OP_NEG:
2012      /* argL == INT64_MIN */
2013      xer_ov
2014         = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
2015      break;
2016
2017   case /* 6  */ PPCG_FLAG_OP_SUBF:
2018   case /* 7  */ PPCG_FLAG_OP_SUBFC:
2019   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2020      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2021      xer_ov
2022         = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
2023                 XOR2(NOT(argL),res),
2024                 mkU64(INT64_MIN) );
2025      /* xer_ov can only be 0 or 1<<63 */
2026      xer_ov
2027         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2028      break;
2029
2030   case PPCG_FLAG_OP_DIVDE:
2031
2032      /* If argR == 0, we must set the OV bit.  But there's another condition
2033       * where we can get overflow set for divde . . . when the
2034       * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
2035       * both dividend and divisor are non-zero, it implies an overflow.
2036       */
2037      xer_ov
2038                  = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2039                           mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
2040                                   mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
2041                                           binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
2042      break;
2043
2044   case PPCG_FLAG_OP_DIVDEU:
2045     /* If argR == 0 or if argL >= argR, set OV. */
2046     xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2047                         binop( Iop_CmpLE64U, argR, argL ) );
2048     break;
2049
2050   default:
2051      vex_printf("set_XER_OV: op = %u\n", op);
2052      vpanic("set_XER_OV(ppc64)");
2053   }
2054
2055   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2056   putXER_OV( unop(Iop_1Uto8, xer_ov) );
2057
2058   /* Update the summary overflow */
2059   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2060
2061#  undef INT64_MIN
2062#  undef AND3
2063#  undef XOR3
2064#  undef XOR2
2065#  undef NOT
2066}
2067
2068static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
2069                         IRExpr* argL, IRExpr* argR )
2070{
2071   if (ty == Ity_I32)
2072      set_XER_OV_32( op, res, argL, argR );
2073   else
2074      set_XER_OV_64( op, res, argL, argR );
2075}
2076
2077
2078
2079/* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2080   value being OLDCA.  Set %XER.CA accordingly. */
2081
2082static void set_XER_CA_32 ( UInt op, IRExpr* res,
2083                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2084{
2085   IRExpr* xer_ca;
2086   vassert(op < PPCG_FLAG_OP_NUMBER);
2087   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
2088   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
2089   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
2090   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
2091
2092   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2093      seems reasonable given that it's always generated by
2094      getXER_CA32(), which masks it accordingly.  In any case it being
2095      0 or 1 is an invariant of the ppc guest state representation;
2096      if it has any other value, that invariant has been violated. */
2097
2098   switch (op) {
2099   case /* 0 */ PPCG_FLAG_OP_ADD:
2100      /* res <u argL */
2101      xer_ca
2102         = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
2103      break;
2104
2105   case /* 1 */ PPCG_FLAG_OP_ADDE:
2106      /* res <u argL || (old_ca==1 && res==argL) */
2107      xer_ca
2108         = mkOR1(
2109              binop(Iop_CmpLT32U, res, argL),
2110              mkAND1(
2111                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2112                 binop(Iop_CmpEQ32, res, argL)
2113              )
2114           );
2115      xer_ca
2116         = unop(Iop_1Uto32, xer_ca);
2117      break;
2118
2119   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2120      /* res <u argR || (old_ca==1 && res==argR) */
2121      xer_ca
2122         = mkOR1(
2123              binop(Iop_CmpLT32U, res, argR),
2124              mkAND1(
2125                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2126                 binop(Iop_CmpEQ32, res, argR)
2127              )
2128           );
2129      xer_ca
2130         = unop(Iop_1Uto32, xer_ca);
2131      break;
2132
2133   case /* 7 */ PPCG_FLAG_OP_SUBFC:
2134   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2135      /* res <=u argR */
2136      xer_ca
2137         = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
2138      break;
2139
2140   case /* 10 */ PPCG_FLAG_OP_SRAW:
2141      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2142         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2143         bit of argL. */
2144      /* This term valid for shift amount < 32 only */
2145      xer_ca
2146         = binop(
2147              Iop_And32,
2148              binop(Iop_Sar32, argL, mkU8(31)),
2149              binop( Iop_And32,
2150                     argL,
2151                     binop( Iop_Sub32,
2152                            binop(Iop_Shl32, mkU32(1),
2153                                             unop(Iop_32to8,argR)),
2154                            mkU32(1) )
2155                     )
2156              );
2157      xer_ca
2158         = IRExpr_Mux0X(
2159              /* shift amt > 31 ? */
2160              unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)),
2161              /* no -- be like srawi */
2162              unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))),
2163              /* yes -- get sign bit of argL */
2164              binop(Iop_Shr32, argL, mkU8(31))
2165           );
2166      break;
2167
2168   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2169      /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2170         0.  Since the shift amount is known to be in the range
2171         0 .. 31 inclusive the following seems viable:
2172         xer.ca == 1 iff the following is nonzero:
2173         (argL >>s 31)           -- either all 0s or all 1s
2174         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2175      xer_ca
2176         = binop(
2177              Iop_And32,
2178              binop(Iop_Sar32, argL, mkU8(31)),
2179              binop( Iop_And32,
2180                     argL,
2181                     binop( Iop_Sub32,
2182                            binop(Iop_Shl32, mkU32(1),
2183                                             unop(Iop_32to8,argR)),
2184                            mkU32(1) )
2185                     )
2186              );
2187      xer_ca
2188         = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2189      break;
2190
2191   default:
2192      vex_printf("set_XER_CA: op = %u\n", op);
2193      vpanic("set_XER_CA(ppc)");
2194   }
2195
2196   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2197   putXER_CA( unop(Iop_32to8, xer_ca) );
2198}
2199
2200static void set_XER_CA_64 ( UInt op, IRExpr* res,
2201                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2202{
2203   IRExpr* xer_ca;
2204   vassert(op < PPCG_FLAG_OP_NUMBER);
2205   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
2206   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
2207   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
2208   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
2209
2210   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2211      seems reasonable given that it's always generated by
2212      getXER_CA32(), which masks it accordingly.  In any case it being
2213      0 or 1 is an invariant of the ppc guest state representation;
2214      if it has any other value, that invariant has been violated. */
2215
2216   switch (op) {
2217   case /* 0 */ PPCG_FLAG_OP_ADD:
2218      /* res <u argL */
2219      xer_ca
2220         = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2221      break;
2222
2223   case /* 1 */ PPCG_FLAG_OP_ADDE:
2224      /* res <u argL || (old_ca==1 && res==argL) */
2225      xer_ca
2226         = mkOR1(
2227              binop(Iop_CmpLT64U, res, argL),
2228              mkAND1(
2229                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2230                 binop(Iop_CmpEQ64, res, argL)
2231                 )
2232              );
2233      xer_ca
2234         = unop(Iop_1Uto32, xer_ca);
2235      break;
2236
2237   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2238      /* res <u argR || (old_ca==1 && res==argR) */
2239      xer_ca
2240         = mkOR1(
2241              binop(Iop_CmpLT64U, res, argR),
2242              mkAND1(
2243                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2244                 binop(Iop_CmpEQ64, res, argR)
2245              )
2246           );
2247      xer_ca
2248         = unop(Iop_1Uto32, xer_ca);
2249      break;
2250
2251   case /* 7 */ PPCG_FLAG_OP_SUBFC:
2252   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2253      /* res <=u argR */
2254      xer_ca
2255         = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2256      break;
2257
2258
2259   case /* 10 */ PPCG_FLAG_OP_SRAW:
2260      /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2261         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2262         bit of argL. */
2263         /* This term valid for shift amount < 31 only */
2264
2265      xer_ca
2266         = binop(
2267              Iop_And64,
2268              binop(Iop_Sar64, argL, mkU8(31)),
2269              binop( Iop_And64,
2270                     argL,
2271                     binop( Iop_Sub64,
2272                            binop(Iop_Shl64, mkU64(1),
2273                                             unop(Iop_64to8,argR)),
2274                            mkU64(1) )
2275              )
2276           );
2277      xer_ca
2278         = IRExpr_Mux0X(
2279              /* shift amt > 31 ? */
2280              unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(31), argR)),
2281              /* no -- be like srawi */
2282              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
2283              /* yes -- get sign bit of argL */
2284              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
2285           );
2286      break;
2287
2288   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2289      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2290         Since the shift amount is known to be in the range 0 .. 31
2291         inclusive the following seems viable:
2292         xer.ca == 1 iff the following is nonzero:
2293         (argL >>s 31)           -- either all 0s or all 1s
2294         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2295
2296      xer_ca
2297         = binop(
2298              Iop_And64,
2299              binop(Iop_Sar64, argL, mkU8(31)),
2300              binop( Iop_And64,
2301                     argL,
2302                     binop( Iop_Sub64,
2303                            binop(Iop_Shl64, mkU64(1),
2304                                             unop(Iop_64to8,argR)),
2305                            mkU64(1) )
2306              )
2307           );
2308      xer_ca
2309         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2310      break;
2311
2312
2313   case /* 12 */ PPCG_FLAG_OP_SRAD:
2314      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2315         If it is <= 63, behave like SRADI; else XER.CA is the sign
2316         bit of argL. */
2317         /* This term valid for shift amount < 63 only */
2318
2319      xer_ca
2320         = binop(
2321              Iop_And64,
2322              binop(Iop_Sar64, argL, mkU8(63)),
2323              binop( Iop_And64,
2324                     argL,
2325                     binop( Iop_Sub64,
2326                            binop(Iop_Shl64, mkU64(1),
2327                                             unop(Iop_64to8,argR)),
2328                            mkU64(1) )
2329              )
2330           );
2331      xer_ca
2332         = IRExpr_Mux0X(
2333              /* shift amt > 63 ? */
2334              unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)),
2335              /* no -- be like sradi */
2336              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
2337              /* yes -- get sign bit of argL */
2338              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
2339           );
2340      break;
2341
2342
2343   case /* 13 */ PPCG_FLAG_OP_SRADI:
2344      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2345         Since the shift amount is known to be in the range 0 .. 63
2346         inclusive, the following seems viable:
2347         xer.ca == 1 iff the following is nonzero:
2348         (argL >>s 63)           -- either all 0s or all 1s
2349         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2350
2351      xer_ca
2352         = binop(
2353              Iop_And64,
2354              binop(Iop_Sar64, argL, mkU8(63)),
2355              binop( Iop_And64,
2356                     argL,
2357                     binop( Iop_Sub64,
2358                            binop(Iop_Shl64, mkU64(1),
2359                                             unop(Iop_64to8,argR)),
2360                            mkU64(1) )
2361              )
2362           );
2363      xer_ca
2364         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2365      break;
2366
2367   default:
2368      vex_printf("set_XER_CA: op = %u\n", op);
2369      vpanic("set_XER_CA(ppc64)");
2370   }
2371
2372   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2373   putXER_CA( unop(Iop_32to8, xer_ca) );
2374}
2375
2376static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
2377                         IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2378{
2379   if (ty == Ity_I32)
2380      set_XER_CA_32( op, res, argL, argR, oldca );
2381   else
2382      set_XER_CA_64( op, res, argL, argR, oldca );
2383}
2384
2385
2386
2387/*------------------------------------------------------------*/
2388/*--- Read/write to guest-state                           --- */
2389/*------------------------------------------------------------*/
2390
2391static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
2392{
2393   IRType ty = mode64 ? Ity_I64 : Ity_I32;
2394   switch (reg) {
2395   case PPC_GST_SPRG3_RO:
2396      return IRExpr_Get( OFFB_SPRG3_RO, ty );
2397
2398   case PPC_GST_CIA:
2399      return IRExpr_Get( OFFB_CIA, ty );
2400
2401   case PPC_GST_LR:
2402      return IRExpr_Get( OFFB_LR, ty );
2403
2404   case PPC_GST_CTR:
2405      return IRExpr_Get( OFFB_CTR, ty );
2406
2407   case PPC_GST_VRSAVE:
2408      return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
2409
2410   case PPC_GST_VSCR:
2411      return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
2412                              mkU32(MASK_VSCR_VALID));
2413
2414   case PPC_GST_CR: {
2415      /* Synthesise the entire CR into a single word.  Expensive. */
2416#     define FIELD(_n)                                               \
2417         binop(Iop_Shl32,                                            \
2418               unop(Iop_8Uto32,                                      \
2419                    binop(Iop_Or8,                                   \
2420                          binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
2421                          binop(Iop_And8, getCR0(_n), mkU8(1))       \
2422                    )                                                \
2423               ),                                                    \
2424               mkU8(4 * (7-(_n)))                                    \
2425         )
2426      return binop(Iop_Or32,
2427                   binop(Iop_Or32,
2428                         binop(Iop_Or32, FIELD(0), FIELD(1)),
2429                         binop(Iop_Or32, FIELD(2), FIELD(3))
2430                         ),
2431                   binop(Iop_Or32,
2432                         binop(Iop_Or32, FIELD(4), FIELD(5)),
2433                         binop(Iop_Or32, FIELD(6), FIELD(7))
2434                         )
2435                   );
2436#     undef FIELD
2437   }
2438
2439   case PPC_GST_XER:
2440      return binop(Iop_Or32,
2441                   binop(Iop_Or32,
2442                         binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
2443                         binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
2444                   binop(Iop_Or32,
2445                         binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
2446                         getXER_BC32()));
2447
2448   default:
2449      vex_printf("getGST(ppc): reg = %u", reg);
2450      vpanic("getGST(ppc)");
2451   }
2452}
2453
2454/* Get a masked word from the given reg */
2455static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
2456{
2457   IRTemp val = newTemp(Ity_I32);
2458   vassert( reg < PPC_GST_MAX );
2459
2460   switch (reg) {
2461
2462   case PPC_GST_FPSCR: {
2463      /* Vex-generated code expects the FPSCR to be set as follows:
2464         all exceptions masked, round-to-nearest.
2465         This corresponds to a FPSCR value of 0x0. */
2466
2467      /* We're only keeping track of the rounding mode,
2468         so if the mask isn't asking for this, just return 0x0 */
2469      if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
2470         assign( val, IRExpr_Get( OFFB_FPROUND, Ity_I32 ) );
2471      } else {
2472         assign( val, mkU32(0x0) );
2473      }
2474      break;
2475   }
2476
2477   default:
2478      vex_printf("getGST_masked(ppc): reg = %u", reg);
2479      vpanic("getGST_masked(ppc)");
2480   }
2481
2482   if (mask != 0xFFFFFFFF) {
2483      return binop(Iop_And32, mkexpr(val), mkU32(mask));
2484   } else {
2485      return mkexpr(val);
2486   }
2487}
2488
2489/* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
2490   and return it at the bottom of an I32; the top 27 bits are
2491   guaranteed to be zero. */
2492static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
2493{
2494   UInt shft, mask;
2495
2496   vassert( fld < 8 );
2497   vassert( reg < PPC_GST_MAX );
2498
2499   shft = 4*(7-fld);
2500   mask = 0xF<<shft;
2501
2502   switch (reg) {
2503   case PPC_GST_XER:
2504      vassert(fld ==7);
2505      return binop(Iop_Or32,
2506                   binop(Iop_Or32,
2507                         binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
2508                         binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
2509                   binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
2510      break;
2511
2512   default:
2513      if (shft == 0)
2514         return getGST_masked( reg, mask );
2515      else
2516         return binop(Iop_Shr32,
2517                      getGST_masked( reg, mask ),
2518                      mkU8(toUChar( shft )));
2519   }
2520}
2521
2522static void putGST ( PPC_GST reg, IRExpr* src )
2523{
2524   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
2525   IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
2526   vassert( reg < PPC_GST_MAX );
2527   switch (reg) {
2528   case PPC_GST_IP_AT_SYSCALL:
2529      vassert( ty_src == ty );
2530      stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
2531      break;
2532   case PPC_GST_CIA:
2533      vassert( ty_src == ty );
2534      stmt( IRStmt_Put( OFFB_CIA, src ) );
2535      break;
2536   case PPC_GST_LR:
2537      vassert( ty_src == ty );
2538      stmt( IRStmt_Put( OFFB_LR, src ) );
2539      break;
2540   case PPC_GST_CTR:
2541      vassert( ty_src == ty );
2542      stmt( IRStmt_Put( OFFB_CTR, src ) );
2543      break;
2544   case PPC_GST_VRSAVE:
2545      vassert( ty_src == Ity_I32 );
2546      stmt( IRStmt_Put( OFFB_VRSAVE,src));
2547      break;
2548   case PPC_GST_VSCR:
2549      vassert( ty_src == Ity_I32 );
2550      stmt( IRStmt_Put( OFFB_VSCR,
2551                        binop(Iop_And32, src,
2552                              mkU32(MASK_VSCR_VALID)) ) );
2553      break;
2554   case PPC_GST_XER:
2555      vassert( ty_src == Ity_I32 );
2556      putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
2557      putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
2558      putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
2559      putXER_BC( unop(Iop_32to8, src) );
2560      break;
2561
2562   case PPC_GST_EMWARN:
2563      vassert( ty_src == Ity_I32 );
2564      stmt( IRStmt_Put( OFFB_EMWARN,src) );
2565      break;
2566
2567   case PPC_GST_TISTART:
2568      vassert( ty_src == ty );
2569      stmt( IRStmt_Put( OFFB_TISTART, src) );
2570      break;
2571
2572   case PPC_GST_TILEN:
2573      vassert( ty_src == ty );
2574      stmt( IRStmt_Put( OFFB_TILEN, src) );
2575      break;
2576
2577   default:
2578      vex_printf("putGST(ppc): reg = %u", reg);
2579      vpanic("putGST(ppc)");
2580   }
2581}
2582
2583/* Write masked src to the given reg */
2584static void putGST_masked ( PPC_GST reg, IRExpr* src, UInt mask )
2585{
2586   IRType ty = mode64 ? Ity_I64 : Ity_I32;
2587   vassert( reg < PPC_GST_MAX );
2588   vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
2589
2590   switch (reg) {
2591   case PPC_GST_FPSCR: {
2592      /* Allow writes to Rounding Mode */
2593      if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
2594         /* construct new fpround from new and old values as per mask:
2595            new fpround = (src & (3 & mask)) | (fpround & (3 & ~mask)) */
2596         stmt(
2597            IRStmt_Put(
2598               OFFB_FPROUND,
2599               binop(
2600                  Iop_Or32,
2601                  binop(Iop_And32, src, mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & mask)),
2602                  binop(
2603                     Iop_And32,
2604                     IRExpr_Get(OFFB_FPROUND,Ity_I32),
2605                     mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & ~mask)
2606                  )
2607               )
2608            )
2609         );
2610      }
2611
2612      /* Give EmWarn for attempted writes to:
2613         - Exception Controls
2614         - Non-IEEE Mode
2615      */
2616      if (mask & 0xFC) {  // Exception Control, Non-IEE mode
2617         VexEmWarn ew = EmWarn_PPCexns;
2618
2619         /* If any of the src::exception_control bits are actually set,
2620            side-exit to the next insn, reporting the warning,
2621            so that Valgrind's dispatcher sees the warning. */
2622         putGST( PPC_GST_EMWARN, mkU32(ew) );
2623         stmt(
2624            IRStmt_Exit(
2625               binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)),
2626               Ijk_EmWarn,
2627               mkSzConst( ty, nextInsnAddr()) ));
2628      }
2629
2630      /* Ignore all other writes */
2631      break;
2632   }
2633
2634   default:
2635      vex_printf("putGST_masked(ppc): reg = %u", reg);
2636      vpanic("putGST_masked(ppc)");
2637   }
2638}
2639
2640/* Write the least significant nibble of src to the specified
2641   REG[FLD] (as per IBM/hardware notation). */
2642static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
2643{
2644   UInt shft, mask;
2645
2646   vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
2647   vassert( fld < 8 );
2648   vassert( reg < PPC_GST_MAX );
2649
2650   shft = 4*(7-fld);
2651   mask = 0xF<<shft;
2652
2653   switch (reg) {
2654   case PPC_GST_CR:
2655      putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
2656      putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
2657      break;
2658
2659   default:
2660      if (shft == 0) {
2661         putGST_masked( reg, src, mask );
2662      } else {
2663         putGST_masked( reg,
2664                        binop(Iop_Shl32, src, mkU8(toUChar(shft))),
2665                        mask );
2666      }
2667   }
2668}
2669
2670/*------------------------------------------------------------*/
2671/* Helpers for VSX instructions that do floating point
2672 * operations and need to determine if a src contains a
2673 * special FP value.
2674 *
2675 *------------------------------------------------------------*/
2676
2677#define NONZERO_FRAC_MASK 0x000fffffffffffffULL
2678#define FP_FRAC_PART(x) binop( Iop_And64, \
2679                               mkexpr( x ), \
2680                               mkU64( NONZERO_FRAC_MASK ) )
2681
2682// Returns exponent part of a single precision floating point as I32
2683static IRExpr * fp_exp_part_sp(IRTemp src)
2684{
2685   return binop( Iop_And32,
2686                 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
2687                 mkU32( 0xff ) );
2688}
2689
2690// Returns exponent part of floating point as I32
2691static IRExpr * fp_exp_part(IRTemp src, Bool sp)
2692{
2693   IRExpr * exp;
2694   if (sp)
2695      return fp_exp_part_sp(src);
2696
2697   if (!mode64)
2698      exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
2699                                                      mkexpr( src ) ),
2700                                     mkU8( 20 ) ), mkU32( 0x7ff ) );
2701   else
2702      exp = unop( Iop_64to32,
2703                  binop( Iop_And64,
2704                         binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
2705                         mkU64( 0x7ff ) ) );
2706   return exp;
2707}
2708
2709static IRExpr * is_Inf_sp(IRTemp src)
2710{
2711   IRTemp frac_part = newTemp(Ity_I32);
2712   IRExpr * Inf_exp;
2713
2714   assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
2715   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
2716   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
2717}
2718
2719
2720// Infinity: exp = 7ff and fraction is zero; s = 0/1
2721static IRExpr * is_Inf(IRTemp src, Bool sp)
2722{
2723   IRExpr * Inf_exp, * hi32, * low32;
2724   IRTemp frac_part;
2725
2726   if (sp)
2727      return is_Inf_sp(src);
2728
2729   frac_part = newTemp(Ity_I64);
2730   assign( frac_part, FP_FRAC_PART(src) );
2731   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
2732   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
2733   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
2734   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
2735                                  mkU32( 0 ) ) );
2736}
2737
2738static IRExpr * is_Zero_sp(IRTemp src)
2739{
2740   IRTemp sign_less_part = newTemp(Ity_I32);
2741   assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
2742   return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
2743}
2744
2745// Zero: exp is zero and fraction is zero; s = 0/1
2746static IRExpr * is_Zero(IRTemp src, Bool sp)
2747{
2748   IRExpr * hi32, * low32;
2749   IRTemp sign_less_part;
2750   if (sp)
2751      return is_Zero_sp(src);
2752
2753   sign_less_part = newTemp(Ity_I64);
2754
2755   assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
2756   hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
2757   low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
2758   return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
2759                              mkU32( 0 ) );
2760}
2761
2762/*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
2763 *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
2764 *  This function returns an IRExpr value of '1' for any type of NaN.
2765 */
2766static IRExpr * is_NaN(IRTemp src)
2767{
2768   IRExpr * NaN_exp, * hi32, * low32;
2769   IRTemp frac_part = newTemp(Ity_I64);
2770
2771   assign( frac_part, FP_FRAC_PART(src) );
2772   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
2773   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
2774   NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
2775                    mkU32( 0x7ff ) );
2776
2777   return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
2778                                               mkU32( 0 ) ) );
2779}
2780
2781/* This function returns an IRExpr value of '1' for any type of NaN.
2782 * The passed 'src' argument is assumed to be Ity_I32.
2783 */
2784static IRExpr * is_NaN_32(IRTemp src)
2785{
2786#define NONZERO_FRAC_MASK32 0x007fffffULL
2787#define FP_FRAC_PART32(x) binop( Iop_And32, \
2788                                 mkexpr( x ), \
2789                                 mkU32( NONZERO_FRAC_MASK32 ) )
2790
2791   IRExpr * frac_part = FP_FRAC_PART32(src);
2792   IRExpr * exp_part = binop( Iop_And32,
2793                              binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
2794                              mkU32( 0x0ff ) );
2795   IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
2796
2797   return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
2798}
2799
2800/* This helper function performs the negation part of operations of the form:
2801 *    "Negate Multiply-<op>"
2802 *  where "<op>" is either "Add" or "Sub".
2803 *
2804 * This function takes one argument -- the floating point intermediate result (converted to
2805 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
2806 * the operation described above.
2807 */
2808static IRTemp getNegatedResult(IRTemp intermediateResult)
2809{
2810   ULong signbit_mask = 0x8000000000000000ULL;
2811   IRTemp signbit_32 = newTemp(Ity_I32);
2812   IRTemp resultantSignbit = newTemp(Ity_I1);
2813   IRTemp negatedResult = newTemp(Ity_I64);
2814   assign( signbit_32, binop( Iop_Shr32,
2815                          unop( Iop_64HIto32,
2816                                 binop( Iop_And64, mkexpr( intermediateResult ),
2817                                        mkU64( signbit_mask ) ) ),
2818                                 mkU8( 31 ) ) );
2819   /* We negate the signbit if and only if the intermediate result from the
2820    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
2821    */
2822   assign( resultantSignbit,
2823        unop( Iop_Not1,
2824              binop( Iop_CmpEQ32,
2825                     binop( Iop_Xor32,
2826                            mkexpr( signbit_32 ),
2827                            unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
2828                     mkU32( 1 ) ) ) );
2829
2830   assign( negatedResult,
2831        binop( Iop_Or64,
2832               binop( Iop_And64,
2833                      mkexpr( intermediateResult ),
2834                      mkU64( ~signbit_mask ) ),
2835               binop( Iop_32HLto64,
2836                      binop( Iop_Shl32,
2837                             unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
2838                             mkU8( 31 ) ),
2839                      mkU32( 0 ) ) ) );
2840
2841   return negatedResult;
2842}
2843
2844/* This helper function performs the negation part of operations of the form:
2845 *    "Negate Multiply-<op>"
2846 *  where "<op>" is either "Add" or "Sub".
2847 *
2848 * This function takes one argument -- the floating point intermediate result (converted to
2849 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
2850 * the operation described above.
2851 */
2852static IRTemp getNegatedResult_32(IRTemp intermediateResult)
2853{
2854   UInt signbit_mask = 0x80000000;
2855   IRTemp signbit_32 = newTemp(Ity_I32);
2856   IRTemp resultantSignbit = newTemp(Ity_I1);
2857   IRTemp negatedResult = newTemp(Ity_I32);
2858   assign( signbit_32, binop( Iop_Shr32,
2859                                 binop( Iop_And32, mkexpr( intermediateResult ),
2860                                        mkU32( signbit_mask ) ),
2861                                 mkU8( 31 ) ) );
2862   /* We negate the signbit if and only if the intermediate result from the
2863    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
2864    */
2865   assign( resultantSignbit,
2866        unop( Iop_Not1,
2867              binop( Iop_CmpEQ32,
2868                     binop( Iop_Xor32,
2869                            mkexpr( signbit_32 ),
2870                            unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
2871                     mkU32( 1 ) ) ) );
2872
2873   assign( negatedResult,
2874           binop( Iop_Or32,
2875                  binop( Iop_And32,
2876                         mkexpr( intermediateResult ),
2877                         mkU32( ~signbit_mask ) ),
2878                  binop( Iop_Shl32,
2879                         unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
2880                         mkU8( 31 ) ) ) );
2881
2882   return negatedResult;
2883}
2884
2885/*------------------------------------------------------------*/
2886/*--- Integer Instruction Translation                     --- */
2887/*------------------------------------------------------------*/
2888
2889/*
2890  Integer Arithmetic Instructions
2891*/
2892static Bool dis_int_arith ( UInt theInstr )
2893{
2894   /* D-Form, XO-Form */
2895   UChar opc1    = ifieldOPC(theInstr);
2896   UChar rD_addr = ifieldRegDS(theInstr);
2897   UChar rA_addr = ifieldRegA(theInstr);
2898   UInt  uimm16  = ifieldUIMM16(theInstr);
2899   UChar rB_addr = ifieldRegB(theInstr);
2900   UChar flag_OE = ifieldBIT10(theInstr);
2901   UInt  opc2    = ifieldOPClo9(theInstr);
2902   UChar flag_rC = ifieldBIT0(theInstr);
2903
2904   Long   simm16 = extend_s_16to64(uimm16);
2905   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
2906   IRTemp rA     = newTemp(ty);
2907   IRTemp rB     = newTemp(ty);
2908   IRTemp rD     = newTemp(ty);
2909
2910   Bool do_rc = False;
2911
2912   assign( rA, getIReg(rA_addr) );
2913   assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
2914
2915   switch (opc1) {
2916   /* D-Form */
2917   case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
2918      DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2919      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2920                         mkSzExtendS16(ty, uimm16) ) );
2921      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
2922                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2923                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2924      break;
2925
2926   case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
2927      DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2928      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2929                         mkSzExtendS16(ty, uimm16) ) );
2930      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
2931                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2932                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2933      do_rc = True;  // Always record to CR
2934      flag_rC = 1;
2935      break;
2936
2937   case 0x0E: // addi   (Add Immediate, PPC32 p350)
2938      // li rD,val   == addi rD,0,val
2939      // la disp(rA) == addi rD,rA,disp
2940      if ( rA_addr == 0 ) {
2941         DIP("li r%u,%d\n", rD_addr, (Int)simm16);
2942         assign( rD, mkSzExtendS16(ty, uimm16) );
2943      } else {
2944         DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2945         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2946                            mkSzExtendS16(ty, uimm16) ) );
2947      }
2948      break;
2949
2950   case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
2951      // lis rD,val == addis rD,0,val
2952      if ( rA_addr == 0 ) {
2953         DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
2954         assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
2955      } else {
2956         DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
2957         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2958                            mkSzExtendS32(ty, uimm16 << 16) ) );
2959      }
2960      break;
2961
2962   case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
2963      DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2964      if (mode64)
2965         assign( rD, unop(Iop_128to64,
2966                          binop(Iop_MullS64, mkexpr(rA),
2967                                mkSzExtendS16(ty, uimm16))) );
2968      else
2969         assign( rD, unop(Iop_64to32,
2970                          binop(Iop_MullS32, mkexpr(rA),
2971                                mkSzExtendS16(ty, uimm16))) );
2972      break;
2973
2974   case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
2975      DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2976      // rD = simm16 - rA
2977      assign( rD, binop( mkSzOp(ty, Iop_Sub8),
2978                         mkSzExtendS16(ty, uimm16),
2979                         mkexpr(rA)) );
2980      set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
2981                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2982                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2983      break;
2984
2985   /* XO-Form */
2986   case 0x1F:
2987      do_rc = True;    // All below record to CR
2988
2989      switch (opc2) {
2990      case 0x10A: // add  (Add, PPC32 p347)
2991         DIP("add%s%s r%u,r%u,r%u\n",
2992             flag_OE ? "o" : "", flag_rC ? ".":"",
2993             rD_addr, rA_addr, rB_addr);
2994         assign( rD, binop( mkSzOp(ty, Iop_Add8),
2995                            mkexpr(rA), mkexpr(rB) ) );
2996         if (flag_OE) {
2997            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
2998                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2999         }
3000         break;
3001
3002      case 0x00A: // addc      (Add Carrying, PPC32 p348)
3003         DIP("addc%s%s r%u,r%u,r%u\n",
3004             flag_OE ? "o" : "", flag_rC ? ".":"",
3005             rD_addr, rA_addr, rB_addr);
3006         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3007                            mkexpr(rA), mkexpr(rB)) );
3008         set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3009                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3010                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3011         if (flag_OE) {
3012            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
3013                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3014         }
3015         break;
3016
3017      case 0x08A: { // adde      (Add Extended, PPC32 p349)
3018         IRTemp old_xer_ca = newTemp(ty);
3019         DIP("adde%s%s r%u,r%u,r%u\n",
3020             flag_OE ? "o" : "", flag_rC ? ".":"",
3021             rD_addr, rA_addr, rB_addr);
3022         // rD = rA + rB + XER[CA]
3023         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3024         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3025                            binop( mkSzOp(ty, Iop_Add8),
3026                                   mkexpr(rB), mkexpr(old_xer_ca))) );
3027         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3028                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3029                     mkexpr(old_xer_ca) );
3030         if (flag_OE) {
3031            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3032                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3033         }
3034         break;
3035      }
3036
3037      case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
3038         IRTemp old_xer_ca = newTemp(ty);
3039         IRExpr *min_one;
3040         if (rB_addr != 0) {
3041            vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
3042            return False;
3043         }
3044         DIP("addme%s%s r%u,r%u,r%u\n",
3045             flag_OE ? "o" : "", flag_rC ? ".":"",
3046             rD_addr, rA_addr, rB_addr);
3047         // rD = rA + (-1) + XER[CA]
3048         // => Just another form of adde
3049         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3050         min_one = mkSzImm(ty, (Long)-1);
3051         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3052                            binop( mkSzOp(ty, Iop_Add8),
3053                                   min_one, mkexpr(old_xer_ca)) ));
3054         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3055                     mkexpr(rD), mkexpr(rA), min_one,
3056                     mkexpr(old_xer_ca) );
3057         if (flag_OE) {
3058            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3059                        mkexpr(rD), mkexpr(rA), min_one );
3060         }
3061         break;
3062      }
3063
3064      case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
3065         IRTemp old_xer_ca = newTemp(ty);
3066         if (rB_addr != 0) {
3067            vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
3068            return False;
3069         }
3070         DIP("addze%s%s r%u,r%u,r%u\n",
3071             flag_OE ? "o" : "", flag_rC ? ".":"",
3072             rD_addr, rA_addr, rB_addr);
3073         // rD = rA + (0) + XER[CA]
3074         // => Just another form of adde
3075         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3076         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3077                            mkexpr(rA), mkexpr(old_xer_ca)) );
3078         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3079                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3080                     mkexpr(old_xer_ca) );
3081         if (flag_OE) {
3082            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3083                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3084         }
3085         break;
3086      }
3087
3088      case 0x1EB: // divw       (Divide Word, PPC32 p388)
3089         DIP("divw%s%s r%u,r%u,r%u\n",
3090             flag_OE ? "o" : "", flag_rC ? ".":"",
3091             rD_addr, rA_addr, rB_addr);
3092         if (mode64) {
3093            /* Note:
3094               XER settings are mode independent, and reflect the
3095               overflow of the low-order 32bit result
3096               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3097            */
3098            /* rD[hi32] are undefined: setting them to sign of lo32
3099                - makes set_CR0 happy */
3100            IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
3101            IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
3102            assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
3103                                                         divisor) ) );
3104            if (flag_OE) {
3105               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3106                           mkexpr(rD), dividend, divisor );
3107            }
3108         } else {
3109            assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
3110            if (flag_OE) {
3111               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3112                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3113            }
3114         }
3115         /* Note:
3116            if (0x8000_0000 / -1) or (x / 0)
3117            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3118            => But _no_ exception raised. */
3119         break;
3120
3121      case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
3122         DIP("divwu%s%s r%u,r%u,r%u\n",
3123             flag_OE ? "o" : "", flag_rC ? ".":"",
3124             rD_addr, rA_addr, rB_addr);
3125         if (mode64) {
3126            /* Note:
3127               XER settings are mode independent, and reflect the
3128               overflow of the low-order 32bit result
3129               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3130            */
3131            IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
3132            IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
3133            assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
3134                                                         divisor) ) );
3135            if (flag_OE) {
3136               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3137                           mkexpr(rD), dividend, divisor );
3138            }
3139         } else {
3140            assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
3141            if (flag_OE) {
3142               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3143                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3144            }
3145         }
3146         /* Note: ditto comment divw, for (x / 0) */
3147         break;
3148
3149      case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
3150         if (flag_OE != 0) {
3151            vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
3152            return False;
3153         }
3154         DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3155             rD_addr, rA_addr, rB_addr);
3156         if (mode64) {
3157            /* rD[hi32] are undefined: setting them to sign of lo32
3158                - makes set_CR0 happy */
3159            assign( rD, binop(Iop_Sar64,
3160                           binop(Iop_Mul64,
3161                                 mk64lo32Sto64( mkexpr(rA) ),
3162                                 mk64lo32Sto64( mkexpr(rB) )),
3163                              mkU8(32)) );
3164         } else {
3165            assign( rD, unop(Iop_64HIto32,
3166                             binop(Iop_MullS32,
3167                                   mkexpr(rA), mkexpr(rB))) );
3168         }
3169         break;
3170
3171      case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
3172         if (flag_OE != 0) {
3173            vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
3174            return False;
3175         }
3176         DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3177             rD_addr, rA_addr, rB_addr);
3178         if (mode64) {
3179            /* rD[hi32] are undefined: setting them to sign of lo32
3180                - makes set_CR0 happy */
3181            assign( rD, binop(Iop_Sar64,
3182                           binop(Iop_Mul64,
3183                                 mk64lo32Uto64( mkexpr(rA) ),
3184                                 mk64lo32Uto64( mkexpr(rB) ) ),
3185                              mkU8(32)) );
3186         } else {
3187            assign( rD, unop(Iop_64HIto32,
3188                             binop(Iop_MullU32,
3189                                   mkexpr(rA), mkexpr(rB))) );
3190         }
3191         break;
3192
3193      case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
3194         DIP("mullw%s%s r%u,r%u,r%u\n",
3195             flag_OE ? "o" : "", flag_rC ? ".":"",
3196             rD_addr, rA_addr, rB_addr);
3197         if (mode64) {
3198            /* rD[hi32] are undefined: setting them to sign of lo32
3199                - set_XER_OV() and set_CR0() depend on this */
3200            IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
3201            IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
3202            assign( rD, binop(Iop_MullS32, a, b) );
3203            if (flag_OE) {
3204               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3205                           mkexpr(rD),
3206                           unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
3207            }
3208         } else {
3209            assign( rD, unop(Iop_64to32,
3210                             binop(Iop_MullU32,
3211                                   mkexpr(rA), mkexpr(rB))) );
3212            if (flag_OE) {
3213               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3214                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3215            }
3216         }
3217         break;
3218
3219      case 0x068: // neg        (Negate, PPC32 p493)
3220         if (rB_addr != 0) {
3221            vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
3222            return False;
3223         }
3224         DIP("neg%s%s r%u,r%u\n",
3225             flag_OE ? "o" : "", flag_rC ? ".":"",
3226             rD_addr, rA_addr);
3227         // rD = (~rA) + 1
3228         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3229                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
3230                            mkSzImm(ty, 1)) );
3231         if (flag_OE) {
3232            set_XER_OV( ty, PPCG_FLAG_OP_NEG,
3233                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3234         }
3235         break;
3236
3237      case 0x028: // subf       (Subtract From, PPC32 p537)
3238         DIP("subf%s%s r%u,r%u,r%u\n",
3239             flag_OE ? "o" : "", flag_rC ? ".":"",
3240             rD_addr, rA_addr, rB_addr);
3241         // rD = rB - rA
3242         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3243                            mkexpr(rB), mkexpr(rA)) );
3244         if (flag_OE) {
3245            set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
3246                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3247         }
3248         break;
3249
3250      case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
3251         DIP("subfc%s%s r%u,r%u,r%u\n",
3252             flag_OE ? "o" : "", flag_rC ? ".":"",
3253             rD_addr, rA_addr, rB_addr);
3254         // rD = rB - rA
3255         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3256                            mkexpr(rB), mkexpr(rA)) );
3257         set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
3258                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3259                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3260         if (flag_OE) {
3261            set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
3262                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3263         }
3264         break;
3265
3266      case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
3267         IRTemp old_xer_ca = newTemp(ty);
3268         DIP("subfe%s%s r%u,r%u,r%u\n",
3269             flag_OE ? "o" : "", flag_rC ? ".":"",
3270             rD_addr, rA_addr, rB_addr);
3271         // rD = (log not)rA + rB + XER[CA]
3272         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3273         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3274                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3275                            binop( mkSzOp(ty, Iop_Add8),
3276                                   mkexpr(rB), mkexpr(old_xer_ca))) );
3277         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3278                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3279                     mkexpr(old_xer_ca) );
3280         if (flag_OE) {
3281            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3282                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3283         }
3284         break;
3285      }
3286
3287      case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
3288         IRTemp old_xer_ca = newTemp(ty);
3289         IRExpr *min_one;
3290         if (rB_addr != 0) {
3291            vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
3292            return False;
3293         }
3294         DIP("subfme%s%s r%u,r%u\n",
3295             flag_OE ? "o" : "", flag_rC ? ".":"",
3296             rD_addr, rA_addr);
3297         // rD = (log not)rA + (-1) + XER[CA]
3298         // => Just another form of subfe
3299         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3300         min_one = mkSzImm(ty, (Long)-1);
3301         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3302                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3303                            binop( mkSzOp(ty, Iop_Add8),
3304                                   min_one, mkexpr(old_xer_ca))) );
3305         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3306                     mkexpr(rD), mkexpr(rA), min_one,
3307                     mkexpr(old_xer_ca) );
3308         if (flag_OE) {
3309            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3310                        mkexpr(rD), mkexpr(rA), min_one );
3311         }
3312         break;
3313      }
3314
3315      case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
3316         IRTemp old_xer_ca = newTemp(ty);
3317         if (rB_addr != 0) {
3318            vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
3319            return False;
3320         }
3321         DIP("subfze%s%s r%u,r%u\n",
3322             flag_OE ? "o" : "", flag_rC ? ".":"",
3323             rD_addr, rA_addr);
3324         // rD = (log not)rA + (0) + XER[CA]
3325         // => Just another form of subfe
3326         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3327         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3328                           unop( mkSzOp(ty, Iop_Not8),
3329                                 mkexpr(rA)), mkexpr(old_xer_ca)) );
3330         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3331                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3332                     mkexpr(old_xer_ca) );
3333         if (flag_OE) {
3334            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3335                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3336         }
3337         break;
3338      }
3339
3340
3341      /* 64bit Arithmetic */
3342      case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
3343         if (flag_OE != 0) {
3344            vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
3345            return False;
3346         }
3347         DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3348             rD_addr, rA_addr, rB_addr);
3349         assign( rD, unop(Iop_128HIto64,
3350                          binop(Iop_MullS64,
3351                                mkexpr(rA), mkexpr(rB))) );
3352
3353         break;
3354
3355      case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
3356         if (flag_OE != 0) {
3357            vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
3358            return False;
3359         }
3360         DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3361             rD_addr, rA_addr, rB_addr);
3362         assign( rD, unop(Iop_128HIto64,
3363                          binop(Iop_MullU64,
3364                                mkexpr(rA), mkexpr(rB))) );
3365         break;
3366
3367      case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
3368         DIP("mulld%s%s r%u,r%u,r%u\n",
3369             flag_OE ? "o" : "", flag_rC ? ".":"",
3370             rD_addr, rA_addr, rB_addr);
3371         assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
3372         if (flag_OE) {
3373            set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3374                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3375         }
3376         break;
3377
3378      case 0x1E9: // divd (Divide DWord, PPC64 p419)
3379         DIP("divd%s%s r%u,r%u,r%u\n",
3380             flag_OE ? "o" : "", flag_rC ? ".":"",
3381             rD_addr, rA_addr, rB_addr);
3382         assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
3383         if (flag_OE) {
3384            set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3385                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3386         }
3387         break;
3388         /* Note:
3389            if (0x8000_0000_0000_0000 / -1) or (x / 0)
3390            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3391            => But _no_ exception raised. */
3392
3393      case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
3394         DIP("divdu%s%s r%u,r%u,r%u\n",
3395             flag_OE ? "o" : "", flag_rC ? ".":"",
3396             rD_addr, rA_addr, rB_addr);
3397         assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
3398         if (flag_OE) {
3399            set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3400                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3401         }
3402         break;
3403         /* Note: ditto comment divd, for (x / 0) */
3404
3405      case 0x18B: // divweu (Divide Word Extended Unsigned)
3406      {
3407        /*
3408         *  If (RA) >= (RB), or if an attempt is made to perform the division
3409         *         <anything> / 0
3410         * then the contents of register RD are undefined as are (if Rc=1) the contents of
3411         * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
3412         * to 1.
3413         */
3414         IRTemp res = newTemp(Ity_I32);
3415         IRExpr * dividend, * divisor;
3416         DIP("divweu%s%s r%u,r%u,r%u\n",
3417             flag_OE ? "o" : "", flag_rC ? ".":"",
3418                                         rD_addr, rA_addr, rB_addr);
3419         if (mode64) {
3420            dividend = unop( Iop_64to32, mkexpr( rA ) );
3421            divisor = unop( Iop_64to32, mkexpr( rB ) );
3422            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
3423            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
3424         } else {
3425            dividend = mkexpr( rA );
3426            divisor =  mkexpr( rB );
3427            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
3428            assign( rD, mkexpr( res) );
3429         }
3430
3431         if (flag_OE) {
3432            set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
3433                           mkexpr(res), dividend, divisor );
3434         }
3435         break;
3436      }
3437
3438      case 0x1AB: // divwe (Divide Word Extended)
3439      {
3440         /*
3441          * If the quotient cannot be represented in 32 bits, or if an
3442          * attempt is made to perform the division
3443          *      <anything> / 0
3444          * then the contents of register RD are undefined as are (if
3445          * Rc=1) the contents of the LT, GT, and EQ bits of CR
3446          * Field 0. In these cases, if OE=1 then OV is set to 1.
3447          */
3448
3449         IRTemp res = newTemp(Ity_I32);
3450         IRExpr * dividend, * divisor;
3451         DIP("divwe%s%s r%u,r%u,r%u\n",
3452             flag_OE ? "o" : "", flag_rC ? ".":"",
3453                                         rD_addr, rA_addr, rB_addr);
3454         if (mode64) {
3455            dividend = unop( Iop_64to32, mkexpr( rA ) );
3456            divisor = unop( Iop_64to32, mkexpr( rB ) );
3457            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
3458            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
3459         } else {
3460            dividend = mkexpr( rA );
3461            divisor =  mkexpr( rB );
3462            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
3463            assign( rD, mkexpr( res) );
3464         }
3465
3466         if (flag_OE) {
3467            set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
3468                           mkexpr(res), dividend, divisor );
3469         }
3470         break;
3471      }
3472
3473
3474      case 0x1A9: // divde (Divide Doubleword Extended)
3475        /*
3476         * If the quotient cannot be represented in 64 bits, or if an
3477         * attempt is made to perform the division
3478         *      <anything> / 0
3479         * then the contents of register RD are undefined as are (if
3480         * Rc=1) the contents of the LT, GT, and EQ bits of CR
3481         * Field 0. In these cases, if OE=1 then OV is set to 1.
3482         */
3483         DIP("divde%s%s r%u,r%u,r%u\n",
3484             flag_OE ? "o" : "", flag_rC ? ".":"",
3485             rD_addr, rA_addr, rB_addr);
3486         assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
3487         if (flag_OE) {
3488            set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
3489                           mkexpr( rA ), mkexpr( rB ) );
3490         }
3491         break;
3492
3493      case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
3494        // Same CR and OV rules as given for divweu above
3495        DIP("divdeu%s%s r%u,r%u,r%u\n",
3496            flag_OE ? "o" : "", flag_rC ? ".":"",
3497            rD_addr, rA_addr, rB_addr);
3498        assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
3499        if (flag_OE) {
3500           set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
3501                          mkexpr( rA ), mkexpr( rB ) );
3502        }
3503        break;
3504
3505      default:
3506         vex_printf("dis_int_arith(ppc)(opc2)\n");
3507         return False;
3508      }
3509      break;
3510
3511   default:
3512      vex_printf("dis_int_arith(ppc)(opc1)\n");
3513      return False;
3514   }
3515
3516   putIReg( rD_addr, mkexpr(rD) );
3517
3518   if (do_rc && flag_rC) {
3519      set_CR0( mkexpr(rD) );
3520   }
3521   return True;
3522}
3523
3524
3525
3526/*
3527  Integer Compare Instructions
3528*/
3529static Bool dis_int_cmp ( UInt theInstr )
3530{
3531   /* D-Form, X-Form */
3532   UChar opc1    = ifieldOPC(theInstr);
3533   UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
3534   UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
3535   UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
3536   UChar rA_addr = ifieldRegA(theInstr);
3537   UInt  uimm16  = ifieldUIMM16(theInstr);
3538   UChar rB_addr = ifieldRegB(theInstr);
3539   UInt  opc2    = ifieldOPClo10(theInstr);
3540   UChar b0      = ifieldBIT0(theInstr);
3541
3542   IRType ty = mode64 ? Ity_I64 : Ity_I32;
3543   IRExpr *a = getIReg(rA_addr);
3544   IRExpr *b;
3545
3546   if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
3547      vex_printf("dis_int_cmp(ppc)(flag_L)\n");
3548      return False;
3549   }
3550
3551   if (b22 != 0) {
3552      vex_printf("dis_int_cmp(ppc)(b22)\n");
3553      return False;
3554   }
3555
3556   switch (opc1) {
3557   case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
3558      DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
3559          (Int)extend_s_16to32(uimm16));
3560      b = mkSzExtendS16( ty, uimm16 );
3561      if (flag_L == 1) {
3562         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
3563      } else {
3564         a = mkNarrowTo32( ty, a );
3565         b = mkNarrowTo32( ty, b );
3566         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
3567      }
3568      putCR0( crfD, getXER_SO() );
3569      break;
3570
3571   case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
3572      DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
3573      b = mkSzImm( ty, uimm16 );
3574      if (flag_L == 1) {
3575         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
3576      } else {
3577         a = mkNarrowTo32( ty, a );
3578         b = mkNarrowTo32( ty, b );
3579         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
3580      }
3581      putCR0( crfD, getXER_SO() );
3582      break;
3583
3584   /* X Form */
3585   case 0x1F:
3586      if (b0 != 0) {
3587         vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
3588         return False;
3589      }
3590      b = getIReg(rB_addr);
3591
3592      switch (opc2) {
3593      case 0x000: // cmp (Compare, PPC32 p367)
3594         DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
3595         /* Comparing a reg with itself produces a result which
3596            doesn't depend on the contents of the reg.  Therefore
3597            remove the false dependency, which has been known to cause
3598            memcheck to produce false errors. */
3599         if (rA_addr == rB_addr)
3600            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
3601                    ? mkU64(0)  : mkU32(0);
3602         if (flag_L == 1) {
3603            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
3604         } else {
3605            a = mkNarrowTo32( ty, a );
3606            b = mkNarrowTo32( ty, b );
3607            putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
3608         }
3609         putCR0( crfD, getXER_SO() );
3610         break;
3611
3612      case 0x020: // cmpl (Compare Logical, PPC32 p369)
3613         DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
3614         /* Comparing a reg with itself produces a result which
3615            doesn't depend on the contents of the reg.  Therefore
3616            remove the false dependency, which has been known to cause
3617            memcheck to produce false errors. */
3618         if (rA_addr == rB_addr)
3619            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
3620                    ? mkU64(0)  : mkU32(0);
3621         if (flag_L == 1) {
3622            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
3623         } else {
3624            a = mkNarrowTo32( ty, a );
3625            b = mkNarrowTo32( ty, b );
3626            putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
3627         }
3628         putCR0( crfD, getXER_SO() );
3629         break;
3630
3631      default:
3632         vex_printf("dis_int_cmp(ppc)(opc2)\n");
3633         return False;
3634      }
3635      break;
3636
3637   default:
3638      vex_printf("dis_int_cmp(ppc)(opc1)\n");
3639      return False;
3640   }
3641
3642   return True;
3643}
3644
3645
3646/*
3647  Integer Logical Instructions
3648*/
3649static Bool dis_int_logic ( UInt theInstr )
3650{
3651   /* D-Form, X-Form */
3652   UChar opc1    = ifieldOPC(theInstr);
3653   UChar rS_addr = ifieldRegDS(theInstr);
3654   UChar rA_addr = ifieldRegA(theInstr);
3655   UInt  uimm16  = ifieldUIMM16(theInstr);
3656   UChar rB_addr = ifieldRegB(theInstr);
3657   UInt  opc2    = ifieldOPClo10(theInstr);
3658   UChar flag_rC = ifieldBIT0(theInstr);
3659
3660   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3661   IRTemp rS     = newTemp(ty);
3662   IRTemp rA     = newTemp(ty);
3663   IRTemp rB     = newTemp(ty);
3664   IRExpr* irx;
3665   Bool do_rc    = False;
3666
3667   assign( rS, getIReg(rS_addr) );
3668   assign( rB, getIReg(rB_addr) );
3669
3670   switch (opc1) {
3671   case 0x1C: // andi. (AND Immediate, PPC32 p358)
3672      DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3673      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3674                         mkSzImm(ty, uimm16)) );
3675      do_rc = True;  // Always record to CR
3676      flag_rC = 1;
3677      break;
3678
3679   case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
3680      DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3681      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3682                         mkSzImm(ty, uimm16 << 16)) );
3683      do_rc = True;  // Always record to CR
3684      flag_rC = 1;
3685      break;
3686
3687   case 0x18: // ori (OR Immediate, PPC32 p497)
3688      DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3689      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3690                         mkSzImm(ty, uimm16)) );
3691      break;
3692
3693   case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
3694      DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3695      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3696                         mkSzImm(ty, uimm16 << 16)) );
3697      break;
3698
3699   case 0x1A: // xori (XOR Immediate, PPC32 p550)
3700      DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3701      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
3702                         mkSzImm(ty, uimm16)) );
3703      break;
3704
3705   case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
3706      DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3707      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
3708                         mkSzImm(ty, uimm16 << 16)) );
3709      break;
3710
3711   /* X Form */
3712   case 0x1F:
3713      do_rc = True; // All below record to CR, except for where we return at case end.
3714
3715      switch (opc2) {
3716      case 0x01C: // and (AND, PPC32 p356)
3717         DIP("and%s r%u,r%u,r%u\n",
3718             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3719         assign(rA, binop( mkSzOp(ty, Iop_And8),
3720                           mkexpr(rS), mkexpr(rB)));
3721         break;
3722
3723      case 0x03C: // andc (AND with Complement, PPC32 p357)
3724         DIP("andc%s r%u,r%u,r%u\n",
3725             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3726         assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3727                           unop( mkSzOp(ty, Iop_Not8),
3728                                 mkexpr(rB))));
3729         break;
3730
3731      case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
3732         IRExpr* lo32;
3733         if (rB_addr!=0) {
3734            vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
3735            return False;
3736         }
3737         DIP("cntlzw%s r%u,r%u\n",
3738             flag_rC ? ".":"", rA_addr, rS_addr);
3739
3740         // mode64: count in low word only
3741         lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
3742
3743         // Iop_Clz32 undefined for arg==0, so deal with that case:
3744         irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
3745         assign(rA, mkWidenFrom32(ty,
3746                         IRExpr_Mux0X( unop(Iop_1Uto8, irx),
3747                                       mkU32(32),
3748                                       unop(Iop_Clz32, lo32)),
3749                         False));
3750
3751         // TODO: alternatively: assign(rA, verbose_Clz32(rS));
3752         break;
3753      }
3754
3755      case 0x11C: // eqv (Equivalent, PPC32 p396)
3756         DIP("eqv%s r%u,r%u,r%u\n",
3757             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3758         assign( rA, unop( mkSzOp(ty, Iop_Not8),
3759                           binop( mkSzOp(ty, Iop_Xor8),
3760                                  mkexpr(rS), mkexpr(rB))) );
3761         break;
3762
3763      case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
3764         if (rB_addr!=0) {
3765            vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
3766            return False;
3767         }
3768         DIP("extsb%s r%u,r%u\n",
3769             flag_rC ? ".":"", rA_addr, rS_addr);
3770         if (mode64)
3771            assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
3772         else
3773            assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
3774         break;
3775
3776      case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
3777         if (rB_addr!=0) {
3778            vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
3779            return False;
3780         }
3781         DIP("extsh%s r%u,r%u\n",
3782             flag_rC ? ".":"", rA_addr, rS_addr);
3783         if (mode64)
3784            assign( rA, unop(Iop_16Sto64,
3785                             unop(Iop_64to16, mkexpr(rS))) );
3786         else
3787            assign( rA, unop(Iop_16Sto32,
3788                             unop(Iop_32to16, mkexpr(rS))) );
3789         break;
3790
3791      case 0x1DC: // nand (NAND, PPC32 p492)
3792         DIP("nand%s r%u,r%u,r%u\n",
3793             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3794         assign( rA, unop( mkSzOp(ty, Iop_Not8),
3795                           binop( mkSzOp(ty, Iop_And8),
3796                                  mkexpr(rS), mkexpr(rB))) );
3797         break;
3798
3799      case 0x07C: // nor (NOR, PPC32 p494)
3800         DIP("nor%s r%u,r%u,r%u\n",
3801             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3802         assign( rA, unop( mkSzOp(ty, Iop_Not8),
3803                           binop( mkSzOp(ty, Iop_Or8),
3804                                  mkexpr(rS), mkexpr(rB))) );
3805         break;
3806
3807      case 0x1BC: // or (OR, PPC32 p495)
3808         if ((!flag_rC) && rS_addr == rB_addr) {
3809            DIP("mr r%u,r%u\n", rA_addr, rS_addr);
3810            assign( rA, mkexpr(rS) );
3811         } else {
3812            DIP("or%s r%u,r%u,r%u\n",
3813                flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3814            assign( rA, binop( mkSzOp(ty, Iop_Or8),
3815                               mkexpr(rS), mkexpr(rB)) );
3816         }
3817         break;
3818
3819      case 0x19C: // orc  (OR with Complement, PPC32 p496)
3820         DIP("orc%s r%u,r%u,r%u\n",
3821             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3822         assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3823                            unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
3824         break;
3825
3826      case 0x13C: // xor (XOR, PPC32 p549)
3827         DIP("xor%s r%u,r%u,r%u\n",
3828             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3829         assign( rA, binop( mkSzOp(ty, Iop_Xor8),
3830                            mkexpr(rS), mkexpr(rB)) );
3831         break;
3832
3833
3834      /* 64bit Integer Logical Instructions */
3835      case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
3836         if (rB_addr!=0) {
3837            vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
3838            return False;
3839         }
3840         DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
3841         assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
3842         break;
3843
3844      case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
3845         if (rB_addr!=0) {
3846            vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
3847            return False;
3848         }
3849         DIP("cntlzd%s r%u,r%u\n",
3850             flag_rC ? ".":"", rA_addr, rS_addr);
3851         // Iop_Clz64 undefined for arg==0, so deal with that case:
3852         irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
3853         assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx),
3854                                  mkU64(64),
3855                                  unop(Iop_Clz64, mkexpr(rS)) ));
3856         // TODO: alternatively: assign(rA, verbose_Clz64(rS));
3857         break;
3858
3859      case 0x1FC: // cmpb (Power6: compare bytes)
3860         DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
3861
3862         if (mode64)
3863            assign( rA, unop( Iop_V128to64,
3864                              binop( Iop_CmpEQ8x16,
3865                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
3866                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
3867                                     )) );
3868         else
3869            assign( rA, unop( Iop_V128to32,
3870                              binop( Iop_CmpEQ8x16,
3871                                     unop( Iop_32UtoV128, mkexpr(rS) ),
3872                                     unop( Iop_32UtoV128, mkexpr(rB) )
3873                                     )) );
3874         break;
3875
3876      case 0x2DF: { // mftgpr (move floating-point to general purpose register)
3877         IRTemp frB = newTemp(Ity_F64);
3878         DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
3879
3880         assign( frB, getFReg(rB_addr));  // always F64
3881         if (mode64)
3882            assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
3883         else
3884            assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
3885
3886         putIReg( rS_addr, mkexpr(rA));
3887         return True;
3888      }
3889
3890      case 0x25F: { // mffgpr (move floating-point from general purpose register)
3891         IRTemp frA = newTemp(Ity_F64);
3892         DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
3893
3894         if (mode64)
3895            assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
3896         else
3897            assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
3898
3899         putFReg( rS_addr, mkexpr(frA));
3900         return True;
3901      }
3902      case 0x1FA: // popcntd (population count doubleword
3903      {
3904    	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
3905        IRTemp result = gen_POPCOUNT(ty, rS);
3906    	  putIReg( rA_addr, mkexpr(result) );
3907    	  return True;
3908      }
3909      case 0x17A: // popcntw (Population Count Words)
3910      {
3911         DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
3912         if (mode64) {
3913            IRTemp resultHi, resultLo;
3914            IRTemp argLo = newTemp(Ity_I32);
3915            IRTemp argHi = newTemp(Ity_I32);
3916            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
3917            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
3918            resultLo = gen_POPCOUNT(Ity_I32, argLo);
3919            resultHi = gen_POPCOUNT(Ity_I32, argHi);
3920            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
3921         } else {
3922            IRTemp result = gen_POPCOUNT(ty, rS);
3923            putIReg( rA_addr, mkexpr(result) );
3924         }
3925         return True;
3926      }
3927       case 0x0FC: // bpermd (Bit Permute Doubleword)
3928       {
3929          /* This is a lot of rigmarole to emulate bpermd like this, as it
3930           * could be done much faster by implementing a call to the native
3931           * instruction.  However, where possible I want to avoid using new
3932           * native instructions so that we can use valgrind to emulate those
3933           * instructions on older PPC64 hardware.
3934           */
3935 #define BPERMD_IDX_MASK 0x00000000000000FFULL
3936 #define BPERMD_BIT_MASK 0x8000000000000000ULL
3937          int i;
3938          IRExpr * rS_expr = mkexpr(rS);
3939          IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
3940          DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
3941          for (i = 0; i < 8; i++) {
3942             IRTemp idx_tmp = newTemp( Ity_I64 );
3943             IRTemp perm_bit = newTemp( Ity_I64 );
3944             IRTemp idx = newTemp( Ity_I8 );
3945             IRTemp idx_LT64 = newTemp( Ity_I1 );
3946             IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
3947
3948             assign( idx_tmp,
3949                     binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
3950             assign( idx_LT64,
3951                           binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
3952             assign( idx,
3953                           binop( Iop_And8,
3954                                  unop( Iop_1Sto8,
3955                                        mkexpr(idx_LT64) ),
3956                                  unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
3957             /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
3958              * to determine which bit of rB to use for the perm bit, and then we shift
3959              * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
3960              * to set the final perm bit.
3961              */
3962             assign( idx_LT64_ity64,
3963                           unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
3964             assign( perm_bit,
3965                           binop( Iop_And64,
3966                                  mkexpr( idx_LT64_ity64 ),
3967                                  binop( Iop_Shr64,
3968                                         binop( Iop_And64,
3969                                                mkU64( BPERMD_BIT_MASK ),
3970                                                binop( Iop_Shl64,
3971                                                       mkexpr( rB ),
3972                                                       mkexpr( idx ) ) ),
3973                                         mkU8( 63 ) ) ) );
3974             res = binop( Iop_Or64,
3975                                res,
3976                                binop( Iop_Shl64,
3977                                       mkexpr( perm_bit ),
3978                                       mkU8( i ) ) );
3979             rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
3980          }
3981          putIReg(rA_addr, res);
3982          return True;
3983       }
3984
3985      default:
3986         vex_printf("dis_int_logic(ppc)(opc2)\n");
3987         return False;
3988      }
3989      break;
3990
3991   default:
3992      vex_printf("dis_int_logic(ppc)(opc1)\n");
3993      return False;
3994   }
3995
3996   putIReg( rA_addr, mkexpr(rA) );
3997
3998   if (do_rc && flag_rC) {
3999      set_CR0( mkexpr(rA) );
4000   }
4001   return True;
4002}
4003
4004/*
4005  Integer Parity Instructions
4006*/
4007static Bool dis_int_parity ( UInt theInstr )
4008{
4009   /* X-Form */
4010   UChar opc1    = ifieldOPC(theInstr);
4011   UChar rS_addr = ifieldRegDS(theInstr);
4012   UChar rA_addr = ifieldRegA(theInstr);
4013   UChar rB_addr = ifieldRegB(theInstr);
4014   UInt  opc2    = ifieldOPClo10(theInstr);
4015   UChar b0      = ifieldBIT0(theInstr);
4016   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4017
4018   IRTemp rS     = newTemp(ty);
4019   IRTemp rA     = newTemp(ty);
4020   IRTemp iTot1  = newTemp(Ity_I32);
4021   IRTemp iTot2  = newTemp(Ity_I32);
4022   IRTemp iTot3  = newTemp(Ity_I32);
4023   IRTemp iTot4  = newTemp(Ity_I32);
4024   IRTemp iTot5  = newTemp(Ity_I32);
4025   IRTemp iTot6  = newTemp(Ity_I32);
4026   IRTemp iTot7  = newTemp(Ity_I32);
4027   IRTemp iTot8  = newTemp(Ity_I32);
4028   IRTemp rS1    = newTemp(ty);
4029   IRTemp rS2    = newTemp(ty);
4030   IRTemp rS3    = newTemp(ty);
4031   IRTemp rS4    = newTemp(ty);
4032   IRTemp rS5    = newTemp(ty);
4033   IRTemp rS6    = newTemp(ty);
4034   IRTemp rS7    = newTemp(ty);
4035   IRTemp iHi    = newTemp(Ity_I32);
4036   IRTemp iLo    = newTemp(Ity_I32);
4037   IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
4038   IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
4039
4040   if (opc1 != 0x1f || rB_addr || b0) {
4041      vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
4042      return False;
4043   }
4044
4045   assign( rS, getIReg(rS_addr) );
4046
4047   switch (opc2) {
4048   case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
4049      DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
4050      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4051      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4052      assign( iTot2, binop(Iop_Add32,
4053                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4054                           mkexpr(iTot1)) );
4055      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4056      assign( iTot3, binop(Iop_Add32,
4057                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4058                           mkexpr(iTot2)) );
4059      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4060      assign( iTot4, binop(Iop_Add32,
4061                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4062                           mkexpr(iTot3)) );
4063      if (mode64) {
4064         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4065         assign( iTot5, binop(Iop_Add32,
4066                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
4067                              mkexpr(iTot4)) );
4068         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4069         assign( iTot6, binop(Iop_Add32,
4070                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4071                              mkexpr(iTot5)) );
4072         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4073         assign( iTot7, binop(Iop_Add32,
4074                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4075                              mkexpr(iTot6)) );
4076         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
4077         assign( iTot8, binop(Iop_Add32,
4078                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4079                              mkexpr(iTot7)) );
4080         assign( rA, unop(Iop_32Uto64,
4081                          binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
4082      } else
4083         assign( rA, mkexpr(iTot4) );
4084
4085      break;
4086   case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
4087      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4088      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4089      assign( iTot2, binop(Iop_Add32,
4090                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4091                           mkexpr(iTot1)) );
4092      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4093      assign( iTot3, binop(Iop_Add32,
4094                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4095                           mkexpr(iTot2)) );
4096      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4097      assign( iTot4, binop(Iop_Add32,
4098                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4099                           mkexpr(iTot3)) );
4100      assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
4101
4102      if (mode64) {
4103         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4104         assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
4105         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4106         assign( iTot6, binop(Iop_Add32,
4107                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4108                              mkexpr(iTot5)) );
4109         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4110         assign( iTot7, binop(Iop_Add32,
4111                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4112                              mkexpr(iTot6)) );
4113         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
4114         assign( iTot8, binop(Iop_Add32,
4115                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4116                              mkexpr(iTot7)) );
4117         assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
4118            assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
4119      } else
4120         assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
4121      break;
4122   default:
4123      vex_printf("dis_int_parity(ppc)(opc2)\n");
4124      return False;
4125   }
4126
4127   putIReg( rA_addr, mkexpr(rA) );
4128
4129   return True;
4130}
4131
4132
4133/*
4134  Integer Rotate Instructions
4135*/
4136static Bool dis_int_rot ( UInt theInstr )
4137{
4138   /* M-Form, MDS-Form */
4139   UChar opc1    = ifieldOPC(theInstr);
4140   UChar rS_addr = ifieldRegDS(theInstr);
4141   UChar rA_addr = ifieldRegA(theInstr);
4142   UChar rB_addr = ifieldRegB(theInstr);
4143   UChar sh_imm  = rB_addr;
4144   UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
4145   UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
4146   UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
4147   UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
4148   UChar b1      = ifieldBIT1(theInstr);
4149   UChar flag_rC = ifieldBIT0(theInstr);
4150
4151   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4152   IRTemp rS     = newTemp(ty);
4153   IRTemp rA     = newTemp(ty);
4154   IRTemp rB     = newTemp(ty);
4155   IRTemp rot    = newTemp(ty);
4156   IRExpr *r;
4157   UInt   mask32;
4158   ULong  mask64;
4159
4160   assign( rS, getIReg(rS_addr) );
4161   assign( rB, getIReg(rB_addr) );
4162
4163   switch (opc1) {
4164   case 0x14: {
4165      // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
4166      DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4167          rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4168      if (mode64) {
4169         // tmp32 = (ROTL(rS_Lo32, Imm)
4170         // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
4171         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4172         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4173         r = unop(Iop_32Uto64, r);
4174         assign( rot, binop(Iop_Or64, r,
4175                            binop(Iop_Shl64, r, mkU8(32))) );
4176         assign( rA,
4177            binop(Iop_Or64,
4178                  binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
4179                  binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
4180      }
4181      else {
4182         // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
4183         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4184         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4185         assign( rA,
4186            binop(Iop_Or32,
4187                  binop(Iop_And32, mkU32(mask32), r),
4188                  binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
4189      }
4190      break;
4191   }
4192
4193   case 0x15: {
4194      // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
4195      vassert(MaskBeg < 32);
4196      vassert(MaskEnd < 32);
4197      vassert(sh_imm  < 32);
4198
4199      if (mode64) {
4200         IRTemp rTmp = newTemp(Ity_I64);
4201         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4202         DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4203             rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4204         // tmp32 = (ROTL(rS_Lo32, Imm)
4205         // rA = ((tmp32 || tmp32) & mask64)
4206         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4207         r = unop(Iop_32Uto64, r);
4208         assign( rTmp, r );
4209         r = NULL;
4210         assign( rot, binop(Iop_Or64, mkexpr(rTmp),
4211                            binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
4212         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4213      }
4214      else {
4215         if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
4216            /* Special-case the ,n,0,31-n form as that is just n-bit
4217               shift left, PPC32 p501 */
4218            DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4219                rA_addr, rS_addr, sh_imm);
4220            assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
4221         }
4222         else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
4223            /* Special-case the ,32-n,n,31 form as that is just n-bit
4224               unsigned shift right, PPC32 p501 */
4225            DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4226                rA_addr, rS_addr, MaskBeg);
4227            assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
4228         }
4229         else {
4230            /* General case. */
4231            mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4232            DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4233                rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4234            // rA = ROTL(rS, Imm) & mask
4235            assign( rA, binop(Iop_And32,
4236                              ROTL(mkexpr(rS), mkU8(sh_imm)),
4237                              mkU32(mask32)) );
4238         }
4239      }
4240      break;
4241   }
4242
4243   case 0x17: {
4244      // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
4245      DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
4246          rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
4247      if (mode64) {
4248         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4249         /* weird insn alert!
4250            tmp32 = (ROTL(rS_Lo32, rB[0-4])
4251            rA = ((tmp32 || tmp32) & mask64)
4252         */
4253         // note, ROTL does the masking, so we don't do it here
4254         r = ROTL( unop(Iop_64to32, mkexpr(rS)),
4255                   unop(Iop_64to8, mkexpr(rB)) );
4256         r = unop(Iop_32Uto64, r);
4257         assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
4258         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4259      } else {
4260         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4261         // rA = ROTL(rS, rB[0-4]) & mask
4262         // note, ROTL does the masking, so we don't do it here
4263         assign( rA, binop(Iop_And32,
4264                           ROTL(mkexpr(rS),
4265                                unop(Iop_32to8, mkexpr(rB))),
4266                           mkU32(mask32)) );
4267      }
4268      break;
4269   }
4270
4271   /* 64bit Integer Rotates */
4272   case 0x1E: {
4273      msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
4274      sh_imm |= b1 << 5;
4275
4276      vassert( msk_imm < 64 );
4277      vassert( sh_imm < 64 );
4278
4279      switch (opc2) {
4280      case 0x4: {
4281         /* r = ROTL64( rS, rB_lo6) */
4282         r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
4283
4284         if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
4285            DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4286                rA_addr, rS_addr, rB_addr, msk_imm);
4287            // note, ROTL does the masking, so we don't do it here
4288            mask64 = MASK64(0, 63-msk_imm);
4289            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4290            break;
4291         } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
4292            DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4293                rA_addr, rS_addr, rB_addr, msk_imm);
4294            mask64 = MASK64(63-msk_imm, 63);
4295            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4296            break;
4297         }
4298         break;
4299      }
4300      case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
4301         DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4302             rA_addr, rS_addr, sh_imm, msk_imm);
4303         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4304         mask64 = MASK64(sh_imm, 63-msk_imm);
4305         assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4306         break;
4307         // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
4308         /*
4309           Hmm... looks like this'll do the job more simply:
4310           r = SHL(rS, sh_imm)
4311           m = ~(1 << (63-msk_imm))
4312           assign(rA, r & m);
4313         */
4314
4315      case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
4316         if (mode64
4317             && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
4318            /* special-case the ,64-n,n form as that is just
4319               unsigned shift-right by n */
4320            DIP("srdi%s r%u,r%u,%u\n",
4321                flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
4322            assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
4323         } else {
4324            DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4325                rA_addr, rS_addr, sh_imm, msk_imm);
4326            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4327            mask64 = MASK64(0, 63-msk_imm);
4328            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4329         }
4330         break;
4331
4332      case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
4333         if (mode64
4334             && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
4335            /* special-case the ,n,63-n form as that is just
4336               shift-left by n */
4337            DIP("sldi%s r%u,r%u,%u\n",
4338                flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
4339            assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
4340         } else {
4341            DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4342                rA_addr, rS_addr, sh_imm, msk_imm);
4343            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4344            mask64 = MASK64(63-msk_imm, 63);
4345            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4346         }
4347         break;
4348
4349      case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
4350         IRTemp rA_orig = newTemp(ty);
4351         DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4352             rA_addr, rS_addr, sh_imm, msk_imm);
4353         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4354         mask64 = MASK64(sh_imm, 63-msk_imm);
4355         assign( rA_orig, getIReg(rA_addr) );
4356         assign( rA, binop(Iop_Or64,
4357                           binop(Iop_And64, mkU64(mask64),  r),
4358                           binop(Iop_And64, mkU64(~mask64),
4359                                            mkexpr(rA_orig))) );
4360         break;
4361      }
4362      default:
4363         vex_printf("dis_int_rot(ppc)(opc2)\n");
4364         return False;
4365      }
4366      break;
4367   }
4368
4369   default:
4370      vex_printf("dis_int_rot(ppc)(opc1)\n");
4371      return False;
4372   }
4373
4374   putIReg( rA_addr, mkexpr(rA) );
4375
4376   if (flag_rC) {
4377      set_CR0( mkexpr(rA) );
4378   }
4379   return True;
4380}
4381
4382
4383/*
4384  Integer Load Instructions
4385*/
4386static Bool dis_int_load ( UInt theInstr )
4387{
4388   /* D-Form, X-Form, DS-Form */
4389   UChar opc1     = ifieldOPC(theInstr);
4390   UChar rD_addr  = ifieldRegDS(theInstr);
4391   UChar rA_addr  = ifieldRegA(theInstr);
4392   UInt  uimm16   = ifieldUIMM16(theInstr);
4393   UChar rB_addr  = ifieldRegB(theInstr);
4394   UInt  opc2     = ifieldOPClo10(theInstr);
4395   UChar b1       = ifieldBIT1(theInstr);
4396   UChar b0       = ifieldBIT0(theInstr);
4397
4398   Int     simm16 = extend_s_16to32(uimm16);
4399   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
4400   IRTemp  EA     = newTemp(ty);
4401   IRExpr* val;
4402
4403   switch (opc1) {
4404   case 0x1F: // register offset
4405      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
4406      break;
4407   case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
4408              // lowest 2 bits of immediate before forming EA
4409      simm16 = simm16 & 0xFFFFFFFC;
4410   default:   // immediate offset
4411      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
4412      break;
4413   }
4414
4415   switch (opc1) {
4416   case 0x22: // lbz (Load B & Zero, PPC32 p433)
4417      DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4418      val = loadBE(Ity_I8, mkexpr(EA));
4419      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4420      break;
4421
4422   case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
4423      if (rA_addr == 0 || rA_addr == rD_addr) {
4424         vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
4425         return False;
4426      }
4427      DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4428      val = loadBE(Ity_I8, mkexpr(EA));
4429      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4430      putIReg( rA_addr, mkexpr(EA) );
4431      break;
4432
4433   case 0x2A: // lha (Load HW Alg, PPC32 p445)
4434      DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4435      val = loadBE(Ity_I16, mkexpr(EA));
4436      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4437      break;
4438
4439   case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
4440      if (rA_addr == 0 || rA_addr == rD_addr) {
4441         vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
4442         return False;
4443      }
4444      DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4445      val = loadBE(Ity_I16, mkexpr(EA));
4446      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4447      putIReg( rA_addr, mkexpr(EA) );
4448      break;
4449
4450   case 0x28: // lhz (Load HW & Zero, PPC32 p450)
4451      DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4452      val = loadBE(Ity_I16, mkexpr(EA));
4453      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4454      break;
4455
4456   case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
4457      if (rA_addr == 0 || rA_addr == rD_addr) {
4458         vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
4459         return False;
4460      }
4461      DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4462      val = loadBE(Ity_I16, mkexpr(EA));
4463      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4464      putIReg( rA_addr, mkexpr(EA) );
4465      break;
4466
4467   case 0x20: // lwz (Load W & Zero, PPC32 p460)
4468      DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4469      val = loadBE(Ity_I32, mkexpr(EA));
4470      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4471      break;
4472
4473   case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
4474      if (rA_addr == 0 || rA_addr == rD_addr) {
4475         vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
4476         return False;
4477      }
4478      DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4479      val = loadBE(Ity_I32, mkexpr(EA));
4480      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4481      putIReg( rA_addr, mkexpr(EA) );
4482      break;
4483
4484   /* X Form */
4485   case 0x1F:
4486      if (b0 != 0) {
4487         vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
4488         return False;
4489      }
4490
4491      switch (opc2) {
4492      case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
4493         DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4494         if (rA_addr == 0 || rA_addr == rD_addr) {
4495            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
4496            return False;
4497         }
4498         val = loadBE(Ity_I8, mkexpr(EA));
4499         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4500         putIReg( rA_addr, mkexpr(EA) );
4501         break;
4502
4503      case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
4504         DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4505         val = loadBE(Ity_I8, mkexpr(EA));
4506         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4507         break;
4508
4509      case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
4510         if (rA_addr == 0 || rA_addr == rD_addr) {
4511            vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
4512            return False;
4513         }
4514         DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4515         val = loadBE(Ity_I16, mkexpr(EA));
4516         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4517         putIReg( rA_addr, mkexpr(EA) );
4518         break;
4519
4520      case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
4521         DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4522         val = loadBE(Ity_I16, mkexpr(EA));
4523         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4524         break;
4525
4526      case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
4527         if (rA_addr == 0 || rA_addr == rD_addr) {
4528            vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
4529            return False;
4530         }
4531         DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4532         val = loadBE(Ity_I16, mkexpr(EA));
4533         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4534         putIReg( rA_addr, mkexpr(EA) );
4535         break;
4536
4537      case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
4538         DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4539         val = loadBE(Ity_I16, mkexpr(EA));
4540         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4541         break;
4542
4543      case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
4544         if (rA_addr == 0 || rA_addr == rD_addr) {
4545            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
4546            return False;
4547         }
4548         DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4549         val = loadBE(Ity_I32, mkexpr(EA));
4550         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4551         putIReg( rA_addr, mkexpr(EA) );
4552         break;
4553
4554      case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
4555         DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4556         val = loadBE(Ity_I32, mkexpr(EA));
4557         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4558         break;
4559
4560
4561      /* 64bit Loads */
4562      case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
4563         if (rA_addr == 0 || rA_addr == rD_addr) {
4564            vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
4565            return False;
4566         }
4567         DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4568         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4569         putIReg( rA_addr, mkexpr(EA) );
4570         break;
4571
4572      case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
4573         DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4574         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4575         break;
4576
4577      case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
4578         if (rA_addr == 0 || rA_addr == rD_addr) {
4579            vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
4580            return False;
4581         }
4582         DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4583         putIReg( rD_addr,
4584                  unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4585         putIReg( rA_addr, mkexpr(EA) );
4586         break;
4587
4588      case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
4589         DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4590         putIReg( rD_addr,
4591                  unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4592         break;
4593
4594      default:
4595         vex_printf("dis_int_load(ppc)(opc2)\n");
4596         return False;
4597      }
4598      break;
4599
4600   /* DS Form - 64bit Loads.  In each case EA will have been formed
4601      with the lowest 2 bits masked off the immediate offset. */
4602   case 0x3A:
4603      switch ((b1<<1) | b0) {
4604      case 0x0: // ld (Load DWord, PPC64 p472)
4605         DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4606         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4607         break;
4608
4609      case 0x1: // ldu (Load DWord, Update, PPC64 p474)
4610         if (rA_addr == 0 || rA_addr == rD_addr) {
4611            vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
4612            return False;
4613         }
4614         DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4615         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4616         putIReg( rA_addr, mkexpr(EA) );
4617         break;
4618
4619      case 0x2: // lwa (Load Word Alg, PPC64 p499)
4620         DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4621         putIReg( rD_addr,
4622                  unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4623         break;
4624
4625      default:
4626         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
4627         return False;
4628      }
4629      break;
4630
4631   default:
4632      vex_printf("dis_int_load(ppc)(opc1)\n");
4633      return False;
4634   }
4635   return True;
4636}
4637
4638
4639
4640/*
4641  Integer Store Instructions
4642*/
4643static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi )
4644{
4645   /* D-Form, X-Form, DS-Form */
4646   UChar opc1    = ifieldOPC(theInstr);
4647   UInt  rS_addr = ifieldRegDS(theInstr);
4648   UInt  rA_addr = ifieldRegA(theInstr);
4649   UInt  uimm16  = ifieldUIMM16(theInstr);
4650   UInt  rB_addr = ifieldRegB(theInstr);
4651   UInt  opc2    = ifieldOPClo10(theInstr);
4652   UChar b1      = ifieldBIT1(theInstr);
4653   UChar b0      = ifieldBIT0(theInstr);
4654
4655   Int    simm16 = extend_s_16to32(uimm16);
4656   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4657   IRTemp rS     = newTemp(ty);
4658   IRTemp rB     = newTemp(ty);
4659   IRTemp EA     = newTemp(ty);
4660
4661   assign( rB, getIReg(rB_addr) );
4662   assign( rS, getIReg(rS_addr) );
4663
4664   switch (opc1) {
4665   case 0x1F: // register offset
4666      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
4667      break;
4668   case 0x3E: // immediate offset: 64bit: std/stdu: mask off
4669              // lowest 2 bits of immediate before forming EA
4670      simm16 = simm16 & 0xFFFFFFFC;
4671   default:   // immediate offset
4672      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
4673      break;
4674   }
4675
4676   switch (opc1) {
4677   case 0x26: // stb (Store B, PPC32 p509)
4678      DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4679      storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4680      break;
4681
4682   case 0x27: // stbu (Store B, Update, PPC32 p510)
4683      if (rA_addr == 0 ) {
4684         vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
4685         return False;
4686      }
4687      DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4688      putIReg( rA_addr, mkexpr(EA) );
4689      storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4690      break;
4691
4692   case 0x2C: // sth (Store HW, PPC32 p522)
4693      DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4694      storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4695      break;
4696
4697   case 0x2D: // sthu (Store HW, Update, PPC32 p524)
4698      if (rA_addr == 0) {
4699         vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
4700         return False;
4701      }
4702      DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4703      putIReg( rA_addr, mkexpr(EA) );
4704      storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4705      break;
4706
4707   case 0x24: // stw (Store W, PPC32 p530)
4708      DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4709      storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4710      break;
4711
4712   case 0x25: // stwu (Store W, Update, PPC32 p534)
4713      if (rA_addr == 0) {
4714         vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
4715         return False;
4716      }
4717      DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4718      putIReg( rA_addr, mkexpr(EA) );
4719      storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4720      break;
4721
4722   /* X Form : all these use EA_indexed */
4723   case 0x1F:
4724      if (b0 != 0) {
4725         vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
4726         return False;
4727      }
4728
4729      switch (opc2) {
4730      case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
4731         if (rA_addr == 0) {
4732            vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
4733            return False;
4734         }
4735         DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4736         putIReg( rA_addr, mkexpr(EA) );
4737         storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4738         break;
4739
4740      case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
4741         DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4742         storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4743         break;
4744
4745      case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
4746         if (rA_addr == 0) {
4747            vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
4748            return False;
4749         }
4750         DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4751         putIReg( rA_addr, mkexpr(EA) );
4752         storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4753         break;
4754
4755      case 0x197: // sthx (Store HW Indexed, PPC32 p526)
4756         DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4757         storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4758         break;
4759
4760      case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
4761         if (rA_addr == 0) {
4762            vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
4763            return False;
4764         }
4765         DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4766         putIReg( rA_addr, mkexpr(EA) );
4767         storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4768         break;
4769
4770      case 0x097: // stwx (Store W Indexed, PPC32 p536)
4771         DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4772         storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4773         break;
4774
4775
4776      /* 64bit Stores */
4777      case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
4778         if (rA_addr == 0) {
4779            vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
4780            return False;
4781         }
4782         DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4783         putIReg( rA_addr, mkexpr(EA) );
4784         storeBE( mkexpr(EA), mkexpr(rS) );
4785         break;
4786
4787      case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
4788         DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4789         storeBE( mkexpr(EA), mkexpr(rS) );
4790         break;
4791
4792      default:
4793         vex_printf("dis_int_store(ppc)(opc2)\n");
4794         return False;
4795      }
4796      break;
4797
4798   /* DS Form - 64bit Stores.  In each case EA will have been formed
4799      with the lowest 2 bits masked off the immediate offset. */
4800   case 0x3E:
4801      switch ((b1<<1) | b0) {
4802      case 0x0: // std (Store DWord, PPC64 p580)
4803         DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4804         storeBE( mkexpr(EA), mkexpr(rS) );
4805         break;
4806
4807      case 0x1: // stdu (Store DWord, Update, PPC64 p583)
4808         DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4809         putIReg( rA_addr, mkexpr(EA) );
4810         storeBE( mkexpr(EA), mkexpr(rS) );
4811         break;
4812
4813      default:
4814         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
4815         return False;
4816      }
4817      break;
4818
4819   default:
4820      vex_printf("dis_int_store(ppc)(opc1)\n");
4821      return False;
4822   }
4823   return True;
4824}
4825
4826
4827
4828/*
4829  Integer Load/Store Multiple Instructions
4830*/
4831static Bool dis_int_ldst_mult ( UInt theInstr )
4832{
4833   /* D-Form */
4834   UChar opc1     = ifieldOPC(theInstr);
4835   UChar rD_addr  = ifieldRegDS(theInstr);
4836   UChar rS_addr  = rD_addr;
4837   UChar rA_addr  = ifieldRegA(theInstr);
4838   UInt  uimm16   = ifieldUIMM16(theInstr);
4839
4840   Int     simm16 = extend_s_16to32(uimm16);
4841   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
4842   IRTemp  EA     = newTemp(ty);
4843   UInt    r      = 0;
4844   UInt    ea_off = 0;
4845   IRExpr* irx_addr;
4846
4847   assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
4848
4849   switch (opc1) {
4850   case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
4851      if (rA_addr >= rD_addr) {
4852         vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
4853         return False;
4854      }
4855      DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4856      for (r = rD_addr; r <= 31; r++) {
4857         irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
4858         putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ),
4859                                       False) );
4860         ea_off += 4;
4861      }
4862      break;
4863
4864   case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
4865      DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4866      for (r = rS_addr; r <= 31; r++) {
4867         irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
4868         storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
4869         ea_off += 4;
4870      }
4871      break;
4872
4873   default:
4874      vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
4875      return False;
4876   }
4877   return True;
4878}
4879
4880
4881
4882/*
4883  Integer Load/Store String Instructions
4884*/
4885static
4886void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
4887                             IRTemp EA,        // EA
4888                             Int    rD,        // first dst register
4889                             Int    maxBytes ) // 32 or 128
4890{
4891   Int     i, shift = 24;
4892   IRExpr* e_nbytes = mkexpr(tNBytes);
4893   IRExpr* e_EA     = mkexpr(EA);
4894   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
4895
4896   vassert(rD >= 0 && rD < 32);
4897   rD--; if (rD < 0) rD = 31;
4898
4899   for (i = 0; i < maxBytes; i++) {
4900      /* if (nBytes < (i+1)) goto NIA; */
4901      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
4902                         Ijk_Boring,
4903                         mkSzConst( ty, nextInsnAddr()) ));
4904      /* when crossing into a new dest register, set it to zero. */
4905      if ((i % 4) == 0) {
4906         rD++; if (rD == 32) rD = 0;
4907         putIReg(rD, mkSzImm(ty, 0));
4908         shift = 24;
4909      }
4910      /* rD |=  (8Uto32(*(EA+i))) << shift */
4911      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
4912      putIReg(
4913         rD,
4914         mkWidenFrom32(
4915            ty,
4916            binop(
4917               Iop_Or32,
4918               mkNarrowTo32(ty, getIReg(rD)),
4919               binop(
4920                  Iop_Shl32,
4921                  unop(
4922                     Iop_8Uto32,
4923                     loadBE(Ity_I8,
4924                            binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)))
4925                  ),
4926                  mkU8(toUChar(shift))
4927               )
4928            ),
4929            /*Signed*/False
4930	 )
4931      );
4932      shift -= 8;
4933   }
4934}
4935
4936static
4937void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
4938                              IRTemp EA,        // EA
4939                              Int    rS,        // first src register
4940                              Int    maxBytes ) // 32 or 128
4941{
4942   Int     i, shift = 24;
4943   IRExpr* e_nbytes = mkexpr(tNBytes);
4944   IRExpr* e_EA     = mkexpr(EA);
4945   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
4946
4947   vassert(rS >= 0 && rS < 32);
4948   rS--; if (rS < 0) rS = 31;
4949
4950   for (i = 0; i < maxBytes; i++) {
4951      /* if (nBytes < (i+1)) goto NIA; */
4952      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
4953                         Ijk_Boring,
4954                         mkSzConst( ty, nextInsnAddr() ) ));
4955      /* check for crossing into a new src register. */
4956      if ((i % 4) == 0) {
4957         rS++; if (rS == 32) rS = 0;
4958         shift = 24;
4959      }
4960      /* *(EA+i) = 32to8(rS >> shift) */
4961      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
4962      storeBE(
4963         binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
4964         unop(Iop_32to8,
4965              binop(Iop_Shr32,
4966                    mkNarrowTo32(ty, getIReg(rS)),
4967                    mkU8(toUChar(shift))))
4968      );
4969      shift -= 8;
4970   }
4971}
4972
4973static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
4974{
4975   /* X-Form */
4976   UChar opc1     = ifieldOPC(theInstr);
4977   UChar rD_addr  = ifieldRegDS(theInstr);
4978   UChar rS_addr  = rD_addr;
4979   UChar rA_addr  = ifieldRegA(theInstr);
4980   UChar rB_addr  = ifieldRegB(theInstr);
4981   UChar NumBytes = rB_addr;
4982   UInt  opc2     = ifieldOPClo10(theInstr);
4983   UChar b0       = ifieldBIT0(theInstr);
4984
4985   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
4986   IRTemp t_EA    = newTemp(ty);
4987   IRTemp t_nbytes = IRTemp_INVALID;
4988
4989   *stopHere = False;
4990
4991   if (opc1 != 0x1F || b0 != 0) {
4992      vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
4993      return False;
4994   }
4995
4996   switch (opc2) {
4997   case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
4998      /* NB: does not reject the case where RA is in the range of
4999         registers to be loaded.  It should. */
5000      DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
5001      assign( t_EA, ea_rAor0(rA_addr) );
5002      if (NumBytes == 8 && !mode64) {
5003         /* Special case hack */
5004         /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
5005         putIReg( rD_addr,
5006                  loadBE(Ity_I32, mkexpr(t_EA)) );
5007         putIReg( (rD_addr+1) % 32,
5008                  loadBE(Ity_I32,
5009                         binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
5010      } else {
5011         t_nbytes = newTemp(Ity_I32);
5012         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5013         generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5014         *stopHere = True;
5015      }
5016      return True;
5017
5018   case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
5019      /* NB: does not reject the case where RA is in the range of
5020         registers to be loaded.  It should.  Although considering
5021         that that can only be detected at run time, it's not easy to
5022         do so. */
5023      if (rD_addr == rA_addr || rD_addr == rB_addr)
5024         return False;
5025      if (rD_addr == 0 && rA_addr == 0)
5026         return False;
5027      DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5028      t_nbytes = newTemp(Ity_I32);
5029      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5030      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5031      generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
5032      *stopHere = True;
5033      return True;
5034
5035   case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
5036      DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
5037      assign( t_EA, ea_rAor0(rA_addr) );
5038      if (NumBytes == 8 && !mode64) {
5039         /* Special case hack */
5040         /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
5041         storeBE( mkexpr(t_EA),
5042                  getIReg(rD_addr) );
5043         storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
5044                  getIReg((rD_addr+1) % 32) );
5045      } else {
5046         t_nbytes = newTemp(Ity_I32);
5047         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5048         generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5049         *stopHere = True;
5050      }
5051      return True;
5052
5053   case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
5054      DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5055      t_nbytes = newTemp(Ity_I32);
5056      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5057      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5058      generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
5059      *stopHere = True;
5060      return True;
5061
5062   default:
5063      vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
5064      return False;
5065   }
5066   return True;
5067}
5068
5069
5070/* ------------------------------------------------------------------
5071   Integer Branch Instructions
5072   ------------------------------------------------------------------ */
5073
5074/*
5075  Branch helper function
5076  ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
5077  Returns an I32 which is 0x00000000 if the ctr condition failed
5078  and 0xFFFFFFFF otherwise.
5079*/
5080static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
5081{
5082   IRType ty = mode64 ? Ity_I64 : Ity_I32;
5083   IRTemp ok = newTemp(Ity_I32);
5084
5085   if ((BO >> 2) & 1) {     // independent of ctr
5086      assign( ok, mkU32(0xFFFFFFFF) );
5087   } else {
5088      if ((BO >> 1) & 1) {  // ctr == 0 ?
5089         assign( ok, unop( Iop_1Sto32,
5090                           binop( mkSzOp(ty, Iop_CmpEQ8),
5091                                  getGST( PPC_GST_CTR ),
5092                                  mkSzImm(ty,0))) );
5093      } else {              // ctr != 0 ?
5094         assign( ok, unop( Iop_1Sto32,
5095                           binop( mkSzOp(ty, Iop_CmpNE8),
5096                                  getGST( PPC_GST_CTR ),
5097                                  mkSzImm(ty,0))) );
5098      }
5099   }
5100   return mkexpr(ok);
5101}
5102
5103
5104/*
5105  Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
5106  Returns an I32 which is either 0 if the condition failed or
5107  some arbitrary nonzero value otherwise. */
5108
5109static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
5110{
5111   Int where;
5112   IRTemp res   = newTemp(Ity_I32);
5113   IRTemp cr_bi = newTemp(Ity_I32);
5114
5115   if ((BO >> 4) & 1) {
5116      assign( res, mkU32(1) );
5117   } else {
5118      // ok = (CR[BI] == BO[3]) Note, the following relies on
5119      // getCRbit_anywhere returning a value which
5120      // is either zero or has exactly 1 bit set.
5121      assign( cr_bi, getCRbit_anywhere( BI, &where ) );
5122
5123      if ((BO >> 3) & 1) {
5124         /* We can use cr_bi as-is. */
5125         assign( res, mkexpr(cr_bi) );
5126      } else {
5127         /* We have to invert the sense of the information held in
5128            cr_bi.  For that we need to know which bit
5129            getCRbit_anywhere regards as significant. */
5130         assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
5131                                       mkU32(1<<where)) );
5132      }
5133   }
5134   return mkexpr(res);
5135}
5136
5137
5138/*
5139  Integer Branch Instructions
5140*/
5141static Bool dis_branch ( UInt theInstr,
5142                         VexAbiInfo* vbi,
5143                         /*OUT*/DisResult* dres,
5144                         Bool (*resteerOkFn)(void*,Addr64),
5145                         void* callback_opaque )
5146{
5147   UChar opc1    = ifieldOPC(theInstr);
5148   UChar BO      = ifieldRegDS(theInstr);
5149   UChar BI      = ifieldRegA(theInstr);
5150   UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
5151   UChar b11to15 = ifieldRegB(theInstr);
5152   UInt  opc2    = ifieldOPClo10(theInstr);
5153   UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
5154   UChar flag_AA = ifieldBIT1(theInstr);
5155   UChar flag_LK = ifieldBIT0(theInstr);
5156
5157   IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
5158   Addr64   tgt       = 0;
5159   Int      BD        = extend_s_16to32(BD_u16);
5160   IRTemp   do_branch = newTemp(Ity_I32);
5161   IRTemp   ctr_ok    = newTemp(Ity_I32);
5162   IRTemp   cond_ok   = newTemp(Ity_I32);
5163   IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
5164   IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
5165   IRTemp   lr_old    = newTemp(ty);
5166
5167   /* Hack to pass through code that just wants to read the PC */
5168   if (theInstr == 0x429F0005) {
5169      DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
5170      putGST( PPC_GST_LR, e_nia );
5171      return True;
5172   }
5173
5174   /* The default what-next.  Individual cases can override it. */
5175   dres->whatNext = Dis_StopHere;
5176
5177   switch (opc1) {
5178   case 0x12: // b     (Branch, PPC32 p360)
5179      if (flag_AA) {
5180         tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
5181      } else {
5182         tgt = mkSzAddr( ty, guest_CIA_curr_instr +
5183                             (Long)extend_s_26to64(LI_u26) );
5184      }
5185      if (mode64) {
5186         DIP("b%s%s 0x%llx\n",
5187             flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
5188      } else {
5189         DIP("b%s%s 0x%x\n",
5190             flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
5191      }
5192
5193      if (flag_LK) {
5194         putGST( PPC_GST_LR, e_nia );
5195         if (vbi->guest_ppc_zap_RZ_at_bl
5196             && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
5197            IRTemp t_tgt = newTemp(ty);
5198            assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
5199            make_redzone_AbiHint( vbi, t_tgt,
5200                                  "branch-and-link (unconditional call)" );
5201         }
5202      }
5203
5204      if (resteerOkFn( callback_opaque, tgt )) {
5205         dres->whatNext   = Dis_ResteerU;
5206         dres->continueAt = tgt;
5207      } else {
5208         irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
5209         irsb->next     = mkSzImm(ty, tgt);
5210      }
5211      break;
5212
5213   case 0x10: // bc    (Branch Conditional, PPC32 p361)
5214      DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
5215          flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
5216
5217      if (!(BO & 0x4)) {
5218         putGST( PPC_GST_CTR,
5219                 binop(mkSzOp(ty, Iop_Sub8),
5220                       getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5221      }
5222
5223      /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
5224         cond_ok is either zero or nonzero, since that's the cheapest
5225         way to compute it.  Anding them together gives a value which
5226         is either zero or non zero and so that's what we must test
5227         for in the IRStmt_Exit. */
5228      assign( ctr_ok,  branch_ctr_ok( BO ) );
5229      assign( cond_ok, branch_cond_ok( BO, BI ) );
5230      assign( do_branch,
5231              binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5232
5233      if (flag_AA) {
5234         tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
5235      } else {
5236         tgt = mkSzAddr(ty, guest_CIA_curr_instr +
5237                            (Long)extend_s_16to64(BD_u16));
5238      }
5239      if (flag_LK)
5240         putGST( PPC_GST_LR, e_nia );
5241
5242      stmt( IRStmt_Exit(
5243               binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
5244               flag_LK ? Ijk_Call : Ijk_Boring,
5245               mkSzConst(ty, tgt) ) );
5246
5247      irsb->jumpkind = Ijk_Boring;
5248      irsb->next     = e_nia;
5249      break;
5250
5251   case 0x13:
5252      /* For bclr and bcctr, it appears that the lowest two bits of
5253         b11to15 are a branch hint, and so we only need to ensure it's
5254         of the form 000XX. */
5255      if ((b11to15 & ~3) != 0) {
5256         vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15);
5257         return False;
5258      }
5259
5260      switch (opc2) {
5261      case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
5262         if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
5263            vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
5264            return False;
5265         }
5266         DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5267
5268         assign( cond_ok, branch_cond_ok( BO, BI ) );
5269
5270         /* FIXME: this is confusing.  lr_old holds the old value
5271            of ctr, not lr :-) */
5272         assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
5273
5274         if (flag_LK)
5275            putGST( PPC_GST_LR, e_nia );
5276
5277         stmt( IRStmt_Exit(
5278                  binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
5279                  Ijk_Boring,
5280                  c_nia ));
5281
5282         if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
5283            make_redzone_AbiHint( vbi, lr_old,
5284                                  "b-ctr-l (indirect call)" );
5285	 }
5286
5287         irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
5288         irsb->next     = mkexpr(lr_old);
5289         break;
5290
5291      case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
5292         Bool vanilla_return = False;
5293         if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
5294            DIP("blr\n");
5295            vanilla_return = True;
5296         } else {
5297            DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5298         }
5299
5300         if (!(BO & 0x4)) {
5301            putGST( PPC_GST_CTR,
5302                    binop(mkSzOp(ty, Iop_Sub8),
5303                          getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5304         }
5305
5306         /* See comments above for 'bc' about this */
5307         assign( ctr_ok,  branch_ctr_ok( BO ) );
5308         assign( cond_ok, branch_cond_ok( BO, BI ) );
5309         assign( do_branch,
5310                 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5311
5312         assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
5313
5314         if (flag_LK)
5315            putGST( PPC_GST_LR,  e_nia );
5316
5317         stmt( IRStmt_Exit(
5318                  binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
5319                  Ijk_Boring,
5320                  c_nia ));
5321
5322         if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
5323            make_redzone_AbiHint( vbi, lr_old,
5324                                  "branch-to-lr (unconditional return)" );
5325         }
5326
5327         /* blrl is pretty strange; it's like a return that sets the
5328            return address of its caller to the insn following this
5329            one.  Mark it as a return. */
5330         irsb->jumpkind = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
5331         irsb->next     = mkexpr(lr_old);
5332         break;
5333      }
5334      default:
5335         vex_printf("dis_int_branch(ppc)(opc2)\n");
5336         return False;
5337      }
5338      break;
5339
5340   default:
5341      vex_printf("dis_int_branch(ppc)(opc1)\n");
5342      return False;
5343   }
5344
5345   return True;
5346}
5347
5348
5349
5350/*
5351  Condition Register Logical Instructions
5352*/
5353static Bool dis_cond_logic ( UInt theInstr )
5354{
5355   /* XL-Form */
5356   UChar opc1      = ifieldOPC(theInstr);
5357   UChar crbD_addr = ifieldRegDS(theInstr);
5358   UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
5359   UChar crbA_addr = ifieldRegA(theInstr);
5360   UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
5361   UChar crbB_addr = ifieldRegB(theInstr);
5362   UInt  opc2      = ifieldOPClo10(theInstr);
5363   UChar b0        = ifieldBIT0(theInstr);
5364
5365   IRTemp crbD     = newTemp(Ity_I32);
5366   IRTemp crbA     = newTemp(Ity_I32);
5367   IRTemp crbB     = newTemp(Ity_I32);
5368
5369   if (opc1 != 19 || b0 != 0) {
5370      vex_printf("dis_cond_logic(ppc)(opc1)\n");
5371      return False;
5372   }
5373
5374   if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
5375      if (((crbD_addr & 0x3) != 0) ||
5376          ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
5377         vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
5378         return False;
5379      }
5380      DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
5381      putCR0(   crfD_addr, getCR0(  crfS_addr) );
5382      putCR321( crfD_addr, getCR321(crfS_addr) );
5383   } else {
5384      assign( crbA, getCRbit(crbA_addr) );
5385      if (crbA_addr == crbB_addr)
5386         crbB = crbA;
5387      else
5388         assign( crbB, getCRbit(crbB_addr) );
5389
5390      switch (opc2) {
5391      case 0x101: // crand   (Cond Reg AND, PPC32 p372)
5392         DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5393         assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
5394         break;
5395      case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
5396         DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5397         assign( crbD, binop(Iop_And32,
5398                             mkexpr(crbA),
5399                             unop(Iop_Not32, mkexpr(crbB))) );
5400         break;
5401      case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
5402         DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5403         assign( crbD, unop(Iop_Not32,
5404                            binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
5405         break;
5406      case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
5407         DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5408         assign( crbD, unop(Iop_Not32,
5409                            binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
5410         break;
5411      case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
5412         DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5413         assign( crbD, unop(Iop_Not32,
5414                            binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
5415         break;
5416      case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
5417         DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5418         assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
5419         break;
5420      case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
5421         DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5422         assign( crbD, binop(Iop_Or32,
5423                             mkexpr(crbA),
5424                             unop(Iop_Not32, mkexpr(crbB))) );
5425         break;
5426      case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
5427         DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5428         assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
5429         break;
5430      default:
5431         vex_printf("dis_cond_logic(ppc)(opc2)\n");
5432         return False;
5433      }
5434
5435      putCRbit( crbD_addr, mkexpr(crbD) );
5436   }
5437   return True;
5438}
5439
5440
5441/*
5442  Trap instructions
5443*/
5444
5445/* Do the code generation for a trap.  Returned Bool is true iff
5446   this is an unconditional trap.  If the two arg IRExpr*s are
5447   Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
5448   then they are 64-bit, and we must be disassembling 64-bit
5449   instructions. */
5450static Bool do_trap ( UChar TO,
5451                      IRExpr* argL0, IRExpr* argR0, Addr64 cia )
5452{
5453   IRTemp argL, argR;
5454   IRExpr *argLe, *argRe, *cond, *tmp;
5455
5456   Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
5457
5458   IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
5459   IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
5460   IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
5461   IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
5462   IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
5463   IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
5464   IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
5465   IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
5466   IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
5467   IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
5468
5469   const UChar b11100 = 0x1C;
5470   const UChar b00111 = 0x07;
5471
5472   if (is32bit) {
5473      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
5474      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
5475   } else {
5476      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
5477      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
5478      vassert( mode64 );
5479   }
5480
5481   if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
5482      /* Unconditional trap.  Just do the exit without
5483         testing the arguments. */
5484      stmt( IRStmt_Exit(
5485               binop(opCMPEQ, const0, const0),
5486               Ijk_SigTRAP,
5487               mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia)
5488      ));
5489      return True; /* unconditional trap */
5490   }
5491
5492   if (is32bit) {
5493      argL = newTemp(Ity_I32);
5494      argR = newTemp(Ity_I32);
5495   } else {
5496      argL = newTemp(Ity_I64);
5497      argR = newTemp(Ity_I64);
5498   }
5499
5500   assign( argL, argL0 );
5501   assign( argR, argR0 );
5502
5503   argLe = mkexpr(argL);
5504   argRe = mkexpr(argR);
5505
5506   cond = const0;
5507   if (TO & 16) { // L <s R
5508      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
5509      cond = binop(opOR, tmp, cond);
5510   }
5511   if (TO & 8) { // L >s R
5512      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
5513      cond = binop(opOR, tmp, cond);
5514   }
5515   if (TO & 4) { // L == R
5516      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
5517      cond = binop(opOR, tmp, cond);
5518   }
5519   if (TO & 2) { // L <u R
5520      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
5521      cond = binop(opOR, tmp, cond);
5522   }
5523   if (TO & 1) { // L >u R
5524      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
5525      cond = binop(opOR, tmp, cond);
5526   }
5527   stmt( IRStmt_Exit(
5528            binop(opCMPNE, cond, const0),
5529            Ijk_SigTRAP,
5530            mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia)
5531   ));
5532   return False; /* not an unconditional trap */
5533}
5534
5535static Bool dis_trapi ( UInt theInstr,
5536                        /*OUT*/DisResult* dres )
5537{
5538   /* D-Form */
5539   UChar  opc1    = ifieldOPC(theInstr);
5540   UChar  TO      = ifieldRegDS(theInstr);
5541   UChar  rA_addr = ifieldRegA(theInstr);
5542   UInt   uimm16  = ifieldUIMM16(theInstr);
5543   ULong  simm16  = extend_s_16to64(uimm16);
5544   Addr64 cia     = guest_CIA_curr_instr;
5545   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5546   Bool   uncond  = False;
5547
5548   switch (opc1) {
5549   case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
5550      uncond = do_trap( TO,
5551                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
5552                               : getIReg(rA_addr),
5553                        mkU32( (UInt)simm16 ),
5554                        cia );
5555      if (TO == 4) {
5556         DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
5557      } else {
5558         DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
5559      }
5560      break;
5561   case 0x02: // tdi
5562      if (!mode64)
5563         return False;
5564      uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
5565      if (TO == 4) {
5566         DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
5567      } else {
5568         DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
5569      }
5570      break;
5571   default:
5572      return False;
5573   }
5574
5575   if (uncond) {
5576      /* If the trap shows signs of being unconditional, don't
5577         continue decoding past it. */
5578      irsb->next     = mkSzImm( ty, nextInsnAddr() );
5579      irsb->jumpkind = Ijk_Boring;
5580      dres->whatNext = Dis_StopHere;
5581   }
5582
5583   return True;
5584}
5585
5586static Bool dis_trap ( UInt theInstr,
5587                        /*OUT*/DisResult* dres )
5588{
5589   /* X-Form */
5590   UInt   opc2    = ifieldOPClo10(theInstr);
5591   UChar  TO      = ifieldRegDS(theInstr);
5592   UChar  rA_addr = ifieldRegA(theInstr);
5593   UChar  rB_addr = ifieldRegB(theInstr);
5594   Addr64 cia     = guest_CIA_curr_instr;
5595   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5596   Bool   uncond  = False;
5597
5598   if (ifieldBIT0(theInstr) != 0)
5599      return False;
5600
5601   switch (opc2) {
5602   case 0x004: // tw  (Trap Word, PPC64 p540)
5603      uncond = do_trap( TO,
5604                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
5605                               : getIReg(rA_addr),
5606                        mode64 ? unop(Iop_64to32, getIReg(rB_addr))
5607                               : getIReg(rB_addr),
5608                        cia );
5609      if (TO == 4) {
5610         DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
5611      } else {
5612         DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
5613      }
5614      break;
5615   case 0x044: // td (Trap Doubleword, PPC64 p534)
5616      if (!mode64)
5617         return False;
5618      uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
5619      if (TO == 4) {
5620         DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
5621      } else {
5622         DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
5623      }
5624      break;
5625   default:
5626      return False;
5627   }
5628
5629   if (uncond) {
5630      /* If the trap shows signs of being unconditional, don't
5631         continue decoding past it. */
5632      irsb->next     = mkSzImm( ty, nextInsnAddr() );
5633      irsb->jumpkind = Ijk_Boring;
5634      dres->whatNext = Dis_StopHere;
5635   }
5636
5637   return True;
5638}
5639
5640
5641/*
5642  System Linkage Instructions
5643*/
5644static Bool dis_syslink ( UInt theInstr,
5645                          VexAbiInfo* abiinfo, DisResult* dres )
5646{
5647   IRType ty = mode64 ? Ity_I64 : Ity_I32;
5648
5649   if (theInstr != 0x44000002) {
5650      vex_printf("dis_syslink(ppc)(theInstr)\n");
5651      return False;
5652   }
5653
5654   // sc  (System Call, PPC32 p504)
5655   DIP("sc\n");
5656
5657   /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX
5658      Valgrind can back the guest up to this instruction if it needs
5659      to restart the syscall. */
5660   putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
5661
5662   /* It's important that all ArchRegs carry their up-to-date value
5663      at this point.  So we declare an end-of-block here, which
5664      forces any TempRegs caching ArchRegs to be flushed. */
5665   irsb->next     = abiinfo->guest_ppc_sc_continues_at_LR
5666                       ? getGST( PPC_GST_LR )
5667                       : mkSzImm( ty, nextInsnAddr() );
5668   irsb->jumpkind = Ijk_Sys_syscall;
5669
5670   dres->whatNext = Dis_StopHere;
5671   return True;
5672}
5673
5674
5675/*
5676  Memory Synchronization Instructions
5677
5678  Note on Reservations:
5679  We rely on the assumption that V will in fact only allow one thread at
5680  once to run.  In effect, a thread can make a reservation, but we don't
5681  check any stores it does.  Instead, the reservation is cancelled when
5682  the scheduler switches to another thread (run_thread_for_a_while()).
5683*/
5684static Bool dis_memsync ( UInt theInstr )
5685{
5686   /* X-Form, XL-Form */
5687   UChar opc1    = ifieldOPC(theInstr);
5688   UInt  b11to25 = IFIELD(theInstr, 11, 15);
5689   UChar flag_L  = ifieldRegDS(theInstr);
5690   UInt  b11to20 = IFIELD(theInstr, 11, 10);
5691   UChar rD_addr = ifieldRegDS(theInstr);
5692   UChar rS_addr = rD_addr;
5693   UChar rA_addr = ifieldRegA(theInstr);
5694   UChar rB_addr = ifieldRegB(theInstr);
5695   UInt  opc2    = ifieldOPClo10(theInstr);
5696   UChar b0      = ifieldBIT0(theInstr);
5697
5698   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
5699   IRTemp EA     = newTemp(ty);
5700
5701   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5702
5703   switch (opc1) {
5704   /* XL-Form */
5705   case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
5706      if (opc2 != 0x096) {
5707         vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
5708         return False;
5709      }
5710      if (b11to25 != 0 || b0 != 0) {
5711         vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
5712         return False;
5713      }
5714      DIP("isync\n");
5715      stmt( IRStmt_MBE(Imbe_Fence) );
5716      break;
5717
5718   /* X-Form */
5719   case 0x1F:
5720      switch (opc2) {
5721      case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394)
5722         if (b11to25 != 0 || b0 != 0) {
5723            vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n");
5724            return False;
5725         }
5726         DIP("eieio\n");
5727         /* Insert a memory fence, just to be on the safe side. */
5728         stmt( IRStmt_MBE(Imbe_Fence) );
5729         break;
5730
5731      case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
5732         IRTemp res;
5733         /* According to the PowerPC ISA version 2.05, b0 (called EH
5734            in the documentation) is merely a hint bit to the
5735            hardware, I think as to whether or not contention is
5736            likely.  So we can just ignore it. */
5737         DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
5738
5739         // trap if misaligned
5740         gen_SIGBUS_if_misaligned( EA, 4 );
5741
5742         // and actually do the load
5743         res = newTemp(Ity_I32);
5744         stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
5745
5746         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
5747         break;
5748      }
5749
5750      case 0x096: {
5751         // stwcx. (Store Word Conditional Indexed, PPC32 p532)
5752         // Note this has to handle stwcx. in both 32- and 64-bit modes,
5753         // so isn't quite as straightforward as it might otherwise be.
5754         IRTemp rS = newTemp(Ity_I32);
5755         IRTemp resSC;
5756         if (b0 != 1) {
5757            vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
5758            return False;
5759         }
5760         DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5761
5762         // trap if misaligned
5763         gen_SIGBUS_if_misaligned( EA, 4 );
5764
5765         // Get the data to be stored, and narrow to 32 bits if necessary
5766         assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
5767
5768         // Do the store, and get success/failure bit into resSC
5769         resSC = newTemp(Ity_I1);
5770         stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
5771
5772         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
5773         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
5774         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
5775         putCR0(0, getXER_SO());
5776
5777         /* Note:
5778            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
5779            whether rS is stored is dependent on that value. */
5780         /* So I guess we can just ignore this case? */
5781         break;
5782      }
5783
5784      case 0x256: // sync (Synchronize, PPC32 p543),
5785                  // also lwsync (L==1), ptesync (L==2)
5786         /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
5787
5788            The PowerPC architecture used in IBM chips has expanded
5789            the sync instruction into two variants: lightweight sync
5790            and heavyweight sync.  The original sync instruction is
5791            the new heavyweight sync and lightweight sync is a strict
5792            subset of the heavyweight sync functionality. This allows
5793            the programmer to specify a less expensive operation on
5794            high-end systems when the full sync functionality is not
5795            necessary.
5796
5797            The basic "sync" mnemonic now utilizes an operand. "sync"
5798            without an operand now becomes a extended mnemonic for
5799            heavyweight sync.  Processors without the lwsync
5800            instruction will not decode the L field and will perform a
5801            heavyweight sync.  Everything is backward compatible.
5802
5803            sync    =       sync 0
5804            lwsync  =       sync 1
5805            ptesync =       sync 2    *** TODO - not implemented ***
5806         */
5807         if (b11to20 != 0 || b0 != 0) {
5808            vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
5809            return False;
5810         }
5811         if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
5812            vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
5813            return False;
5814         }
5815         DIP("%ssync\n", flag_L == 1 ? "lw" : "");
5816         /* Insert a memory fence.  It's sometimes important that these
5817            are carried through to the generated code. */
5818         stmt( IRStmt_MBE(Imbe_Fence) );
5819         break;
5820
5821      /* 64bit Memsync */
5822      case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
5823         IRTemp res;
5824         /* According to the PowerPC ISA version 2.05, b0 (called EH
5825            in the documentation) is merely a hint bit to the
5826            hardware, I think as to whether or not contention is
5827            likely.  So we can just ignore it. */
5828         if (!mode64)
5829            return False;
5830         DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
5831
5832         // trap if misaligned
5833         gen_SIGBUS_if_misaligned( EA, 8 );
5834
5835         // and actually do the load
5836         res = newTemp(Ity_I64);
5837         stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
5838
5839         putIReg( rD_addr, mkexpr(res) );
5840         break;
5841      }
5842
5843      case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
5844         // A marginally simplified version of the stwcx. case
5845         IRTemp rS = newTemp(Ity_I64);
5846         IRTemp resSC;
5847         if (b0 != 1) {
5848            vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
5849            return False;
5850         }
5851         if (!mode64)
5852            return False;
5853         DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5854
5855         // trap if misaligned
5856         gen_SIGBUS_if_misaligned( EA, 8 );
5857
5858         // Get the data to be stored
5859         assign( rS, getIReg(rS_addr) );
5860
5861         // Do the store, and get success/failure bit into resSC
5862         resSC = newTemp(Ity_I1);
5863         stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
5864
5865         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
5866         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
5867         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
5868         putCR0(0, getXER_SO());
5869
5870         /* Note:
5871            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
5872            whether rS is stored is dependent on that value. */
5873         /* So I guess we can just ignore this case? */
5874         break;
5875      }
5876
5877      default:
5878         vex_printf("dis_memsync(ppc)(opc2)\n");
5879         return False;
5880      }
5881      break;
5882
5883   default:
5884      vex_printf("dis_memsync(ppc)(opc1)\n");
5885      return False;
5886   }
5887   return True;
5888}
5889
5890
5891
5892/*
5893  Integer Shift Instructions
5894*/
5895static Bool dis_int_shift ( UInt theInstr )
5896{
5897   /* X-Form, XS-Form */
5898   UChar opc1    = ifieldOPC(theInstr);
5899   UChar rS_addr = ifieldRegDS(theInstr);
5900   UChar rA_addr = ifieldRegA(theInstr);
5901   UChar rB_addr = ifieldRegB(theInstr);
5902   UChar sh_imm  = rB_addr;
5903   UInt  opc2    = ifieldOPClo10(theInstr);
5904   UChar b1      = ifieldBIT1(theInstr);
5905   UChar flag_rC = ifieldBIT0(theInstr);
5906
5907   IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
5908   IRTemp  rA         = newTemp(ty);
5909   IRTemp  rS         = newTemp(ty);
5910   IRTemp  rB         = newTemp(ty);
5911   IRTemp  outofrange = newTemp(Ity_I8);
5912   IRTemp  rS_lo32    = newTemp(Ity_I32);
5913   IRTemp  rB_lo32    = newTemp(Ity_I32);
5914   IRExpr* e_tmp;
5915
5916   assign( rS, getIReg(rS_addr) );
5917   assign( rB, getIReg(rB_addr) );
5918   assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
5919   assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
5920
5921   if (opc1 == 0x1F) {
5922      switch (opc2) {
5923      case 0x018: { // slw (Shift Left Word, PPC32 p505)
5924         DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5925             rA_addr, rS_addr, rB_addr);
5926         /* rA = rS << rB */
5927         /* ppc32 semantics are:
5928            slw(x,y) = (x << (y & 31))         -- primary result
5929                       & ~((y << 26) >>s 31)   -- make result 0
5930                                                  for y in 32 .. 63
5931         */
5932         e_tmp =
5933            binop( Iop_And32,
5934               binop( Iop_Shl32,
5935                      mkexpr(rS_lo32),
5936                      unop( Iop_32to8,
5937                            binop(Iop_And32,
5938                                  mkexpr(rB_lo32), mkU32(31)))),
5939               unop( Iop_Not32,
5940                     binop( Iop_Sar32,
5941                            binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
5942                            mkU8(31))) );
5943         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
5944         break;
5945      }
5946
5947      case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
5948         IRTemp sh_amt = newTemp(Ity_I32);
5949         DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5950             rA_addr, rS_addr, rB_addr);
5951         /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
5952            amt = rB & 63
5953            rA = Sar32( rS, amt > 31 ? 31 : amt )
5954            XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
5955         */
5956         assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
5957                                          mkexpr(rB_lo32)) );
5958         assign( outofrange,
5959                 unop( Iop_1Uto8,
5960                       binop(Iop_CmpLT32U, mkU32(31),
5961                                           mkexpr(sh_amt)) ));
5962         e_tmp = binop( Iop_Sar32,
5963                        mkexpr(rS_lo32),
5964                        unop( Iop_32to8,
5965                              IRExpr_Mux0X( mkexpr(outofrange),
5966                                            mkexpr(sh_amt),
5967                                            mkU32(31)) ) );
5968         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
5969
5970         set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
5971                     mkexpr(rA),
5972                     mkWidenFrom32(ty, mkexpr(rS_lo32), True),
5973                     mkWidenFrom32(ty, mkexpr(sh_amt), True ),
5974                     mkWidenFrom32(ty, getXER_CA32(), True) );
5975         break;
5976      }
5977
5978      case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
5979         DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
5980             rA_addr, rS_addr, sh_imm);
5981         vassert(sh_imm < 32);
5982         if (mode64) {
5983            assign( rA, binop(Iop_Sar64,
5984                              binop(Iop_Shl64, getIReg(rS_addr),
5985                                               mkU8(32)),
5986                              mkU8(32 + sh_imm)) );
5987         } else {
5988            assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
5989                                         mkU8(sh_imm)) );
5990         }
5991
5992         set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
5993                     mkexpr(rA),
5994                     mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
5995                     mkSzImm(ty, sh_imm),
5996                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
5997         break;
5998
5999      case 0x218: // srw (Shift Right Word, PPC32 p508)
6000         DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6001             rA_addr, rS_addr, rB_addr);
6002         /* rA = rS >>u rB */
6003         /* ppc32 semantics are:
6004            srw(x,y) = (x >>u (y & 31))        -- primary result
6005                       & ~((y << 26) >>s 31)   -- make result 0
6006                                                  for y in 32 .. 63
6007         */
6008         e_tmp =
6009            binop(
6010               Iop_And32,
6011               binop( Iop_Shr32,
6012                      mkexpr(rS_lo32),
6013                      unop( Iop_32to8,
6014                            binop(Iop_And32, mkexpr(rB_lo32),
6015                                             mkU32(31)))),
6016               unop( Iop_Not32,
6017                     binop( Iop_Sar32,
6018                            binop(Iop_Shl32, mkexpr(rB_lo32),
6019                                             mkU8(26)),
6020                            mkU8(31))));
6021         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6022         break;
6023
6024
6025      /* 64bit Shifts */
6026      case 0x01B: // sld (Shift Left DWord, PPC64 p568)
6027         DIP("sld%s r%u,r%u,r%u\n",
6028             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6029         /* rA = rS << rB */
6030         /* ppc64 semantics are:
6031            slw(x,y) = (x << (y & 63))         -- primary result
6032                       & ~((y << 57) >>s 63)   -- make result 0
6033                                                  for y in 64 ..
6034         */
6035         assign( rA,
6036            binop(
6037               Iop_And64,
6038               binop( Iop_Shl64,
6039                      mkexpr(rS),
6040                      unop( Iop_64to8,
6041                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6042               unop( Iop_Not64,
6043                     binop( Iop_Sar64,
6044                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6045                            mkU8(63)))) );
6046         break;
6047
6048      case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
6049         IRTemp sh_amt = newTemp(Ity_I64);
6050         DIP("srad%s r%u,r%u,r%u\n",
6051             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6052         /* amt = rB & 127
6053            rA = Sar64( rS, amt > 63 ? 63 : amt )
6054            XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
6055         */
6056         assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
6057         assign( outofrange,
6058                 unop( Iop_1Uto8,
6059                       binop(Iop_CmpLT64U, mkU64(63),
6060                                           mkexpr(sh_amt)) ));
6061         assign( rA,
6062                 binop( Iop_Sar64,
6063                        mkexpr(rS),
6064                        unop( Iop_64to8,
6065                              IRExpr_Mux0X( mkexpr(outofrange),
6066                                            mkexpr(sh_amt),
6067                                            mkU64(63)) ))
6068               );
6069         set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
6070                     mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
6071                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6072         break;
6073      }
6074
6075      case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
6076         sh_imm |= b1<<5;
6077         vassert(sh_imm < 64);
6078         DIP("sradi%s r%u,r%u,%u\n",
6079             flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
6080         assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
6081
6082         set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
6083                     mkexpr(rA),
6084                     getIReg(rS_addr),
6085                     mkU64(sh_imm),
6086                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6087         break;
6088
6089      case 0x21B: // srd (Shift Right DWord, PPC64 p574)
6090         DIP("srd%s r%u,r%u,r%u\n",
6091             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6092         /* rA = rS >>u rB */
6093         /* ppc semantics are:
6094            srw(x,y) = (x >>u (y & 63))        -- primary result
6095                       & ~((y << 57) >>s 63)   -- make result 0
6096                                                  for y in 64 .. 127
6097         */
6098         assign( rA,
6099            binop(
6100               Iop_And64,
6101               binop( Iop_Shr64,
6102                      mkexpr(rS),
6103                      unop( Iop_64to8,
6104                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6105               unop( Iop_Not64,
6106                     binop( Iop_Sar64,
6107                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6108                            mkU8(63)))) );
6109         break;
6110
6111      default:
6112         vex_printf("dis_int_shift(ppc)(opc2)\n");
6113         return False;
6114      }
6115   } else {
6116      vex_printf("dis_int_shift(ppc)(opc1)\n");
6117      return False;
6118   }
6119
6120   putIReg( rA_addr, mkexpr(rA) );
6121
6122   if (flag_rC) {
6123      set_CR0( mkexpr(rA) );
6124   }
6125   return True;
6126}
6127
6128
6129
6130/*
6131  Integer Load/Store Reverse Instructions
6132*/
6133/* Generates code to swap the byte order in an Ity_I32. */
6134static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
6135{
6136   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
6137   return
6138      binop(Iop_Or32,
6139         binop(Iop_Shl32, mkexpr(t), mkU8(24)),
6140      binop(Iop_Or32,
6141         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
6142                          mkU32(0x00FF0000)),
6143      binop(Iop_Or32,
6144         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
6145                          mkU32(0x0000FF00)),
6146         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
6147                          mkU32(0x000000FF) )
6148      )));
6149}
6150
6151/* Generates code to swap the byte order in the lower half of an Ity_I32,
6152   and zeroes the upper half. */
6153static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
6154{
6155   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
6156   return
6157      binop(Iop_Or32,
6158         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
6159                          mkU32(0x0000FF00)),
6160         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
6161                          mkU32(0x000000FF))
6162      );
6163}
6164
6165static Bool dis_int_ldst_rev ( UInt theInstr )
6166{
6167   /* X-Form */
6168   UChar opc1    = ifieldOPC(theInstr);
6169   UChar rD_addr = ifieldRegDS(theInstr);
6170   UChar rS_addr = rD_addr;
6171   UChar rA_addr = ifieldRegA(theInstr);
6172   UChar rB_addr = ifieldRegB(theInstr);
6173   UInt  opc2    = ifieldOPClo10(theInstr);
6174   UChar b0      = ifieldBIT0(theInstr);
6175
6176   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6177   IRTemp EA = newTemp(ty);
6178   IRTemp w1 = newTemp(Ity_I32);
6179   IRTemp w2 = newTemp(Ity_I32);
6180
6181   if (opc1 != 0x1F || b0 != 0) {
6182      vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
6183      return False;
6184   }
6185
6186   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6187
6188   switch (opc2) {
6189
6190      case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
6191         DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
6192         assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) );
6193         assign( w2, gen_byterev16(w1) );
6194         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
6195                                         /* Signed */False) );
6196         break;
6197
6198      case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
6199         DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
6200         assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
6201         assign( w2, gen_byterev32(w1) );
6202         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
6203                                         /* Signed */False) );
6204         break;
6205
6206      case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
6207      {
6208         IRExpr * nextAddr;
6209         IRTemp w3 = newTemp( Ity_I32 );
6210         IRTemp w4 = newTemp( Ity_I32 );
6211         DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
6212         assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) );
6213         assign( w2, gen_byterev32( w1 ) );
6214         nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
6215                           ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
6216         assign( w3, loadBE( Ity_I32, nextAddr ) );
6217         assign( w4, gen_byterev32( w3 ) );
6218         putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
6219         break;
6220      }
6221
6222      case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
6223         DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6224         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
6225         storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
6226         break;
6227
6228      case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
6229         DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6230         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
6231         storeBE( mkexpr(EA), gen_byterev32(w1) );
6232         break;
6233
6234      case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
6235      {
6236         IRTemp lo = newTemp(Ity_I32);
6237         IRTemp hi = newTemp(Ity_I32);
6238         IRTemp rS = newTemp(Ity_I64);
6239         assign( rS, getIReg( rS_addr ) );
6240         DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6241         assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
6242         assign(hi, unop(Iop_64to32, mkexpr(rS)));
6243         storeBE( mkexpr( EA ),
6244                  binop( Iop_32HLto64, gen_byterev32( hi ), gen_byterev32( lo ) ) );
6245         break;
6246      }
6247
6248      default:
6249         vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
6250         return False;
6251   }
6252   return True;
6253}
6254
6255
6256
6257/*
6258  Processor Control Instructions
6259*/
6260static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr )
6261{
6262   UChar opc1     = ifieldOPC(theInstr);
6263
6264   /* X-Form */
6265   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
6266   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
6267   UChar rD_addr  = ifieldRegDS(theInstr);
6268   UInt  b11to20  = IFIELD( theInstr, 11, 10 );
6269
6270   /* XFX-Form */
6271   UChar rS_addr  = rD_addr;
6272   UInt  SPR      = b11to20;
6273   UInt  TBR      = b11to20;
6274   UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
6275   UInt  CRM      = IFIELD( theInstr, 12, 8 );
6276   UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
6277
6278   UInt  opc2     = ifieldOPClo10(theInstr);
6279   UChar b0       = ifieldBIT0(theInstr);
6280
6281   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6282   IRTemp rS = newTemp(ty);
6283   assign( rS, getIReg(rS_addr) );
6284
6285   /* Reorder SPR field as per PPC32 p470 */
6286   SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
6287   /* Reorder TBR field as per PPC32 p475 */
6288   TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
6289
6290   if (opc1 != 0x1F || b0 != 0) {
6291      vex_printf("dis_proc_ctl(ppc)(opc1|b0)\n");
6292      return False;
6293   }
6294
6295   switch (opc2) {
6296   /* X-Form */
6297   case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
6298      if (b21to22 != 0 || b11to20 != 0) {
6299         vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
6300         return False;
6301      }
6302      DIP("mcrxr crf%d\n", crfD);
6303      /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
6304      putGST_field( PPC_GST_CR,
6305                    getGST_field( PPC_GST_XER, 7 ),
6306                    crfD );
6307
6308      // Clear XER[0-3]
6309      putXER_SO( mkU8(0) );
6310      putXER_OV( mkU8(0) );
6311      putXER_CA( mkU8(0) );
6312      break;
6313   }
6314
6315   case 0x013:
6316      // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
6317      // b20==1 & b11==0: mfocrf (Move from One CR Field)
6318      // However it seems that the 'mfcr' behaviour is an acceptable
6319      // implementation of mfocr (from the 2.02 arch spec)
6320      if (b11to20 == 0) {
6321         DIP("mfcr r%u\n", rD_addr);
6322         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
6323                                         /* Signed */False) );
6324         break;
6325      }
6326      if (b20 == 1 && b11 == 0) {
6327         DIP("mfocrf r%u,%u\n", rD_addr, CRM);
6328         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
6329                                         /* Signed */False) );
6330         break;
6331      }
6332      /* not decodable */
6333      return False;
6334
6335   /* XFX-Form */
6336   case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
6337
6338      switch (SPR) {  // Choose a register...
6339      case 0x1:
6340         DIP("mfxer r%u\n", rD_addr);
6341         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
6342                                         /* Signed */False) );
6343         break;
6344      case 0x8:
6345         DIP("mflr r%u\n", rD_addr);
6346         putIReg( rD_addr, getGST( PPC_GST_LR ) );
6347         break;
6348      case 0x9:
6349         DIP("mfctr r%u\n", rD_addr);
6350         putIReg( rD_addr, getGST( PPC_GST_CTR ) );
6351         break;
6352      case 0x100:
6353         DIP("mfvrsave r%u\n", rD_addr);
6354         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
6355                                         /* Signed */False) );
6356         break;
6357
6358      case 0x103:
6359         DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
6360         putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
6361         break;
6362
6363      /* Even a lowly PPC7400 can run the associated helper, so no
6364         obvious need for feature testing at this point. */
6365      case 268 /* 0x10C */:
6366      case 269 /* 0x10D */: {
6367         UInt     arg  = SPR==268 ? 0 : 1;
6368         IRTemp   val  = newTemp(Ity_I32);
6369         IRExpr** args = mkIRExprVec_1( mkU32(arg) );
6370         IRDirty* d    = unsafeIRDirty_1_N(
6371                            val,
6372                            0/*regparms*/,
6373                            "ppc32g_dirtyhelper_MFSPR_268_269",
6374                            fnptr_to_fnentry
6375                               (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
6376                            args
6377                         );
6378         /* execute the dirty call, dumping the result in val. */
6379         stmt( IRStmt_Dirty(d) );
6380         putIReg( rD_addr,
6381                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
6382         DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
6383         break;
6384      }
6385
6386      /* Again, runs natively on PPC7400 (7447, really).  Not
6387         bothering with a feature test. */
6388      case 287: /* 0x11F */ {
6389         IRTemp   val  = newTemp(Ity_I32);
6390         IRExpr** args = mkIRExprVec_0();
6391         IRDirty* d    = unsafeIRDirty_1_N(
6392                            val,
6393                            0/*regparms*/,
6394                            "ppc32g_dirtyhelper_MFSPR_287",
6395                            fnptr_to_fnentry
6396                               (vbi, &ppc32g_dirtyhelper_MFSPR_287),
6397                            args
6398                         );
6399         /* execute the dirty call, dumping the result in val. */
6400         stmt( IRStmt_Dirty(d) );
6401         putIReg( rD_addr,
6402                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
6403         DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
6404         break;
6405      }
6406
6407      default:
6408         vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
6409         return False;
6410      }
6411      break;
6412
6413   case 0x173: { // mftb (Move from Time Base, PPC32 p475)
6414      IRTemp   val  = newTemp(Ity_I64);
6415      IRExpr** args = mkIRExprVec_0();
6416      IRDirty* d    = unsafeIRDirty_1_N(
6417                              val,
6418                              0/*regparms*/,
6419                              "ppcg_dirtyhelper_MFTB",
6420                              fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
6421                              args );
6422      /* execute the dirty call, dumping the result in val. */
6423      stmt( IRStmt_Dirty(d) );
6424
6425      switch (TBR) {
6426      case 269:
6427         DIP("mftbu r%u", rD_addr);
6428         putIReg( rD_addr,
6429                  mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
6430                                /* Signed */False) );
6431         break;
6432      case 268:
6433         DIP("mftb r%u", rD_addr);
6434         putIReg( rD_addr, (mode64) ? mkexpr(val) :
6435                                      unop(Iop_64to32, mkexpr(val)) );
6436         break;
6437      default:
6438         return False; /* illegal instruction */
6439      }
6440      break;
6441   }
6442
6443   case 0x090: {
6444      // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
6445      // b20==1: mtocrf (Move to One Cond Reg Field)
6446      Int   cr;
6447      UChar shft;
6448      if (b11 != 0)
6449         return False;
6450      if (b20 == 1) {
6451         /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
6452            1 field is written.  It seems more robust to decline to
6453            decode the insn if so. */
6454         switch (CRM) {
6455            case 0x01: case 0x02: case 0x04: case 0x08:
6456            case 0x10: case 0x20: case 0x40: case 0x80:
6457               break;
6458            default:
6459               return False;
6460         }
6461      }
6462      DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
6463                           CRM, rS_addr);
6464      /* Write to each field specified by CRM */
6465      for (cr = 0; cr < 8; cr++) {
6466         if ((CRM & (1 << (7-cr))) == 0)
6467            continue;
6468         shft = 4*(7-cr);
6469         putGST_field( PPC_GST_CR,
6470                       binop(Iop_Shr32,
6471                             mkNarrowTo32(ty, mkexpr(rS)),
6472                             mkU8(shft)), cr );
6473      }
6474      break;
6475   }
6476
6477   case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
6478
6479      switch (SPR) {  // Choose a register...
6480      case 0x1:
6481         DIP("mtxer r%u\n", rS_addr);
6482         putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
6483         break;
6484      case 0x8:
6485         DIP("mtlr r%u\n", rS_addr);
6486         putGST( PPC_GST_LR, mkexpr(rS) );
6487         break;
6488      case 0x9:
6489         DIP("mtctr r%u\n", rS_addr);
6490         putGST( PPC_GST_CTR, mkexpr(rS) );
6491         break;
6492      case 0x100:
6493         DIP("mtvrsave r%u\n", rS_addr);
6494         putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
6495         break;
6496
6497      default:
6498         vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
6499         return False;
6500      }
6501      break;
6502
6503   default:
6504      vex_printf("dis_proc_ctl(ppc)(opc2)\n");
6505      return False;
6506   }
6507   return True;
6508}
6509
6510
6511/*
6512  Cache Management Instructions
6513*/
6514static Bool dis_cache_manage ( UInt         theInstr,
6515                               DisResult*   dres,
6516                               VexArchInfo* guest_archinfo )
6517{
6518   /* X-Form */
6519   UChar opc1    = ifieldOPC(theInstr);
6520   UChar b21to25 = ifieldRegDS(theInstr);
6521   UChar rA_addr = ifieldRegA(theInstr);
6522   UChar rB_addr = ifieldRegB(theInstr);
6523   UInt  opc2    = ifieldOPClo10(theInstr);
6524   UChar b0      = ifieldBIT0(theInstr);
6525   UInt  lineszB = guest_archinfo->ppc_cache_line_szB;
6526   Bool  is_dcbzl = False;
6527
6528   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6529
6530   /* For dcbt, the lowest two bits of b21to25 encode an
6531      access-direction hint (TH field) which we ignore.  Well, that's
6532      what the PowerPC documentation says.  In fact xlc -O4 on POWER5
6533      seems to generate values of 8 and 10 for b21to25. */
6534   if (opc1 == 0x1F && opc2 == 0x116) {
6535     /* b21to25 &= ~3; */ /* if the docs were true */
6536     b21to25 = 0; /* blunt instrument */
6537   }
6538   if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
6539      if (b21to25 == 1) {
6540         is_dcbzl = True;
6541         b21to25 = 0;
6542         if (!(guest_archinfo->ppc_dcbzl_szB)) {
6543            vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
6544            return False;
6545         }
6546      }
6547   }
6548
6549   if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
6550      if (0) vex_printf("dis_cache_manage %d %d %d\n",
6551                        (Int)opc1, (Int)b21to25, (Int)b0);
6552      vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n");
6553      return False;
6554   }
6555
6556   /* stay sane .. */
6557   vassert(lineszB == 32 || lineszB == 64 || lineszB == 128);
6558
6559   switch (opc2) {
6560//zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
6561//zz       vassert(0); /* AWAITING TEST CASE */
6562//zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
6563//zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
6564//zz       break;
6565
6566   case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
6567      DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
6568      /* nop as far as vex is concerned */
6569      break;
6570
6571   case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
6572      DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
6573      /* nop as far as vex is concerned */
6574      break;
6575
6576   case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
6577      DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
6578      /* nop as far as vex is concerned */
6579      break;
6580
6581   case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
6582      DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
6583      /* nop as far as vex is concerned */
6584      break;
6585
6586   case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
6587                 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
6588      /* Clear all bytes in cache block at (rA|0) + rB. */
6589      IRTemp  EA   = newTemp(ty);
6590      IRTemp  addr = newTemp(ty);
6591      IRExpr* irx_addr;
6592      UInt    i;
6593      UInt clearszB;
6594      if (is_dcbzl) {
6595          clearszB = guest_archinfo->ppc_dcbzl_szB;
6596          DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
6597      }
6598      else {
6599          clearszB = guest_archinfo->ppc_dcbz_szB;
6600          DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
6601      }
6602
6603      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6604
6605      if (mode64) {
6606         /* Round EA down to the start of the containing block. */
6607         assign( addr, binop( Iop_And64,
6608                              mkexpr(EA),
6609                              mkU64( ~((ULong)clearszB-1) )) );
6610
6611         for (i = 0; i < clearszB / 8; i++) {
6612            irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
6613            storeBE( irx_addr, mkU64(0) );
6614         }
6615      } else {
6616         /* Round EA down to the start of the containing block. */
6617         assign( addr, binop( Iop_And32,
6618                              mkexpr(EA),
6619                              mkU32( ~(clearszB-1) )) );
6620
6621         for (i = 0; i < clearszB / 4; i++) {
6622            irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
6623            storeBE( irx_addr, mkU32(0) );
6624         }
6625      }
6626      break;
6627   }
6628
6629   case 0x3D6: {
6630      // icbi (Instruction Cache Block Invalidate, PPC32 p431)
6631      /* Invalidate all translations containing code from the cache
6632         block at (rA|0) + rB. */
6633      IRTemp EA   = newTemp(ty);
6634      IRTemp addr = newTemp(ty);
6635      DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
6636      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6637
6638      /* Round EA down to the start of the containing block. */
6639      assign( addr, binop( mkSzOp(ty, Iop_And8),
6640                           mkexpr(EA),
6641                           mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
6642      putGST( PPC_GST_TISTART, mkexpr(addr) );
6643      putGST( PPC_GST_TILEN, mkSzImm(ty, lineszB) );
6644
6645      /* be paranoid ... */
6646      stmt( IRStmt_MBE(Imbe_Fence) );
6647
6648      irsb->jumpkind = Ijk_TInval;
6649      irsb->next     = mkSzImm(ty, nextInsnAddr());
6650      dres->whatNext = Dis_StopHere;
6651      break;
6652   }
6653
6654   default:
6655      vex_printf("dis_cache_manage(ppc)(opc2)\n");
6656      return False;
6657   }
6658   return True;
6659}
6660
6661
6662/*------------------------------------------------------------*/
6663/*--- Floating Point Helpers                               ---*/
6664/*------------------------------------------------------------*/
6665
6666/* --------- Synthesise a 2-bit FPU rounding mode. --------- */
6667/* Produces a value in 0 .. 3, which is encoded as per the type
6668   IRRoundingMode.  PPCRoundingMode encoding is different to
6669   IRRoundingMode, so need to map it.
6670*/
6671static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
6672{
6673/*
6674   rounding mode | PPC | IR
6675   ------------------------
6676   to nearest    | 00  | 00
6677   to zero       | 01  | 11
6678   to +infinity  | 10  | 10
6679   to -infinity  | 11  | 01
6680*/
6681   IRTemp rm_PPC32 = newTemp(Ity_I32);
6682   assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
6683
6684   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
6685   return binop( Iop_Xor32,
6686                 mkexpr(rm_PPC32),
6687                 binop( Iop_And32,
6688                        binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
6689                        mkU32(2) ));
6690}
6691
6692
6693/*------------------------------------------------------------*/
6694/*--- Floating Point Instruction Translation               ---*/
6695/*------------------------------------------------------------*/
6696
6697/*
6698  Floating Point Load Instructions
6699*/
6700static Bool dis_fp_load ( UInt theInstr )
6701{
6702   /* X-Form, D-Form */
6703   UChar opc1      = ifieldOPC(theInstr);
6704   UChar frD_addr  = ifieldRegDS(theInstr);
6705   UChar rA_addr   = ifieldRegA(theInstr);
6706   UChar rB_addr   = ifieldRegB(theInstr);
6707   UInt  opc2      = ifieldOPClo10(theInstr);
6708   UChar b0        = ifieldBIT0(theInstr);
6709   UInt  uimm16    = ifieldUIMM16(theInstr);
6710
6711   Int    simm16 = extend_s_16to32(uimm16);
6712   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6713   IRTemp EA     = newTemp(ty);
6714   IRTemp rA     = newTemp(ty);
6715   IRTemp rB     = newTemp(ty);
6716   IRTemp iHi    = newTemp(Ity_I32);
6717   IRTemp iLo    = newTemp(Ity_I32);
6718
6719   assign( rA, getIReg(rA_addr) );
6720   assign( rB, getIReg(rB_addr) );
6721
6722   /* These are completely straightforward from a rounding and status
6723      bits perspective: no rounding involved and no funny status or CR
6724      bits affected. */
6725
6726   switch (opc1) {
6727   case 0x30: // lfs (Load Float Single, PPC32 p441)
6728      DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6729      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6730      putFReg( frD_addr,
6731               unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6732      break;
6733
6734   case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
6735      if (rA_addr == 0)
6736         return False;
6737      DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6738      assign( EA, ea_rA_simm(rA_addr, simm16) );
6739      putFReg( frD_addr,
6740               unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6741      putIReg( rA_addr, mkexpr(EA) );
6742      break;
6743
6744   case 0x32: // lfd (Load Float Double, PPC32 p437)
6745      DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6746      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6747      putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6748      break;
6749
6750   case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
6751      if (rA_addr == 0)
6752         return False;
6753      DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6754      assign( EA, ea_rA_simm(rA_addr, simm16) );
6755      putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6756      putIReg( rA_addr, mkexpr(EA) );
6757      break;
6758
6759   case 0x1F:
6760      if (b0 != 0) {
6761         vex_printf("dis_fp_load(ppc)(instr,b0)\n");
6762         return False;
6763      }
6764
6765      switch(opc2) {
6766      case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
6767         DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6768         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6769         putFReg( frD_addr, unop( Iop_F32toF64,
6770                                  loadBE(Ity_F32, mkexpr(EA))) );
6771         break;
6772
6773      case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
6774         if (rA_addr == 0)
6775            return False;
6776         DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6777         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6778         putFReg( frD_addr,
6779                  unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6780         putIReg( rA_addr, mkexpr(EA) );
6781         break;
6782
6783      case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
6784         DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6785         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6786         putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6787         break;
6788
6789      case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
6790         if (rA_addr == 0)
6791            return False;
6792         DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6793         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6794         putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6795         putIReg( rA_addr, mkexpr(EA) );
6796         break;
6797
6798      case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
6799         DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6800         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6801         assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
6802         assign( iHi, binop(Iop_Sub32,
6803                            mkU32(0),
6804                            binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
6805         putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
6806                                 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
6807         break;
6808
6809      case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
6810      {
6811         IRTemp dw = newTemp( Ity_I64 );
6812         DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6813         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6814         assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
6815         assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
6816         putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
6817         break;
6818      }
6819
6820      default:
6821         vex_printf("dis_fp_load(ppc)(opc2)\n");
6822         return False;
6823      }
6824      break;
6825
6826   default:
6827      vex_printf("dis_fp_load(ppc)(opc1)\n");
6828      return False;
6829   }
6830   return True;
6831}
6832
6833
6834
6835/*
6836  Floating Point Store Instructions
6837*/
6838static Bool dis_fp_store ( UInt theInstr )
6839{
6840   /* X-Form, D-Form */
6841   UChar opc1      = ifieldOPC(theInstr);
6842   UChar frS_addr  = ifieldRegDS(theInstr);
6843   UChar rA_addr   = ifieldRegA(theInstr);
6844   UChar rB_addr   = ifieldRegB(theInstr);
6845   UInt  opc2      = ifieldOPClo10(theInstr);
6846   UChar b0        = ifieldBIT0(theInstr);
6847   Int   uimm16    = ifieldUIMM16(theInstr);
6848
6849   Int    simm16 = extend_s_16to32(uimm16);
6850   IRTemp frS    = newTemp(Ity_F64);
6851   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6852   IRTemp EA     = newTemp(ty);
6853   IRTemp rA     = newTemp(ty);
6854   IRTemp rB     = newTemp(ty);
6855
6856   assign( frS, getFReg(frS_addr) );
6857   assign( rA,  getIReg(rA_addr) );
6858   assign( rB,  getIReg(rB_addr) );
6859
6860   /* These are straightforward from a status bits perspective: no
6861      funny status or CR bits affected.  For single precision stores,
6862      the values are truncated and denormalised (not rounded) to turn
6863      them into single precision values. */
6864
6865   switch (opc1) {
6866
6867   case 0x34: // stfs (Store Float Single, PPC32 p518)
6868      DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6869      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6870      /* Use Iop_TruncF64asF32 to truncate and possible denormalise
6871         the value to be stored in the correct way, without any
6872         rounding. */
6873      storeBE( mkexpr(EA),
6874               unop(Iop_TruncF64asF32, mkexpr(frS)) );
6875      break;
6876
6877   case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
6878      if (rA_addr == 0)
6879         return False;
6880      DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6881      assign( EA, ea_rA_simm(rA_addr, simm16) );
6882      /* See comment for stfs */
6883      storeBE( mkexpr(EA),
6884               unop(Iop_TruncF64asF32, mkexpr(frS)) );
6885      putIReg( rA_addr, mkexpr(EA) );
6886      break;
6887
6888   case 0x36: // stfd (Store Float Double, PPC32 p513)
6889      DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6890      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6891      storeBE( mkexpr(EA), mkexpr(frS) );
6892      break;
6893
6894   case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
6895      if (rA_addr == 0)
6896         return False;
6897      DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6898      assign( EA, ea_rA_simm(rA_addr, simm16) );
6899      storeBE( mkexpr(EA), mkexpr(frS) );
6900      putIReg( rA_addr, mkexpr(EA) );
6901      break;
6902
6903   case 0x1F:
6904      if (b0 != 0) {
6905         vex_printf("dis_fp_store(ppc)(instr,b0)\n");
6906         return False;
6907      }
6908      switch(opc2) {
6909      case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
6910         DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6911         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6912         /* See note for stfs */
6913         storeBE( mkexpr(EA),
6914                  unop(Iop_TruncF64asF32, mkexpr(frS)) );
6915         break;
6916
6917      case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
6918         if (rA_addr == 0)
6919            return False;
6920         DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6921         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6922         /* See note for stfs */
6923         storeBE( mkexpr(EA),
6924                  unop(Iop_TruncF64asF32, mkexpr(frS)) );
6925         putIReg( rA_addr, mkexpr(EA) );
6926         break;
6927
6928      case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
6929         DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6930         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6931         storeBE( mkexpr(EA), mkexpr(frS) );
6932         break;
6933
6934      case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
6935         if (rA_addr == 0)
6936            return False;
6937         DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6938         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6939         storeBE( mkexpr(EA), mkexpr(frS) );
6940         putIReg( rA_addr, mkexpr(EA) );
6941         break;
6942
6943      case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
6944         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6945         DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6946         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6947         storeBE( mkexpr(EA),
6948                  unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
6949         break;
6950
6951      default:
6952         vex_printf("dis_fp_store(ppc)(opc2)\n");
6953         return False;
6954      }
6955      break;
6956
6957   default:
6958      vex_printf("dis_fp_store(ppc)(opc1)\n");
6959      return False;
6960   }
6961   return True;
6962}
6963
6964
6965
6966/*
6967  Floating Point Arith Instructions
6968*/
6969static Bool dis_fp_arith ( UInt theInstr )
6970{
6971   /* A-Form */
6972   UChar opc1     = ifieldOPC(theInstr);
6973   UChar frD_addr = ifieldRegDS(theInstr);
6974   UChar frA_addr = ifieldRegA(theInstr);
6975   UChar frB_addr = ifieldRegB(theInstr);
6976   UChar frC_addr = ifieldRegC(theInstr);
6977   UChar opc2     = ifieldOPClo5(theInstr);
6978   UChar flag_rC  = ifieldBIT0(theInstr);
6979
6980   IRTemp  frD = newTemp(Ity_F64);
6981   IRTemp  frA = newTemp(Ity_F64);
6982   IRTemp  frB = newTemp(Ity_F64);
6983   IRTemp  frC = newTemp(Ity_F64);
6984   IRExpr* rm  = get_IR_roundingmode();
6985
6986   /* By default, we will examine the results of the operation and set
6987      fpscr[FPRF] accordingly. */
6988   Bool set_FPRF = True;
6989
6990   /* By default, if flag_RC is set, we will clear cr1 after the
6991      operation.  In reality we should set cr1 to indicate the
6992      exception status of the operation, but since we're not
6993      simulating exceptions, the exception status will appear to be
6994      zero.  Hence cr1 should be cleared if this is a . form insn. */
6995   Bool clear_CR1 = True;
6996
6997   assign( frA, getFReg(frA_addr));
6998   assign( frB, getFReg(frB_addr));
6999   assign( frC, getFReg(frC_addr));
7000
7001   switch (opc1) {
7002   case 0x3B:
7003      switch (opc2) {
7004      case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
7005         if (frC_addr != 0)
7006            return False;
7007         DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7008             frD_addr, frA_addr, frB_addr);
7009         assign( frD, triop( Iop_DivF64r32,
7010                             rm, mkexpr(frA), mkexpr(frB) ));
7011         break;
7012
7013      case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
7014         if (frC_addr != 0)
7015            return False;
7016         DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7017             frD_addr, frA_addr, frB_addr);
7018         assign( frD, triop( Iop_SubF64r32,
7019                             rm, mkexpr(frA), mkexpr(frB) ));
7020         break;
7021
7022      case 0x15: // fadds (Floating Add Single, PPC32 p401)
7023         if (frC_addr != 0)
7024            return False;
7025         DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7026             frD_addr, frA_addr, frB_addr);
7027         assign( frD, triop( Iop_AddF64r32,
7028                             rm, mkexpr(frA), mkexpr(frB) ));
7029         break;
7030
7031      case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
7032         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
7033         if (frA_addr != 0 || frC_addr != 0)
7034            return False;
7035         DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
7036             frD_addr, frB_addr);
7037         // however illogically, on ppc970 this insn behaves identically
7038         // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
7039         assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
7040         break;
7041
7042      case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
7043         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7044         if (frA_addr != 0 || frC_addr != 0)
7045            return False;
7046         DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
7047             frD_addr, frB_addr);
7048         { IRExpr* ieee_one
7049              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
7050           assign( frD, triop( Iop_DivF64r32,
7051                               rm,
7052                               ieee_one, mkexpr(frB) ));
7053         }
7054         break;
7055
7056      case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
7057         if (frB_addr != 0)
7058            return False;
7059         DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7060             frD_addr, frA_addr, frC_addr);
7061         assign( frD, triop( Iop_MulF64r32,
7062                             rm, mkexpr(frA), mkexpr(frC) ));
7063         break;
7064
7065      case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
7066         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7067         // Undocumented instruction?
7068         if (frA_addr != 0 || frC_addr != 0)
7069            return False;
7070         DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
7071             frD_addr, frB_addr);
7072         assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
7073         break;
7074
7075      default:
7076         vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
7077         return False;
7078      }
7079      break;
7080
7081   case 0x3F:
7082      switch (opc2) {
7083      case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
7084         if (frC_addr != 0)
7085            return False;
7086         DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7087             frD_addr, frA_addr, frB_addr);
7088         assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
7089         break;
7090
7091      case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
7092         if (frC_addr != 0)
7093            return False;
7094         DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7095             frD_addr, frA_addr, frB_addr);
7096         assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
7097         break;
7098
7099      case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
7100         if (frC_addr != 0)
7101            return False;
7102         DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7103             frD_addr, frA_addr, frB_addr);
7104         assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
7105         break;
7106
7107      case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
7108         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
7109         if (frA_addr != 0 || frC_addr != 0)
7110            return False;
7111         DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
7112             frD_addr, frB_addr);
7113         assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
7114         break;
7115
7116      case 0x17: { // fsel (Floating Select, PPC32 p426)
7117         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7118         IRTemp cc    = newTemp(Ity_I32);
7119         IRTemp cc_b0 = newTemp(Ity_I32);
7120
7121         DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7122             frD_addr, frA_addr, frC_addr, frB_addr);
7123
7124         // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
7125         // => GT|EQ == (cc & 0x1 == 0)
7126         assign( cc, binop(Iop_CmpF64, mkexpr(frA),
7127                                       IRExpr_Const(IRConst_F64(0))) );
7128         assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
7129
7130         // frD = (frA >= 0.0) ? frC : frB
7131         //     = (cc_b0 == 0) ? frC : frB
7132         assign( frD,
7133                 IRExpr_Mux0X(
7134                    unop(Iop_1Uto8,
7135                         binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0))),
7136                    mkexpr(frB),
7137                    mkexpr(frC) ));
7138
7139         /* One of the rare ones which don't mess with FPRF */
7140         set_FPRF = False;
7141         break;
7142      }
7143
7144      case 0x18: // fre (Floating Reciprocal Estimate)
7145         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7146         // Note: unclear whether this insn really exists or not
7147         // ppc970 doesn't have it, but POWER5 does
7148         if (frA_addr != 0 || frC_addr != 0)
7149            return False;
7150         DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
7151             frD_addr, frB_addr);
7152         { IRExpr* ieee_one
7153              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
7154           assign( frD, triop( Iop_DivF64,
7155                               rm,
7156                               ieee_one, mkexpr(frB) ));
7157         }
7158         break;
7159
7160      case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
7161         if (frB_addr != 0)
7162            vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
7163         DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7164             frD_addr, frA_addr, frC_addr);
7165         assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
7166         break;
7167
7168      case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
7169         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7170         if (frA_addr != 0 || frC_addr != 0)
7171            return False;
7172         DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
7173             frD_addr, frB_addr);
7174         assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
7175         break;
7176
7177      default:
7178         vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
7179         return False;
7180      }
7181      break;
7182
7183   default:
7184      vex_printf("dis_fp_arith(ppc)(opc1)\n");
7185      return False;
7186   }
7187
7188   putFReg( frD_addr, mkexpr(frD) );
7189
7190   if (set_FPRF) {
7191      // XXX XXX XXX FIXME
7192      // set FPRF from frD
7193   }
7194
7195   if (flag_rC && clear_CR1) {
7196      putCR321( 1, mkU8(0) );
7197      putCR0( 1, mkU8(0) );
7198   }
7199
7200   return True;
7201}
7202
7203
7204
7205/*
7206  Floating Point Mult-Add Instructions
7207*/
7208static Bool dis_fp_multadd ( UInt theInstr )
7209{
7210   /* A-Form */
7211   UChar opc1     = ifieldOPC(theInstr);
7212   UChar frD_addr = ifieldRegDS(theInstr);
7213   UChar frA_addr = ifieldRegA(theInstr);
7214   UChar frB_addr = ifieldRegB(theInstr);
7215   UChar frC_addr = ifieldRegC(theInstr);
7216   UChar opc2     = ifieldOPClo5(theInstr);
7217   UChar flag_rC  = ifieldBIT0(theInstr);
7218
7219   IRTemp  frD = newTemp(Ity_F64);
7220   IRTemp  frA = newTemp(Ity_F64);
7221   IRTemp  frB = newTemp(Ity_F64);
7222   IRTemp  frC = newTemp(Ity_F64);
7223   IRTemp  rmt = newTemp(Ity_I32);
7224   IRExpr* rm;
7225
7226   /* By default, we will examine the results of the operation and set
7227      fpscr[FPRF] accordingly. */
7228   Bool set_FPRF = True;
7229
7230   /* By default, if flag_RC is set, we will clear cr1 after the
7231      operation.  In reality we should set cr1 to indicate the
7232      exception status of the operation, but since we're not
7233      simulating exceptions, the exception status will appear to be
7234      zero.  Hence cr1 should be cleared if this is a . form insn. */
7235   Bool clear_CR1 = True;
7236
7237   /* Bind the rounding mode expression to a temp; there's no
7238      point in creating gratuitous CSEs, as we know we'll need
7239      to use it twice. */
7240   assign( rmt, get_IR_roundingmode() );
7241   rm = mkexpr(rmt);
7242
7243   assign( frA, getFReg(frA_addr));
7244   assign( frB, getFReg(frB_addr));
7245   assign( frC, getFReg(frC_addr));
7246
7247   /* The rounding in this is all a bit dodgy.  The idea is to only do
7248      one rounding.  That clearly isn't achieveable without dedicated
7249      four-input IR primops, although in the single precision case we
7250      can sort-of simulate it by doing the inner multiply in double
7251      precision.
7252
7253      In the negated cases, the negation happens after rounding. */
7254
7255   switch (opc1) {
7256   case 0x3B:
7257      switch (opc2) {
7258      case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
7259         DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7260             frD_addr, frA_addr, frC_addr, frB_addr);
7261         assign( frD, qop( Iop_MSubF64r32, rm,
7262                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
7263         break;
7264
7265      case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
7266         DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7267             frD_addr, frA_addr, frC_addr, frB_addr);
7268         assign( frD, qop( Iop_MAddF64r32, rm,
7269                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
7270         break;
7271
7272      case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
7273         DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7274             frD_addr, frA_addr, frC_addr, frB_addr);
7275         assign( frD, unop( Iop_NegF64,
7276                      qop( Iop_MSubF64r32, rm,
7277                           mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
7278         break;
7279
7280      case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
7281         DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7282             frD_addr, frA_addr, frC_addr, frB_addr);
7283         assign( frD, unop( Iop_NegF64,
7284                      qop( Iop_MAddF64r32, rm,
7285                           mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
7286         break;
7287
7288      default:
7289         vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
7290         return False;
7291      }
7292      break;
7293
7294   case 0x3F:
7295      switch (opc2) {
7296      case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
7297         DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7298             frD_addr, frA_addr, frC_addr, frB_addr);
7299         assign( frD, qop( Iop_MSubF64, rm,
7300                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
7301         break;
7302
7303      case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
7304         DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7305             frD_addr, frA_addr, frC_addr, frB_addr);
7306         assign( frD, qop( Iop_MAddF64, rm,
7307                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
7308         break;
7309
7310      case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
7311         DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7312             frD_addr, frA_addr, frC_addr, frB_addr);
7313         assign( frD, unop( Iop_NegF64,
7314                      qop( Iop_MSubF64, rm,
7315                           mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
7316         break;
7317
7318      case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
7319         DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7320             frD_addr, frA_addr, frC_addr, frB_addr);
7321         assign( frD, unop( Iop_NegF64,
7322                      qop( Iop_MAddF64, rm,
7323                           mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
7324         break;
7325
7326      default:
7327         vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
7328         return False;
7329      }
7330      break;
7331
7332   default:
7333      vex_printf("dis_fp_multadd(ppc)(opc1)\n");
7334      return False;
7335   }
7336
7337   putFReg( frD_addr, mkexpr(frD) );
7338
7339   if (set_FPRF) {
7340      // XXX XXX XXX FIXME
7341      // set FPRF from frD
7342   }
7343
7344   if (flag_rC && clear_CR1) {
7345      putCR321( 1, mkU8(0) );
7346      putCR0( 1, mkU8(0) );
7347   }
7348
7349   return True;
7350}
7351
7352/*
7353 * fe_flag is set to 1 if any of the following conditions occurs:
7354 *  - The floating-point operand in register FRB is a Zero, a
7355 *    NaN, an Infinity, or a negative value.
7356 *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
7357 *  Otherwise fe_flag is set to 0.
7358 *
7359 * fg_flag is set to 1 if either of the following conditions occurs.
7360 *   - The floating-point operand in register FRB is a Zero, an
7361 *     Infinity, or a denormalized value.
7362 *  Otherwise fg_flag is set to 0.
7363 *
7364 */
7365static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
7366{
7367   // The following temps are for holding intermediate results
7368   IRTemp e_b = newTemp(Ity_I32);
7369   IRExpr * fe_flag,  * fg_flag;
7370   IRTemp frB_exp_shR = newTemp(Ity_I32);
7371   UInt bias = sp? 127 : 1023;
7372   IRExpr * frbNaN, * frbDenorm, * frBNeg;
7373   IRExpr * eb_LTE;
7374   IRTemp  frbZero_tmp = newTemp(Ity_I1);
7375   IRTemp  frbInf_tmp = newTemp(Ity_I1);
7376   *fe_flag_tmp = newTemp(Ity_I32);
7377   *fg_flag_tmp = newTemp(Ity_I32);
7378   assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
7379   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
7380
7381   //////////////////  fe_flag tests BEGIN //////////////////////
7382   /* We first do all tests that may result in setting fe_flag to '1'.
7383    * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
7384    * for details.)
7385    */
7386   frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
7387   assign( frbInf_tmp, is_Inf(frB_Int, sp) );
7388   assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
7389   {
7390      // Test_value = -970 for double precision
7391      UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
7392      eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
7393   }
7394   frBNeg = binop( Iop_CmpEQ32,
7395                   binop( Iop_Shr32,
7396                          sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
7397                          mkU8( 31 ) ),
7398                   mkU32( 1 ) );
7399   //////////////////  fe_flag tests END //////////////////////
7400
7401   //////////////////  fg_flag tests BEGIN //////////////////////
7402   /*
7403    * The following tests were already performed above in the fe_flag
7404    * tests.  So these conditions will result in both fe_ and fg_ flags
7405    * being set.
7406    *   - Test if FRB is Zero
7407    *   - Test if FRB is an Infinity
7408    */
7409
7410   /*
7411    * Test if FRB holds a denormalized value.  A denormalized value is one where
7412    * the exp is 0 and the fraction is non-zero.
7413    */
7414   if (sp) {
7415      IRTemp frac_part = newTemp(Ity_I32);
7416      assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
7417      frbDenorm
7418               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
7419                         binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
7420   } else {
7421      IRExpr * hi32, * low32, * fraction_is_nonzero;
7422      IRTemp frac_part = newTemp(Ity_I64);
7423
7424      assign( frac_part, FP_FRAC_PART(frB_Int) );
7425      hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
7426      low32 = unop( Iop_64to32, mkexpr( frac_part ) );
7427      fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
7428                                                mkU32( 0 ) );
7429      frbDenorm
7430               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
7431                         fraction_is_nonzero );
7432   }
7433   //////////////////  fg_flag tests END //////////////////////
7434
7435   /////////////////////////
7436   fe_flag = mkOR1( mkexpr( frbZero_tmp ),
7437                    mkOR1( frbNaN,
7438                           mkOR1( mkexpr( frbInf_tmp ),
7439                                  mkOR1( frBNeg, eb_LTE ) ) ) );
7440
7441   fe_flag = unop(Iop_1Uto32, fe_flag);
7442
7443   fg_flag = mkOR1( mkexpr( frbZero_tmp ),
7444                    mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
7445   fg_flag = unop(Iop_1Uto32, fg_flag);
7446   assign (*fg_flag_tmp, fg_flag);
7447   assign (*fe_flag_tmp, fe_flag);
7448}
7449/*
7450 * fe_flag is set to 1 if any of the following conditions occurs:
7451 *  - The double-precision floating-point operand in register FRA is a NaN or an
7452 *    Infinity.
7453 *  - The double-precision floating-point operand in register FRB is a Zero, a
7454 *    NaN, or an Infinity.
7455 *  - e_b is less than or equal to -1022.
7456 *  - e_b is greater than or equal to 1021.
7457 *  - The double-precision floating-point operand in register FRA is not a zero
7458 *    and the difference, e_a - e_b, is greater than or equal to 1023.
7459 *  - The double-precision floating-point operand in register FRA is not a zero
7460 *    and the difference, e_a - e_b, is less than or equal to -1021.
7461 *  - The double-precision floating-point operand in register FRA is not a zero
7462 *    and e_a is less than or equal to -970
7463 *  Otherwise fe_flag is set to 0.
7464 *
7465 * fg_flag is set to 1 if either of the following conditions occurs.
7466 *   - The double-precision floating-point operand in register FRA is an Infinity.
7467 *   - The double-precision floating-point operand in register FRB is a Zero, an
7468 *     Infinity, or a denormalized value.
7469 *  Otherwise fg_flag is set to 0.
7470 *
7471 */
7472static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
7473{
7474   // The following temps are for holding intermediate results
7475   IRTemp e_a = newTemp(Ity_I32);
7476   IRTemp e_b = newTemp(Ity_I32);
7477   IRTemp frA_exp_shR = newTemp(Ity_I32);
7478   IRTemp frB_exp_shR = newTemp(Ity_I32);
7479
7480   UInt bias = sp? 127 : 1023;
7481   *fe_flag_tmp = newTemp(Ity_I32);
7482   *fg_flag_tmp = newTemp(Ity_I32);
7483
7484   /* The following variables hold boolean results from tests
7485    * that are OR'ed together for setting the fe_ and fg_ flags.
7486    * For some cases, the booleans are used more than once, so
7487    * I make those IRTemp's instead of IRExpr's.
7488    */
7489   IRExpr * fraNaN, * frbNaN, * frbDenorm;
7490   IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
7491   IRTemp  fraInf_tmp = newTemp(Ity_I1);
7492   IRTemp  frbZero_tmp = newTemp(Ity_I1);
7493   IRTemp  frbInf_tmp = newTemp(Ity_I1);
7494   IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
7495
7496/* The following are the flags that are set by OR'ing the results of
7497 * all the tests done for tdiv.  These flags are the input to the specified CR.
7498 */
7499   IRExpr * fe_flag, * fg_flag;
7500
7501   // Create temps that will be used throughout the following tests.
7502   assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
7503   assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
7504   /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
7505   assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
7506   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
7507
7508
7509   //////////////////  fe_flag tests BEGIN //////////////////////
7510   /* We first do all tests that may result in setting fe_flag to '1'. */
7511
7512   /*
7513    * Test if the double-precision floating-point operand in register FRA is
7514    * a NaN:
7515    */
7516   fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
7517   /*
7518    * Test if the double-precision floating-point operand in register FRA is
7519    * an Infinity.
7520    */
7521   assign(fraInf_tmp, is_Inf(frA_int, sp));
7522
7523   /*
7524    * Test if the double-precision floating-point operand in register FRB is
7525    * a NaN:
7526    */
7527   frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
7528   /*
7529    * Test if the double-precision floating-point operand in register FRB is
7530    * an Infinity.
7531    */
7532   assign( frbInf_tmp, is_Inf(frB_int, sp) );
7533   /*
7534    * Test if the double-precision floating-point operand in register FRB is
7535    * a Zero.
7536    */
7537   assign( frbZero_tmp, is_Zero(frB_int, sp) );
7538
7539   /*
7540    * Test if e_b <= -1022 for double precision;
7541    * or e_b <= -126 for single precision
7542    */
7543   {
7544      UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
7545      eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
7546   }
7547
7548   /*
7549    * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
7550    * or e_b >= -125 (125 < e_b) for single precision
7551    */
7552   {
7553      Int test_value = sp ? 125 : 1021;
7554      eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
7555   }
7556
7557   /*
7558    * Test if FRA != Zero and (e_a - e_b) >= bias
7559    */
7560   assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
7561   ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
7562                       binop( Iop_CmpLT32S, mkU32( bias ),
7563                              binop( Iop_Sub32, mkexpr( e_a ),
7564                                     mkexpr( e_b ) ) ) );
7565
7566   /*
7567    * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
7568    */
7569   {
7570      UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
7571
7572      ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
7573                          binop( Iop_CmpLE32S,
7574                                 binop( Iop_Sub32,
7575                                        mkexpr( e_a ),
7576                                        mkexpr( e_b ) ),
7577                                        mkU32( test_value ) ) );
7578   }
7579
7580   /*
7581    * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
7582    */
7583   {
7584      UInt test_value = 0xfffffc36;  //Int test_value = -970;
7585
7586      ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
7587                                                        mkexpr( e_a ),
7588                                                        mkU32( test_value ) ) );
7589   }
7590   //////////////////  fe_flag tests END //////////////////////
7591
7592   //////////////////  fg_flag tests BEGIN //////////////////////
7593   /*
7594    * The following tests were already performed above in the fe_flag
7595    * tests.  So these conditions will result in both fe_ and fg_ flags
7596    * being set.
7597    *   - Test if FRA is an Infinity
7598    *   - Test if FRB ix Zero
7599    *   - Test if FRB is an Infinity
7600    */
7601
7602   /*
7603    * Test if FRB holds a denormalized value.  A denormalized value is one where
7604    * the exp is 0 and the fraction is non-zero.
7605    */
7606   {
7607      IRExpr * fraction_is_nonzero;
7608
7609      if (sp) {
7610         fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
7611                                      mkU32( 0 ) );
7612      } else {
7613         IRExpr * hi32, * low32;
7614         IRTemp frac_part = newTemp(Ity_I64);
7615         assign( frac_part, FP_FRAC_PART(frB_int) );
7616
7617         hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
7618         low32 = unop( Iop_64to32, mkexpr( frac_part ) );
7619         fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
7620                                      mkU32( 0 ) );
7621      }
7622      frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
7623                                 mkU32( 0x0 ) ), fraction_is_nonzero );
7624
7625   }
7626   //////////////////  fg_flag tests END //////////////////////
7627
7628   fe_flag
7629   = mkOR1(
7630            fraNaN,
7631            mkOR1(
7632                   mkexpr( fraInf_tmp ),
7633                   mkOR1(
7634                          mkexpr( frbZero_tmp ),
7635                          mkOR1(
7636                                 frbNaN,
7637                                 mkOR1(
7638                                        mkexpr( frbInf_tmp ),
7639                                        mkOR1( eb_LTE,
7640                                               mkOR1( eb_GTE,
7641                                                      mkOR1( ea_eb_GTE,
7642                                                             mkOR1( ea_eb_LTE,
7643                                                                    ea_LTE ) ) ) ) ) ) ) ) );
7644
7645   fe_flag = unop(Iop_1Uto32, fe_flag);
7646
7647   fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
7648                                                 mkOR1( mkexpr( frbInf_tmp ),
7649                                                        frbDenorm ) ) );
7650   fg_flag = unop(Iop_1Uto32, fg_flag);
7651   assign(*fe_flag_tmp, fe_flag);
7652   assign(*fg_flag_tmp, fg_flag);
7653}
7654
7655/* See description for _do_fp_tdiv() above. */
7656static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
7657{
7658   IRTemp  fe_flag, fg_flag;
7659   /////////////////////////
7660   /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
7661    * where fl_flag == 1 on ppc64.
7662    */
7663   IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
7664   fe_flag = fg_flag = IRTemp_INVALID;
7665   _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
7666   return binop( Iop_Or32,
7667                 binop( Iop_Or32,
7668                        binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
7669                        binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
7670                 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
7671}
7672
7673static Bool dis_fp_tests ( UInt theInstr )
7674{
7675   UChar opc1     = ifieldOPC(theInstr);
7676   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
7677   UChar frB_addr = ifieldRegB(theInstr);
7678   UChar b0       = ifieldBIT0(theInstr);
7679   UInt  opc2     = ifieldOPClo10(theInstr);
7680   IRTemp frB_I64     = newTemp(Ity_I64);
7681
7682   if (opc1 != 0x3F || b0 != 0 ){
7683      vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
7684      return False;
7685   }
7686   assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
7687
7688   switch (opc2) {
7689      case 0x080: // ftdiv
7690      {
7691         UChar frA_addr = ifieldRegA(theInstr);
7692         IRTemp frA_I64     = newTemp(Ity_I64);
7693         UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
7694         if (b21to22 != 0 ) {
7695            vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
7696            return False;
7697         }
7698
7699         assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
7700         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
7701
7702         DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7703         break;
7704      }
7705      case 0x0A0: // ftsqrt
7706      {
7707         IRTemp flags = newTemp(Ity_I32);
7708         IRTemp  fe_flag, fg_flag;
7709         fe_flag = fg_flag = IRTemp_INVALID;
7710         UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
7711         if ( b18to22 != 0) {
7712            vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
7713            return False;
7714         }
7715         DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
7716         do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
7717         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
7718          * where fl_flag == 1 on ppc64.
7719          */
7720         assign( flags,
7721                 binop( Iop_Or32,
7722                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
7723                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
7724                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
7725         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
7726         break;
7727      }
7728
7729      default:
7730         vex_printf("dis_fp_tests(ppc)(opc2)\n");
7731         return False;
7732
7733   }
7734   return True;
7735}
7736
7737/*
7738  Floating Point Compare Instructions
7739*/
7740static Bool dis_fp_cmp ( UInt theInstr )
7741{
7742   /* X-Form */
7743   UChar opc1     = ifieldOPC(theInstr);
7744   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
7745   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
7746   UChar frA_addr = ifieldRegA(theInstr);
7747   UChar frB_addr = ifieldRegB(theInstr);
7748   UInt  opc2     = ifieldOPClo10(theInstr);
7749   UChar b0       = ifieldBIT0(theInstr);
7750
7751   IRTemp ccIR    = newTemp(Ity_I32);
7752   IRTemp ccPPC32 = newTemp(Ity_I32);
7753
7754   IRTemp frA     = newTemp(Ity_F64);
7755   IRTemp frB     = newTemp(Ity_F64);
7756
7757   if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
7758      vex_printf("dis_fp_cmp(ppc)(instr)\n");
7759      return False;
7760   }
7761
7762   assign( frA, getFReg(frA_addr));
7763   assign( frB, getFReg(frB_addr));
7764
7765   assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
7766
7767   /* Map compare result from IR to PPC32 */
7768   /*
7769     FP cmp result | PPC | IR
7770     --------------------------
7771     UN            | 0x1 | 0x45
7772     EQ            | 0x2 | 0x40
7773     GT            | 0x4 | 0x00
7774     LT            | 0x8 | 0x01
7775   */
7776
7777   // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
7778   //                    | ((ccIR ^ (ccIR>>6)) & 1)
7779   assign(
7780      ccPPC32,
7781      binop(
7782         Iop_Shl32,
7783         mkU32(1),
7784         unop(
7785            Iop_32to8,
7786            binop(
7787               Iop_Or32,
7788               binop(
7789                  Iop_And32,
7790                  unop(
7791                     Iop_Not32,
7792                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
7793                  ),
7794                  mkU32(2)
7795               ),
7796               binop(
7797                  Iop_And32,
7798                  binop(
7799                     Iop_Xor32,
7800                     mkexpr(ccIR),
7801                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
7802                  ),
7803                  mkU32(1)
7804               )
7805            )
7806         )
7807      )
7808   );
7809
7810   putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
7811
7812   /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
7813      putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
7814   */
7815   // XXX XXX XXX FIXME
7816   // Also write the result into FPRF (it's not entirely clear how)
7817
7818   /* Note: Differences between fcmpu and fcmpo are only in exception
7819      flag settings, which aren't supported anyway. */
7820   switch (opc2) {
7821   case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
7822      DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7823      break;
7824   case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
7825      DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7826      break;
7827   default:
7828      vex_printf("dis_fp_cmp(ppc)(opc2)\n");
7829      return False;
7830   }
7831   return True;
7832}
7833
7834
7835
7836/*
7837  Floating Point Rounding/Conversion Instructions
7838*/
7839static Bool dis_fp_round ( UInt theInstr )
7840{
7841   /* X-Form */
7842   UChar opc1     = ifieldOPC(theInstr);
7843   UChar b16to20  = ifieldRegA(theInstr);
7844   UChar frD_addr = ifieldRegDS(theInstr);
7845   UChar frB_addr = ifieldRegB(theInstr);
7846   UInt  opc2     = ifieldOPClo10(theInstr);
7847   UChar flag_rC  = ifieldBIT0(theInstr);
7848
7849   IRTemp  frD     = newTemp(Ity_F64);
7850   IRTemp  frB     = newTemp(Ity_F64);
7851   IRTemp  r_tmp32 = newTemp(Ity_I32);
7852   IRTemp  r_tmp64 = newTemp(Ity_I64);
7853   IRExpr* rm      = get_IR_roundingmode();
7854
7855   /* By default, we will examine the results of the operation and set
7856      fpscr[FPRF] accordingly. */
7857   Bool set_FPRF = True;
7858
7859   /* By default, if flag_RC is set, we will clear cr1 after the
7860      operation.  In reality we should set cr1 to indicate the
7861      exception status of the operation, but since we're not
7862      simulating exceptions, the exception status will appear to be
7863      zero.  Hence cr1 should be cleared if this is a . form insn. */
7864   Bool clear_CR1 = True;
7865   if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
7866      vex_printf("dis_fp_round(ppc)(instr)\n");
7867      return False;
7868   }
7869
7870   assign( frB, getFReg(frB_addr));
7871   if (opc1 == 0x3B) {
7872      /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
7873       * they're very similar to the other instructions handled here, but have
7874       * a different primary opcode.
7875       */
7876      switch (opc2) {
7877         case 0x34E: // fcfids (Float convert from signed DWord to single precision)
7878            DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7879            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7880            assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
7881                                                              mkexpr( r_tmp64 ) ) ) );
7882            goto putFR;
7883
7884         case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
7885            DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7886            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7887            assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
7888            goto putFR;
7889      }
7890   }
7891
7892
7893   switch (opc2) {
7894   case 0x00C: // frsp (Float Round to Single, PPC32 p423)
7895      DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7896      assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
7897      break;
7898
7899   case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
7900      DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7901      assign( r_tmp32,
7902              binop(Iop_F64toI32S, rm, mkexpr(frB)) );
7903      assign( frD, unop( Iop_ReinterpI64asF64,
7904                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
7905      /* FPRF is undefined after fctiw.  Leave unchanged. */
7906      set_FPRF = False;
7907      break;
7908
7909   case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
7910      DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7911      assign( r_tmp32,
7912              binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
7913      assign( frD, unop( Iop_ReinterpI64asF64,
7914                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
7915      /* FPRF is undefined after fctiwz.  Leave unchanged. */
7916      set_FPRF = False;
7917      break;
7918
7919   case 0x08F: case 0x08E: // fctiwu[z]
7920      DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
7921               flag_rC ? ".":"", frD_addr, frB_addr);
7922      assign( r_tmp32,
7923              binop( Iop_F64toI32U,
7924                     opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
7925                     mkexpr( frB ) ) );
7926      assign( frD, unop( Iop_ReinterpI64asF64,
7927                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
7928      /* FPRF is undefined after fctiwz.  Leave unchanged. */
7929      set_FPRF = False;
7930      break;
7931
7932
7933   case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
7934      DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7935      assign( r_tmp64,
7936              binop(Iop_F64toI64S, rm, mkexpr(frB)) );
7937      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
7938      /* FPRF is undefined after fctid.  Leave unchanged. */
7939      set_FPRF = False;
7940      break;
7941
7942   case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
7943      DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7944      assign( r_tmp64,
7945              binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
7946      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
7947      /* FPRF is undefined after fctidz.  Leave unchanged. */
7948      set_FPRF = False;
7949      break;
7950
7951   case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
7952   {
7953      DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
7954               flag_rC ? ".":"", frD_addr, frB_addr);
7955      assign( r_tmp64,
7956              binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
7957      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
7958      /* FPRF is undefined after fctidz.  Leave unchanged. */
7959      set_FPRF = False;
7960      break;
7961   }
7962   case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
7963      DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7964      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7965      assign( frD,
7966              binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
7967      break;
7968
7969   case 0x3CE: // fcfidu (Float convert from unsigned DWord)
7970      DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7971      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7972      assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
7973      break;
7974
7975   case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
7976      switch(opc2) {
7977      case 0x188: // frin (Floating Round to Integer Nearest)
7978         DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7979         assign( r_tmp64,
7980                 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
7981         break;
7982      case 0x1A8: // friz (Floating Round to Integer Toward Zero)
7983         DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7984         assign( r_tmp64,
7985                 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
7986         break;
7987      case 0x1C8: // frip (Floating Round to Integer Plus)
7988         DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7989         assign( r_tmp64,
7990                 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
7991         break;
7992      case 0x1E8: // frim (Floating Round to Integer Minus)
7993         DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7994         assign( r_tmp64,
7995                 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
7996         break;
7997      }
7998
7999      /* don't use the rounded integer if frB is outside -9e18..9e18 */
8000      /* F64 has only log10(2**52) significant digits anyway */
8001      /* need to preserve sign of zero */
8002      /*   frD = (fabs(frB) > 9e18) ? frB :
8003               (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
8004      assign(frD, IRExpr_Mux0X( unop(Iop_32to8,
8005                                     binop(Iop_CmpF64,
8006                                           IRExpr_Const(IRConst_F64(9e18)),
8007                                           unop(Iop_AbsF64, mkexpr(frB)))),
8008                                IRExpr_Mux0X(unop(Iop_32to8,
8009                                                  binop(Iop_Shr32,
8010                                                        unop(Iop_64HIto32,
8011                                                             unop(Iop_ReinterpF64asI64,
8012                                                                  mkexpr(frB))), mkU8(31))),
8013                                             binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ),
8014                                             unop(Iop_NegF64,
8015                                                  unop( Iop_AbsF64,
8016                                                        binop(Iop_I64StoF64, mkU32(0),
8017                                                              mkexpr(r_tmp64)) )) ),
8018                                mkexpr(frB)));
8019      break;
8020
8021   default:
8022      vex_printf("dis_fp_round(ppc)(opc2)\n");
8023      return False;
8024   }
8025putFR:
8026   putFReg( frD_addr, mkexpr(frD) );
8027
8028   if (set_FPRF) {
8029      // XXX XXX XXX FIXME
8030      // set FPRF from frD
8031   }
8032
8033   if (flag_rC && clear_CR1) {
8034      putCR321( 1, mkU8(0) );
8035      putCR0( 1, mkU8(0) );
8036   }
8037
8038   return True;
8039}
8040
8041/*
8042  Floating Point Pair Instructions
8043*/
8044static Bool dis_fp_pair ( UInt theInstr )
8045{
8046   /* X-Form/DS-Form */
8047   UChar  opc1         = ifieldOPC(theInstr);
8048   UChar  frT_hi_addr  = ifieldRegDS(theInstr);
8049   UChar  frT_lo_addr  = frT_hi_addr + 1;
8050   UChar  rA_addr      = ifieldRegA(theInstr);
8051   UChar  rB_addr      = ifieldRegB(theInstr);
8052   UInt  uimm16        = ifieldUIMM16(theInstr);
8053   Int    simm16       = extend_s_16to32(uimm16);
8054   UInt   opc2         = ifieldOPClo10(theInstr);
8055   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
8056   IRTemp EA_hi        = newTemp(ty);
8057   IRTemp EA_lo        = newTemp(ty);
8058   IRTemp frT_hi       = newTemp(Ity_F64);
8059   IRTemp frT_lo       = newTemp(Ity_F64);
8060   UChar b0            = ifieldBIT0(theInstr);
8061   Bool is_load        = 0;
8062
8063   if ((frT_hi_addr %2) != 0) {
8064      vex_printf("dis_fp_pair(ppc) : odd frT register\n");
8065      return False;
8066   }
8067
8068   switch (opc1) {
8069   case 0x1F: // register offset
8070      switch(opc2) {
8071      case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
8072         DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
8073         is_load = 1;
8074         break;
8075      case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
8076         DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
8077         break;
8078      default:
8079         vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
8080         return False;
8081      }
8082
8083      if (b0 != 0) {
8084         vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
8085         return False;
8086      }
8087      assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
8088      break;
8089   case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
8090      DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
8091      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
8092      is_load = 1;
8093      break;
8094   case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
8095      DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
8096      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
8097      break;
8098   default:   // immediate offset
8099      vex_printf("dis_fp_pair(ppc)(instr)\n");
8100      return False;
8101   }
8102
8103   if (mode64)
8104      assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
8105   else
8106      assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
8107
8108   assign( frT_hi, getFReg(frT_hi_addr) );
8109   assign( frT_lo, getFReg(frT_lo_addr) );
8110
8111   if (is_load) {
8112      putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) );
8113      putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) );
8114   } else {
8115      storeBE( mkexpr(EA_hi), mkexpr(frT_hi) );
8116      storeBE( mkexpr(EA_lo), mkexpr(frT_lo) );
8117   }
8118
8119   return True;
8120}
8121
8122
8123/*
8124  Floating Point Move Instructions
8125*/
8126static Bool dis_fp_move ( UInt theInstr )
8127{
8128   /* X-Form */
8129   UChar opc1     = ifieldOPC(theInstr);
8130   UChar frD_addr = ifieldRegDS(theInstr);
8131   UChar frA_addr = ifieldRegA(theInstr);
8132   UChar frB_addr = ifieldRegB(theInstr);
8133   UInt  opc2     = ifieldOPClo10(theInstr);
8134   UChar flag_rC  = ifieldBIT0(theInstr);
8135
8136   IRTemp frD = newTemp(Ity_F64);
8137   IRTemp frB = newTemp(Ity_F64);
8138   IRTemp itmpB = newTemp(Ity_F64);
8139   IRTemp frA;
8140   IRTemp signA;
8141   IRTemp hiD;
8142
8143   if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
8144      vex_printf("dis_fp_move(ppc)(instr)\n");
8145      return False;
8146   }
8147
8148   assign( frB, getFReg(frB_addr));
8149
8150   switch (opc2) {
8151   case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
8152      DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
8153          frB_addr);
8154      signA = newTemp(Ity_I32);
8155      hiD = newTemp(Ity_I32);
8156      itmpB = newTemp(Ity_I64);
8157      frA = newTemp(Ity_F64);
8158      assign( frA, getFReg(frA_addr) );
8159
8160      /* get A's sign bit */
8161      assign(signA, binop(Iop_And32,
8162                          unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
8163                                                  mkexpr(frA))),
8164                          mkU32(0x80000000)) );
8165
8166      assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
8167
8168      /* mask off B's sign bit and or in A's sign bit */
8169      assign(hiD, binop(Iop_Or32,
8170                        binop(Iop_And32,
8171                              unop(Iop_64HIto32,
8172                                   mkexpr(itmpB)),  /* frB's high 32 bits */
8173                              mkU32(0x7fffffff)),
8174                        mkexpr(signA)) );
8175
8176      /* combine hiD/loB into frD */
8177      assign( frD, unop(Iop_ReinterpI64asF64,
8178                        binop(Iop_32HLto64,
8179                              mkexpr(hiD),
8180                              unop(Iop_64to32,
8181                                   mkexpr(itmpB)))) );   /* frB's low 32 bits */
8182      break;
8183
8184   case 0x028: // fneg (Floating Negate, PPC32 p416)
8185      DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8186      assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
8187      break;
8188
8189   case 0x048: // fmr (Floating Move Register, PPC32 p410)
8190      DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8191      assign( frD, mkexpr(frB) );
8192      break;
8193
8194   case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
8195      DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8196      assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
8197      break;
8198
8199   case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
8200      DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8201      assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
8202      break;
8203
8204   default:
8205      vex_printf("dis_fp_move(ppc)(opc2)\n");
8206      return False;
8207   }
8208
8209   putFReg( frD_addr, mkexpr(frD) );
8210
8211   /* None of these change FPRF.  cr1 is set in the usual way though,
8212      if flag_rC is set. */
8213
8214   if (flag_rC) {
8215      putCR321( 1, mkU8(0) );
8216      putCR0( 1, mkU8(0) );
8217   }
8218
8219   return True;
8220}
8221
8222
8223
8224/*
8225  Floating Point Status/Control Register Instructions
8226*/
8227static Bool dis_fp_scr ( UInt theInstr )
8228{
8229   /* Many forms - see each switch case */
8230   UChar opc1    = ifieldOPC(theInstr);
8231   UInt  opc2    = ifieldOPClo10(theInstr);
8232   UChar flag_rC = ifieldBIT0(theInstr);
8233
8234   if (opc1 != 0x3F) {
8235      vex_printf("dis_fp_scr(ppc)(instr)\n");
8236      return False;
8237   }
8238
8239   switch (opc2) {
8240   case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
8241      // Bit crbD of the FPSCR is set.
8242      UChar crbD    = ifieldRegDS(theInstr);
8243      UInt  b11to20 = IFIELD(theInstr, 11, 10);
8244
8245      if (b11to20 != 0) {
8246         vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
8247         return False;
8248      }
8249      DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
8250      putGST_masked( PPC_GST_FPSCR, mkU32(1<<(31-crbD)), 1<<(31-crbD) );
8251      break;
8252   }
8253
8254   case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
8255      UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
8256      UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
8257      UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
8258      UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
8259      IRTemp  tmp     = newTemp(Ity_I32);
8260      IRExpr* fpscr_all;
8261      if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
8262         vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
8263         return False;
8264      }
8265      DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
8266      vassert(crfD < 8);
8267      vassert(crfS < 8);
8268      fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
8269      assign( tmp, binop(Iop_And32,
8270                         binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
8271                        mkU32(0xF)) );
8272      putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
8273      break;
8274   }
8275
8276   case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
8277      // Bit crbD of the FPSCR is cleared.
8278      UChar crbD    = ifieldRegDS(theInstr);
8279      UInt  b11to20 = IFIELD(theInstr, 11, 10);
8280
8281      if (b11to20 != 0) {
8282         vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
8283         return False;
8284      }
8285      DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
8286      putGST_masked( PPC_GST_FPSCR, mkU32(0), 1<<(31-crbD) );
8287      break;
8288   }
8289
8290   case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
8291      UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
8292      UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
8293      UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
8294      UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
8295
8296      if (b16to22 != 0 || b11 != 0) {
8297         vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
8298         return False;
8299      }
8300      DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM);
8301      putGST_field( PPC_GST_FPSCR, mkU32(IMM), crfD );
8302      break;
8303   }
8304
8305   case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
8306      UChar   frD_addr  = ifieldRegDS(theInstr);
8307      UInt    b11to20   = IFIELD(theInstr, 11, 10);
8308      IRExpr* fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
8309
8310      if (b11to20 != 0) {
8311         vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
8312         return False;
8313      }
8314      DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
8315      putFReg( frD_addr,
8316          unop( Iop_ReinterpI64asF64,
8317                unop( Iop_32Uto64, fpscr_all )));
8318      break;
8319   }
8320
8321   case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
8322      UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
8323      UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
8324      UChar frB_addr = ifieldRegB(theInstr);
8325      IRTemp frB   = newTemp(Ity_F64);
8326      IRTemp rB_32 = newTemp(Ity_I32);
8327      Int i, mask;
8328
8329      if (b25 == 1) {
8330         /* new 64 bit move variant for power 6.  If L field (bit 25) is
8331          * a one do a full 64 bit move.  Note, the FPSCR is not really
8332          * properly modeled.  This instruciton only changes the value of
8333          * the rounding mode.  The HW exception bits do not get set in
8334          * the simulator.  1/12/09
8335          */
8336         DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
8337         mask = 0xFF;
8338
8339      } else {
8340         DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
8341         // Build 32bit mask from FM:
8342         mask = 0;
8343         for (i=0; i<8; i++) {
8344            if ((FM & (1<<(7-i))) == 1) {
8345               mask |= 0xF << (7-i);
8346            }
8347         }
8348      }
8349      assign( frB, getFReg(frB_addr));
8350      assign( rB_32, unop( Iop_64to32,
8351                           unop( Iop_ReinterpF64asI64, mkexpr(frB) )));
8352      putGST_masked( PPC_GST_FPSCR, mkexpr(rB_32), mask );
8353      break;
8354   }
8355
8356   default:
8357      vex_printf("dis_fp_scr(ppc)(opc2)\n");
8358      return False;
8359   }
8360   return True;
8361}
8362
8363
8364
8365/*------------------------------------------------------------*/
8366/*--- AltiVec Instruction Translation                      ---*/
8367/*------------------------------------------------------------*/
8368
8369/*
8370  Altivec Cache Control Instructions (Data Streams)
8371*/
8372static Bool dis_av_datastream ( UInt theInstr )
8373{
8374   /* X-Form */
8375   UChar opc1     = ifieldOPC(theInstr);
8376   UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
8377   UChar flag_A   = flag_T;
8378   UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
8379   UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
8380   UChar rA_addr  = ifieldRegA(theInstr);
8381   UChar rB_addr  = ifieldRegB(theInstr);
8382   UInt  opc2     = ifieldOPClo10(theInstr);
8383   UChar b0       = ifieldBIT0(theInstr);
8384
8385   if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
8386      vex_printf("dis_av_datastream(ppc)(instr)\n");
8387      return False;
8388   }
8389
8390   switch (opc2) {
8391   case 0x156: // dst (Data Stream Touch, AV p115)
8392      DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
8393                                rA_addr, rB_addr, STRM);
8394      break;
8395
8396   case 0x176: // dstst (Data Stream Touch for Store, AV p117)
8397      DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
8398                                  rA_addr, rB_addr, STRM);
8399      break;
8400
8401   case 0x336: // dss (Data Stream Stop, AV p114)
8402      if (rA_addr != 0 || rB_addr != 0) {
8403         vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
8404         return False;
8405      }
8406      if (flag_A == 0) {
8407         DIP("dss %d\n", STRM);
8408      } else {
8409         DIP("dssall\n");
8410      }
8411      break;
8412
8413   default:
8414      vex_printf("dis_av_datastream(ppc)(opc2)\n");
8415      return False;
8416   }
8417   return True;
8418}
8419
8420/*
8421  AltiVec Processor Control Instructions
8422*/
8423static Bool dis_av_procctl ( UInt theInstr )
8424{
8425   /* VX-Form */
8426   UChar opc1    = ifieldOPC(theInstr);
8427   UChar vD_addr = ifieldRegDS(theInstr);
8428   UChar vA_addr = ifieldRegA(theInstr);
8429   UChar vB_addr = ifieldRegB(theInstr);
8430   UInt  opc2    = IFIELD( theInstr, 0, 11 );
8431
8432   if (opc1 != 0x4) {
8433      vex_printf("dis_av_procctl(ppc)(instr)\n");
8434      return False;
8435   }
8436
8437   switch (opc2) {
8438   case 0x604: // mfvscr (Move from VSCR, AV p129)
8439      if (vA_addr != 0 || vB_addr != 0) {
8440         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
8441         return False;
8442      }
8443      DIP("mfvscr v%d\n", vD_addr);
8444      putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
8445      break;
8446
8447   case 0x644: { // mtvscr (Move to VSCR, AV p130)
8448      IRTemp vB = newTemp(Ity_V128);
8449      if (vD_addr != 0 || vA_addr != 0) {
8450         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
8451         return False;
8452      }
8453      DIP("mtvscr v%d\n", vB_addr);
8454      assign( vB, getVReg(vB_addr));
8455      putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
8456      break;
8457   }
8458   default:
8459      vex_printf("dis_av_procctl(ppc)(opc2)\n");
8460      return False;
8461   }
8462   return True;
8463}
8464
8465/*
8466 * VSX scalar and vector convert instructions
8467 */
8468static Bool
8469dis_vx_conv ( UInt theInstr, UInt opc2 )
8470{
8471   /* XX2-Form */
8472   UChar opc1 = ifieldOPC( theInstr );
8473   UChar XT = ifieldRegXT( theInstr );
8474   UChar XB = ifieldRegXB( theInstr );
8475   IRTemp xB, xB2;
8476   IRTemp b3, b2, b1, b0;
8477   xB = xB2 = IRTemp_INVALID;
8478
8479   if (opc1 != 0x3C) {
8480      vex_printf( "dis_vx_conv(ppc)(instr)\n" );
8481      return False;
8482   }
8483
8484   /* Create and assign temps only as needed for the given instruction. */
8485   switch (opc2) {
8486      // scalar double-precision floating point argument
8487      case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x090:
8488         xB = newTemp(Ity_F64);
8489         assign( xB,
8490                 unop( Iop_ReinterpI64asF64,
8491                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
8492         break;
8493      // vector double-precision floating point arguments
8494      case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
8495
8496         xB = newTemp(Ity_F64);
8497         xB2 = newTemp(Ity_F64);
8498         assign( xB,
8499                 unop( Iop_ReinterpI64asF64,
8500                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
8501         assign( xB2,
8502                 unop( Iop_ReinterpI64asF64,
8503                       unop( Iop_V128to64, getVSReg( XB ) ) ) );
8504         break;
8505      // vector single precision or [un]signed integer word arguments
8506      case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
8507      case 0x1f0: case 0x1d0:
8508         b3 = b2 = b1 = b0 = IRTemp_INVALID;
8509         breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
8510         break;
8511         // vector [un]signed integer doubleword argument
8512      case 0x3f0: case 0x370: case 0x3d0: case 0x350:
8513         xB = newTemp(Ity_I64);
8514         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
8515         xB2 = newTemp(Ity_I64);
8516         assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
8517         break;
8518      // scalar [un]signed integer doubleword argument
8519      case 0x2F0: case 0x2D0:
8520         xB = newTemp(Ity_I64);
8521         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
8522         break;
8523      // scalar single precision argument
8524      case 0x292: // xscvspdp
8525         xB = newTemp(Ity_I32);
8526         assign( xB,
8527                 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
8528         break;
8529
8530      /* Certain instructions have their complete implementation in the main switch statement
8531       * that follows this one; thus we have a "do nothing" case for those instructions here.
8532       */
8533      case 0x170: case 0x150:
8534         break; // do nothing
8535
8536      default:
8537         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
8538         return False;
8539   }
8540
8541
8542   switch (opc2) {
8543      case 0x2B0:
8544         // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
8545         //             to Signed Integer Doubleword format with Saturate)
8546         DIP("xscvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8547         putVSReg( XT,
8548                   binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
8549                                                 mkU32( Irrm_ZERO ),
8550                                                 mkexpr( xB ) ), mkU64( 0 ) ) );
8551         break;
8552      case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
8553                  //             Convert to Signed Integer Word format with Saturate)
8554         DIP("xscvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
8555         putVSReg( XT,
8556                   binop( Iop_64HLtoV128,
8557                          unop( Iop_32Sto64,
8558                                binop( Iop_F64toI32S,
8559                                       mkU32( Irrm_ZERO ),
8560                                       mkexpr( xB ) ) ),
8561                                       mkU64( 0ULL ) ) );
8562         break;
8563      case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
8564                  //             to Unsigned Integer Doubleword format with Saturate)
8565         DIP("xscvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8566         putVSReg( XT,
8567                   binop( Iop_64HLtoV128,
8568                          binop( Iop_F64toI64U,
8569                                 mkU32( Irrm_ZERO ),
8570                                 mkexpr( xB ) ),
8571                                 mkU64( 0ULL ) ) );
8572         break;
8573      case 0x2F0:
8574         // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
8575         //            Double-Precision format)
8576         DIP("xscvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8577         putVSReg( XT,
8578                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
8579                                                binop( Iop_I64StoF64, get_IR_roundingmode(),
8580                                                       mkexpr( xB ) ) ),
8581                                                       mkU64( 0 ) ) );
8582         break;
8583      case 0x2D0:
8584         // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
8585         //            Double-Precision format)
8586         DIP("xscvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8587         putVSReg( XT,
8588                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
8589                                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
8590                                                       mkexpr( xB ) ) ),
8591                                                       mkU64( 0 ) ) );
8592         break;
8593      case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
8594                  //             to Signed Integer Word format with Saturate)
8595      {
8596         IRTemp hiResult_32 = newTemp(Ity_I32);
8597         IRTemp loResult_32 = newTemp(Ity_I32);
8598         IRExpr* rmZero = mkU32(Irrm_ZERO);
8599
8600         DIP("xvcvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
8601         assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
8602         assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
8603         putVSReg( XT,
8604                   binop( Iop_64HLtoV128,
8605                          unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
8606                          unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
8607         break;
8608      }
8609      case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
8610         //  (VSX Vector truncate Single-Precision to integer and
8611         //   Convert to [Un]signed Integer Word format with Saturate)
8612      {
8613         IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
8614         IRTemp tempResult = newTemp(Ity_V128);
8615         IRTemp res0 = newTemp(Ity_I32);
8616         IRTemp res1 = newTemp(Ity_I32);
8617         IRTemp res2 = newTemp(Ity_I32);
8618         IRTemp res3 = newTemp(Ity_I32);
8619         IRTemp hi64 = newTemp(Ity_I64);
8620         IRTemp lo64 = newTemp(Ity_I64);
8621         Bool un_signed = (opc2 == 0x110);
8622         IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
8623
8624         DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB);
8625         /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
8626          * then result is set to 0x80000000.  */
8627         assign(tempResult, unop(op, getVSReg(XB)));
8628         assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
8629         assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
8630         assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
8631         assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
8632         assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
8633         assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
8634
8635         b3_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b3)),
8636                                  // else: result is from the Iop_QFtoI32{s|u}x4_RZ
8637                                  mkexpr(res3),
8638                                  // then: result is 0x{8|0}80000000
8639                                  mkU32(un_signed ? 0x00000000 : 0x80000000));
8640         b2_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b2)),
8641                                  // else: result is from the Iop_QFtoI32{s|u}x4_RZ
8642                                  mkexpr(res2),
8643                                  // then: result is 0x{8|0}80000000
8644                                  mkU32(un_signed ? 0x00000000 : 0x80000000));
8645         b1_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b1)),
8646                                  // else: result is from the Iop_QFtoI32{s|u}x4_RZ
8647                                  mkexpr(res1),
8648                                  // then: result is 0x{8|0}80000000
8649                                  mkU32(un_signed ? 0x00000000 : 0x80000000));
8650         b0_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b0)),
8651                                  // else: result is from the Iop_QFtoI32{s|u}x4_RZ
8652                                  mkexpr(res0),
8653                                  // then: result is 0x{8|0}80000000
8654                                  mkU32(un_signed ? 0x00000000 : 0x80000000));
8655
8656         putVSReg( XT,
8657                   binop( Iop_64HLtoV128,
8658                          binop( Iop_32HLto64, b3_result, b2_result ),
8659                          binop( Iop_32HLto64, b1_result, b0_result ) ) );
8660         break;
8661      }
8662      case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
8663                  //           Convert to Single-Precision format
8664         DIP("xscvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8665         putVSReg( XT,
8666                   binop( Iop_64HLtoV128,
8667                          binop( Iop_32HLto64,
8668                                 unop( Iop_ReinterpF32asI32,
8669                                       unop( Iop_TruncF64asF32,
8670                                             binop( Iop_RoundF64toF32,
8671                                                    get_IR_roundingmode(),
8672                                                    mkexpr( xB ) ) ) ),
8673                                 mkU32( 0 ) ),
8674                          mkU64( 0ULL ) ) );
8675         break;
8676      case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
8677                  //             and Convert to Unsigned Integer Word format with Saturate)
8678         DIP("xscvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
8679         putVSReg( XT,
8680                   binop( Iop_64HLtoV128,
8681                          binop( Iop_32HLto64,
8682                                 mkU32( 0 ),
8683                                 binop( Iop_F64toI32U,
8684                                        mkU32( Irrm_ZERO ),
8685                                        mkexpr( xB ) ) ),
8686                          mkU64( 0ULL ) ) );
8687         break;
8688      case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format)
8689         DIP("xscvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8690         putVSReg( XT,
8691                   binop( Iop_64HLtoV128,
8692                          unop( Iop_ReinterpF64asI64,
8693                                unop( Iop_F32toF64,
8694                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
8695                          mkU64( 0ULL ) ) );
8696         break;
8697      case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
8698                  //           and Convert to Single-Precision format)
8699         DIP("xvcvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8700         putVSReg( XT,
8701                   binop( Iop_64HLtoV128,
8702                          binop( Iop_32HLto64,
8703                                 unop( Iop_ReinterpF32asI32,
8704                                       unop( Iop_TruncF64asF32,
8705                                             binop( Iop_RoundF64toF32,
8706                                                    get_IR_roundingmode(),
8707                                                    mkexpr( xB ) ) ) ),
8708                                 mkU32( 0 ) ),
8709                          binop( Iop_32HLto64,
8710                                 unop( Iop_ReinterpF32asI32,
8711                                       unop( Iop_TruncF64asF32,
8712                                             binop( Iop_RoundF64toF32,
8713                                                    get_IR_roundingmode(),
8714                                                    mkexpr( xB2 ) ) ) ),
8715                                 mkU32( 0 ) ) ) );
8716         break;
8717      case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
8718                  //             and Convert to Unsigned Integer Doubleword format
8719                  //             with Saturate)
8720         DIP("xvcvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8721         putVSReg( XT,
8722                   binop( Iop_64HLtoV128,
8723                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
8724                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
8725         break;
8726      case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
8727                  //             Convert to Unsigned Integer Word format with Saturate)
8728         DIP("xvcvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
8729         putVSReg( XT,
8730                   binop( Iop_64HLtoV128,
8731                          binop( Iop_32HLto64,
8732                                 binop( Iop_F64toI32U,
8733                                        mkU32( Irrm_ZERO ),
8734                                        mkexpr( xB ) ),
8735                                 mkU32( 0 ) ),
8736                          binop( Iop_32HLto64,
8737                                 binop( Iop_F64toI32U,
8738                                        mkU32( Irrm_ZERO ),
8739                                        mkexpr( xB2 ) ),
8740                                 mkU32( 0 ) ) ) );
8741         break;
8742      case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
8743         DIP("xvcvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8744         putVSReg( XT,
8745                   binop( Iop_64HLtoV128,
8746                          unop( Iop_ReinterpF64asI64,
8747                                unop( Iop_F32toF64,
8748                                      unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
8749                          unop( Iop_ReinterpF64asI64,
8750                                unop( Iop_F32toF64,
8751                                      unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
8752         break;
8753      case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
8754                  //           Convert to Signed Integer Doubleword format with Saturate)
8755         DIP("xvcvspsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8756         putVSReg( XT,
8757                   binop( Iop_64HLtoV128,
8758                          binop( Iop_F64toI64S,
8759                                 mkU32( Irrm_ZERO ),
8760                                 unop( Iop_F32toF64,
8761                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
8762                          binop( Iop_F64toI64S,
8763                                 mkU32( Irrm_ZERO ),
8764                                 unop( Iop_F32toF64,
8765                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
8766         break;
8767      case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
8768                  //            Convert to Unsigned Integer Doubleword format with Saturate)
8769         DIP("xvcvspuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8770         putVSReg( XT,
8771                   binop( Iop_64HLtoV128,
8772                          binop( Iop_F64toI64U,
8773                                 mkU32( Irrm_ZERO ),
8774                                 unop( Iop_F32toF64,
8775                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
8776                          binop( Iop_F64toI64U,
8777                                 mkU32( Irrm_ZERO ),
8778                                 unop( Iop_F32toF64,
8779                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
8780         break;
8781      case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
8782                  //             Convert to Signed Integer Doubleword format with Saturate)
8783         DIP("xvcvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8784         putVSReg( XT,
8785                   binop( Iop_64HLtoV128,
8786                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
8787                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
8788         break;
8789      case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
8790                  //            to Double-Precision format)
8791         DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8792         putVSReg( XT,
8793                   binop( Iop_64HLtoV128,
8794                          unop( Iop_ReinterpF64asI64,
8795                                binop( Iop_I64StoF64,
8796                                       get_IR_roundingmode(),
8797                                       mkexpr( xB ) ) ),
8798                          unop( Iop_ReinterpF64asI64,
8799                                binop( Iop_I64StoF64,
8800                                       get_IR_roundingmode(),
8801                                       mkexpr( xB2 ) ) ) ) );
8802         break;
8803      case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
8804                  //            to Double-Precision format)
8805         DIP("xvcvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8806         putVSReg( XT,
8807                   binop( Iop_64HLtoV128,
8808                          unop( Iop_ReinterpF64asI64,
8809                                binop( Iop_I64UtoF64,
8810                                       get_IR_roundingmode(),
8811                                       mkexpr( xB ) ) ),
8812                          unop( Iop_ReinterpF64asI64,
8813                                binop( Iop_I64UtoF64,
8814                                       get_IR_roundingmode(),
8815                                       mkexpr( xB2 ) ) ) ) );
8816
8817         break;
8818      case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
8819                  //            to Single-Precision format)
8820         DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8821         putVSReg( XT,
8822                   binop( Iop_64HLtoV128,
8823                          binop( Iop_32HLto64,
8824                                 unop( Iop_ReinterpF32asI32,
8825                                       unop( Iop_TruncF64asF32,
8826                                             binop( Iop_RoundF64toF32,
8827                                                    get_IR_roundingmode(),
8828                                                    binop( Iop_I64StoF64,
8829                                                           get_IR_roundingmode(),
8830                                                           mkexpr( xB ) ) ) ) ),
8831                                 mkU32( 0 ) ),
8832                          binop( Iop_32HLto64,
8833                                 unop( Iop_ReinterpF32asI32,
8834                                       unop( Iop_TruncF64asF32,
8835                                             binop( Iop_RoundF64toF32,
8836                                                    get_IR_roundingmode(),
8837                                                    binop( Iop_I64StoF64,
8838                                                           get_IR_roundingmode(),
8839                                                           mkexpr( xB2 ) ) ) ) ),
8840                                 mkU32( 0 ) ) ) );
8841         break;
8842      case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
8843                  //            to Single-Precision format)
8844         DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
8845         putVSReg( XT,
8846                   binop( Iop_64HLtoV128,
8847                          binop( Iop_32HLto64,
8848                                 unop( Iop_ReinterpF32asI32,
8849                                       unop( Iop_TruncF64asF32,
8850                                             binop( Iop_RoundF64toF32,
8851                                                    get_IR_roundingmode(),
8852                                                    binop( Iop_I64UtoF64,
8853                                                           get_IR_roundingmode(),
8854                                                           mkexpr( xB ) ) ) ) ),
8855                                 mkU32( 0 ) ),
8856                          binop( Iop_32HLto64,
8857                                 unop( Iop_ReinterpF32asI32,
8858                                       unop( Iop_TruncF64asF32,
8859                                             binop( Iop_RoundF64toF32,
8860                                                    get_IR_roundingmode(),
8861                                                    binop( Iop_I64UtoF64,
8862                                                           get_IR_roundingmode(),
8863                                                           mkexpr( xB2 ) ) ) ) ),
8864                                 mkU32( 0 ) ) ) );
8865         break;
8866
8867      case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
8868         DIP("xvcvsxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8869         putVSReg( XT,
8870                   binop( Iop_64HLtoV128,
8871                          unop( Iop_ReinterpF64asI64,
8872                                binop( Iop_I64StoF64, get_IR_roundingmode(),
8873                                       unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
8874                          unop( Iop_ReinterpF64asI64,
8875                                binop( Iop_I64StoF64, get_IR_roundingmode(),
8876                                       unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
8877         break;
8878      case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
8879         DIP("xvcvuxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8880         putVSReg( XT,
8881                   binop( Iop_64HLtoV128,
8882                          unop( Iop_ReinterpF64asI64,
8883                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
8884                                       unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
8885                          unop( Iop_ReinterpF64asI64,
8886                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
8887                                       unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
8888         break;
8889      case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
8890         DIP("xvcvsxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8891         putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
8892         break;
8893      case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
8894         DIP("xvcvuxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8895         putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
8896         break;
8897
8898      default:
8899         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
8900         return False;
8901   }
8902   return True;
8903}
8904
8905/*
8906 * VSX vector Double Precision Floating Point Arithmetic Instructions
8907 */
8908static Bool
8909dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
8910{
8911   /* XX3-Form */
8912   UChar opc1 = ifieldOPC( theInstr );
8913   UChar XT = ifieldRegXT( theInstr );
8914   UChar XA = ifieldRegXA( theInstr );
8915   UChar XB = ifieldRegXB( theInstr );
8916   IRExpr* rm = get_IR_roundingmode();
8917   IRTemp frA = newTemp(Ity_F64);
8918   IRTemp frB = newTemp(Ity_F64);
8919   IRTemp frA2 = newTemp(Ity_F64);
8920   IRTemp frB2 = newTemp(Ity_F64);
8921
8922   if (opc1 != 0x3C) {
8923      vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
8924      return False;
8925   }
8926
8927   assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
8928   assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
8929   assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
8930   assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
8931
8932   switch (opc2) {
8933      case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
8934      case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
8935      case 0x180: // xvadddp (VSX Vector Add Double-Precision)
8936      case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
8937      {
8938         IROp mOp;
8939         Char * oper_name;
8940         switch (opc2) {
8941            case 0x1E0:
8942               mOp = Iop_DivF64;
8943               oper_name = "div";
8944               break;
8945            case 0x1C0:
8946               mOp = Iop_MulF64;
8947               oper_name = "mul";
8948               break;
8949            case 0x180:
8950               mOp = Iop_AddF64;
8951               oper_name = "add";
8952               break;
8953            case 0x1A0:
8954               mOp = Iop_SubF64;
8955               oper_name = "sub";
8956               break;
8957
8958            default:
8959               vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
8960         }
8961         IRTemp hiResult = newTemp(Ity_I64);
8962         IRTemp loResult = newTemp(Ity_I64);
8963         DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB);
8964
8965         assign( hiResult,
8966                 unop( Iop_ReinterpF64asI64,
8967                       triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
8968         assign( loResult,
8969                 unop( Iop_ReinterpF64asI64,
8970                       triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
8971         putVSReg( XT,
8972                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
8973         break;
8974      }
8975      case 0x196: // xvsqrtdp
8976      {
8977         IRTemp hiResult = newTemp(Ity_I64);
8978         IRTemp loResult = newTemp(Ity_I64);
8979         DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
8980
8981         assign( hiResult,
8982                 unop( Iop_ReinterpF64asI64,
8983                       binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
8984         assign( loResult,
8985                 unop( Iop_ReinterpF64asI64,
8986                       binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
8987         putVSReg( XT,
8988                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
8989         break;
8990      }
8991      case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
8992      case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
8993      case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
8994      case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
8995      {
8996         /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
8997          *    XT == FRC
8998          *    XA == FRA
8999          *    XB == FRB
9000          *
9001          * and for xvm{add|sub}adp . . .
9002          *    XT == FRB
9003          *    XA == FRA
9004          *    XB == FRC
9005          */
9006         Bool negate;
9007         IROp mOp = Iop_INVALID;
9008         Char * oper_name = NULL;
9009         Bool mdp = False;
9010
9011         switch (opc2) {
9012            case 0x184: case 0x1A4:
9013            case 0x384: case 0x3A4:
9014               mOp = Iop_MAddF64;
9015               oper_name = "add";
9016               mdp = (opc2 & 0x0FF) == 0x0A4;
9017               break;
9018
9019            case 0x1C4: case 0x1E4:
9020            case 0x3C4: case 0x3E4:
9021               mOp = Iop_MSubF64;
9022               oper_name = "sub";
9023               mdp = (opc2 & 0x0FF) == 0x0E4;
9024               break;
9025
9026            default:
9027               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
9028         }
9029
9030         switch (opc2) {
9031            case 0x384: case 0x3A4:
9032            case 0x3C4: case 0x3E4:
9033               negate = True;
9034               break;
9035            default:
9036               negate = False;
9037         }
9038         IRTemp hiResult = newTemp(Ity_I64);
9039         IRTemp loResult = newTemp(Ity_I64);
9040         IRTemp frT = newTemp(Ity_F64);
9041         IRTemp frT2 = newTemp(Ity_F64);
9042         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
9043             (UInt)XT, (UInt)XA, (UInt)XB);
9044         assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
9045         assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
9046
9047         assign( hiResult,
9048                 unop( Iop_ReinterpF64asI64,
9049                       qop( mOp,
9050                            rm,
9051                            mkexpr( frA ),
9052                            mkexpr( mdp ? frT : frB ),
9053                            mkexpr( mdp ? frB : frT ) ) ) );
9054         assign( loResult,
9055                 unop( Iop_ReinterpF64asI64,
9056                       qop( mOp,
9057                            rm,
9058                            mkexpr( frA2 ),
9059                            mkexpr( mdp ? frT2 : frB2 ),
9060                            mkexpr( mdp ? frB2 : frT2 ) ) ) );
9061         putVSReg( XT,
9062                   binop( Iop_64HLtoV128,
9063                          mkexpr( negate ? getNegatedResult( hiResult )
9064                                         : hiResult ),
9065                          mkexpr( negate ? getNegatedResult( loResult )
9066                                         : loResult ) ) );
9067         break;
9068      }
9069      case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
9070      {
9071         IRTemp frBHi_I64 = newTemp(Ity_I64);
9072         IRTemp frBLo_I64 = newTemp(Ity_I64);
9073         IRTemp flagsHi = newTemp(Ity_I32);
9074         IRTemp flagsLo = newTemp(Ity_I32);
9075         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
9076         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
9077         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
9078
9079         DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
9080         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
9081         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
9082         do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
9083         do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
9084         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
9085          * where fl_flag == 1 on ppc64.
9086          */
9087         assign( flagsHi,
9088                 binop( Iop_Or32,
9089                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9090                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
9091                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
9092         assign( flagsLo,
9093                 binop( Iop_Or32,
9094                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9095                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
9096                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
9097         putGST_field( PPC_GST_CR,
9098                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
9099                       crfD );
9100         break;
9101      }
9102      case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
9103      {
9104         IRTemp frBHi_I64 = newTemp(Ity_I64);
9105         IRTemp frBLo_I64 = newTemp(Ity_I64);
9106         IRTemp frAHi_I64 = newTemp(Ity_I64);
9107         IRTemp frALo_I64 = newTemp(Ity_I64);
9108         IRTemp flagsHi = newTemp(Ity_I32);
9109         IRTemp flagsLo = newTemp(Ity_I32);
9110         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
9111         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
9112         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
9113
9114         DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
9115         assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
9116         assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
9117         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
9118         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
9119
9120         _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
9121         _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
9122         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
9123          * where fl_flag == 1 on ppc64.
9124          */
9125         assign( flagsHi,
9126                 binop( Iop_Or32,
9127                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9128                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
9129                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
9130         assign( flagsLo,
9131                 binop( Iop_Or32,
9132                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9133                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
9134                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
9135         putGST_field( PPC_GST_CR,
9136                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
9137                       crfD );
9138         break;
9139      }
9140
9141      default:
9142         vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
9143         return False;
9144   }
9145   return True;
9146}
9147
9148/*
9149 * VSX vector Single Precision Floating Point Arithmetic Instructions
9150 */
9151static Bool
9152dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
9153{
9154   /* XX3-Form */
9155   UChar opc1 = ifieldOPC( theInstr );
9156   UChar XT = ifieldRegXT( theInstr );
9157   UChar XA = ifieldRegXA( theInstr );
9158   UChar XB = ifieldRegXB( theInstr );
9159   IRExpr* rm = get_IR_roundingmode();
9160   IRTemp a3, a2, a1, a0;
9161   IRTemp b3, b2, b1, b0;
9162   IRTemp res0 = newTemp(Ity_I32);
9163   IRTemp res1 = newTemp(Ity_I32);
9164   IRTemp res2 = newTemp(Ity_I32);
9165   IRTemp res3 = newTemp(Ity_I32);
9166
9167   a3 = a2 = a1 = a0 = IRTemp_INVALID;
9168   b3 = b2 = b1 = b0 = IRTemp_INVALID;
9169
9170   if (opc1 != 0x3C) {
9171      vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
9172      return False;
9173   }
9174
9175   switch (opc2) {
9176      case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
9177         DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
9178         putVSReg( XT, binop(Iop_Add32Fx4, getVSReg( XA ), getVSReg( XB )) );
9179         break;
9180
9181      case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
9182         DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
9183         putVSReg( XT, binop(Iop_Mul32Fx4, getVSReg( XA ), getVSReg( XB )) );
9184         break;
9185
9186      case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
9187         DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
9188         putVSReg( XT, binop(Iop_Sub32Fx4, getVSReg( XA ), getVSReg( XB )) );
9189         break;
9190
9191      case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
9192      {
9193         /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
9194          * So there are two choices:
9195          *   1. Implement the xvdivsp with a native insn; or
9196          *   2. Extract the 4 single precision floats from each vector
9197          *      register inputs and perform fdivs on each pair
9198          * I will do the latter, due to the general philosophy of
9199          * reusing existing implementations when practical.
9200          */
9201         DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
9202         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
9203         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9204
9205         assign( res0,
9206              unop( Iop_ReinterpF32asI32,
9207                    unop( Iop_TruncF64asF32,
9208                          triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
9209         assign( res1,
9210                 unop( Iop_ReinterpF32asI32,
9211                       unop( Iop_TruncF64asF32,
9212                             triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
9213         assign( res2,
9214                 unop( Iop_ReinterpF32asI32,
9215                       unop( Iop_TruncF64asF32,
9216                             triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
9217         assign( res3,
9218                 unop( Iop_ReinterpF32asI32,
9219                       unop( Iop_TruncF64asF32,
9220                             triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
9221
9222         putVSReg( XT,
9223                   binop( Iop_64HLtoV128,
9224                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
9225                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
9226         break;
9227      }
9228      case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
9229      {
9230         DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
9231         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9232         /* Note: The native xvsqrtsp insruction does not always give the same precision
9233          * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
9234          * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
9235          * to the actual instruction.
9236          */
9237
9238         assign( res0,
9239                 unop( Iop_ReinterpF32asI32,
9240                       unop( Iop_TruncF64asF32,
9241                             binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
9242         assign( res1,
9243                 unop( Iop_ReinterpF32asI32,
9244                       unop( Iop_TruncF64asF32,
9245                             binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
9246         assign( res2,
9247                 unop( Iop_ReinterpF32asI32,
9248                       unop( Iop_TruncF64asF32,
9249                             binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
9250         assign( res3,
9251                 unop( Iop_ReinterpF32asI32,
9252                       unop( Iop_TruncF64asF32,
9253                             binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
9254
9255         putVSReg( XT,
9256                   binop( Iop_64HLtoV128,
9257                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
9258                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
9259         break;
9260      }
9261
9262      case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
9263      case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
9264      case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
9265      case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
9266      {
9267         IRTemp t3, t2, t1, t0;
9268         Bool msp = False;
9269         Bool negate;
9270         Char * oper_name = NULL;
9271         IROp mOp = Iop_INVALID;
9272         switch (opc2) {
9273            case 0x104: case 0x124:
9274            case 0x304: case 0x324:
9275               msp = (opc2 & 0x0FF) == 0x024;
9276               mOp = Iop_MAddF64r32;
9277               oper_name = "madd";
9278               break;
9279
9280            case 0x144: case 0x164:
9281            case 0x344: case 0x364:
9282               msp = (opc2 & 0x0FF) == 0x064;
9283               mOp = Iop_MSubF64r32;
9284               oper_name = "sub";
9285               break;
9286
9287            default:
9288               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
9289         }
9290
9291         switch (opc2) {
9292            case 0x304: case 0x324:
9293            case 0x344: case 0x364:
9294               negate = True;
9295               break;
9296
9297            default:
9298               negate = False;
9299         }
9300
9301         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp",
9302             (UInt)XT, (UInt)XA, (UInt)XB);
9303
9304         t3 = t2 = t1 = t0 = IRTemp_INVALID;
9305         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
9306         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9307         breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
9308
9309         assign( res0,
9310                 unop( Iop_ReinterpF32asI32,
9311                       unop( Iop_TruncF64asF32,
9312                             qop( mOp,
9313                                  rm,
9314                                  mkexpr( a0 ),
9315                                  mkexpr( msp ? t0 : b0 ),
9316                                  mkexpr( msp ? b0 : t0 ) ) ) ) );
9317         assign( res1,
9318                 unop( Iop_ReinterpF32asI32,
9319                       unop( Iop_TruncF64asF32,
9320                             qop( mOp,
9321                                  rm,
9322                                  mkexpr( a1 ),
9323                                  mkexpr( msp ? t1 : b1 ),
9324                                  mkexpr( msp ? b1 : t1 ) ) ) ) );
9325         assign( res2,
9326                 unop( Iop_ReinterpF32asI32,
9327                       unop( Iop_TruncF64asF32,
9328                             qop( mOp,
9329                                  rm,
9330                                  mkexpr( a2 ),
9331                                  mkexpr( msp ? t2 : b2 ),
9332                                  mkexpr( msp ? b2 : t2 ) ) ) ) );
9333         assign( res3,
9334                 unop( Iop_ReinterpF32asI32,
9335                       unop( Iop_TruncF64asF32,
9336                             qop( mOp,
9337                                  rm,
9338                                  mkexpr( a3 ),
9339                                  mkexpr( msp ? t3 : b3 ),
9340                                  mkexpr( msp ? b3 : t3 ) ) ) ) );
9341
9342         putVSReg( XT,
9343                   binop( Iop_64HLtoV128,
9344                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
9345                                 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
9346                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
9347                                 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
9348
9349         break;
9350      }
9351      case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
9352      {
9353         IRTemp flags0 = newTemp(Ity_I32);
9354         IRTemp flags1 = newTemp(Ity_I32);
9355         IRTemp flags2 = newTemp(Ity_I32);
9356         IRTemp flags3 = newTemp(Ity_I32);
9357         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
9358         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
9359         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
9360         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
9361         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
9362         DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
9363
9364         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9365         do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
9366         do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
9367         do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
9368         do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
9369
9370         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
9371          * where fl_flag == 1 on ppc64.
9372          */
9373         assign( flags0,
9374                 binop( Iop_Or32,
9375                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9376                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
9377                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
9378         assign( flags1,
9379                 binop( Iop_Or32,
9380                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9381                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
9382                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
9383         assign( flags2,
9384                 binop( Iop_Or32,
9385                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9386                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
9387                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
9388         assign( flags3,
9389                 binop( Iop_Or32,
9390                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9391                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
9392                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
9393         putGST_field( PPC_GST_CR,
9394                       binop( Iop_Or32,
9395                              mkexpr( flags0 ),
9396                              binop( Iop_Or32,
9397                                     mkexpr( flags1 ),
9398                                     binop( Iop_Or32,
9399                                            mkexpr( flags2 ),
9400                                            mkexpr( flags3 ) ) ) ),
9401                       crfD );
9402
9403         break;
9404      }
9405      case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
9406      {
9407         IRTemp flags0 = newTemp(Ity_I32);
9408         IRTemp flags1 = newTemp(Ity_I32);
9409         IRTemp flags2 = newTemp(Ity_I32);
9410         IRTemp flags3 = newTemp(Ity_I32);
9411         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
9412         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
9413         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
9414         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
9415         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
9416         DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
9417
9418         breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
9419         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9420         _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
9421         _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
9422         _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
9423         _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
9424
9425         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
9426          * where fl_flag == 1 on ppc64.
9427          */
9428         assign( flags0,
9429                 binop( Iop_Or32,
9430                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9431                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
9432                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
9433         assign( flags1,
9434                 binop( Iop_Or32,
9435                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9436                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
9437                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
9438         assign( flags2,
9439                 binop( Iop_Or32,
9440                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9441                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
9442                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
9443         assign( flags3,
9444                 binop( Iop_Or32,
9445                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9446                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
9447                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
9448         putGST_field( PPC_GST_CR,
9449                       binop( Iop_Or32,
9450                              mkexpr( flags0 ),
9451                              binop( Iop_Or32,
9452                                     mkexpr( flags1 ),
9453                                     binop( Iop_Or32,
9454                                            mkexpr( flags2 ),
9455                                            mkexpr( flags3 ) ) ) ),
9456                       crfD );
9457
9458         break;
9459      }
9460
9461      default:
9462         vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
9463         return False;
9464   }
9465   return True;
9466}
9467
9468typedef enum {
9469   PPC_CMP_EQ = 2,
9470   PPC_CMP_GT = 4,
9471   PPC_CMP_GE = 6,
9472   PPC_CMP_LT = 8
9473} ppc_cmp_t;
9474
9475
9476/*
9477  This helper function takes as input the IRExpr returned
9478  from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
9479  in IR form.  This helper function converts it to PPC form.
9480
9481  Map compare result from IR to PPC
9482
9483  FP cmp result | PPC | IR
9484  --------------------------
9485  UN            | 0x1 | 0x45
9486  EQ            | 0x2 | 0x40
9487  GT            | 0x4 | 0x00
9488  LT            | 0x8 | 0x01
9489
9490 condcode = Shl(1, (~(ccIR>>5) & 2)
9491                    | ((ccIR ^ (ccIR>>6)) & 1)
9492*/
9493static IRTemp
9494get_fp_cmp_CR_val (IRExpr * ccIR_expr)
9495{
9496   IRTemp condcode = newTemp( Ity_I32 );
9497   IRTemp ccIR = newTemp( Ity_I32 );
9498
9499   assign(ccIR, ccIR_expr);
9500   assign( condcode,
9501           binop( Iop_Shl32,
9502                  mkU32( 1 ),
9503                  unop( Iop_32to8,
9504                        binop( Iop_Or32,
9505                               binop( Iop_And32,
9506                                      unop( Iop_Not32,
9507                                            binop( Iop_Shr32,
9508                                                   mkexpr( ccIR ),
9509                                                   mkU8( 5 ) ) ),
9510                                      mkU32( 2 ) ),
9511                               binop( Iop_And32,
9512                                      binop( Iop_Xor32,
9513                                             mkexpr( ccIR ),
9514                                             binop( Iop_Shr32,
9515                                                    mkexpr( ccIR ),
9516                                                    mkU8( 6 ) ) ),
9517                                      mkU32( 1 ) ) ) ) ) );
9518   return condcode;
9519}
9520
9521/*
9522 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
9523 * following these special rules:
9524 *   - The max/min of a QNaN and any value is that value
9525 *     (When two QNaNs are being compared, the frA QNaN is the return value.)
9526 *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
9527 *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
9528 */
9529static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
9530{
9531   IRTemp frA_isNaN = newTemp(Ity_I1);
9532   IRTemp frB_isNaN = newTemp(Ity_I1);
9533   IRTemp frA_isSNaN = newTemp(Ity_I1);
9534   IRTemp frB_isSNaN = newTemp(Ity_I1);
9535   IRTemp frA_isQNaN = newTemp(Ity_I1);
9536   IRTemp frB_isQNaN = newTemp(Ity_I1);
9537
9538   assign( frA_isNaN, is_NaN( frA_I64 ) );
9539   assign( frB_isNaN, is_NaN( frB_I64 ) );
9540   // If operand is a NAN and bit 12 is '0', then it's an SNaN
9541   assign( frA_isSNaN,
9542           mkAND1( mkexpr(frA_isNaN),
9543                   binop( Iop_CmpEQ32,
9544                          binop( Iop_And32,
9545                                 unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
9546                                 mkU32( 0x00080000 ) ),
9547                          mkU32( 0 ) ) ) );
9548   assign( frB_isSNaN,
9549           mkAND1( mkexpr(frB_isNaN),
9550                   binop( Iop_CmpEQ32,
9551                          binop( Iop_And32,
9552                                 unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
9553                                 mkU32( 0x00080000 ) ),
9554                          mkU32( 0 ) ) ) );
9555   assign( frA_isQNaN,
9556           mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
9557   assign( frB_isQNaN,
9558           mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
9559
9560   /* Based on the rules specified in the function prologue, the algorithm is as follows:
9561    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
9562    *   if frA is a SNaN
9563    *     result = frA converted to QNaN
9564    *   else if frB is a SNaN
9565    *     result = frB converted to QNaN
9566    *   else if frB is a QNaN
9567    *     result = frA
9568    *   // One of frA or frB was a NaN in order for this function to be called, so
9569    *   // if we get to this point, we KNOW that frA must be a QNaN.
9570    *   else // frA is a QNaN
9571    *     result = frB
9572    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
9573    */
9574
9575#define SNAN_MASK 0x0008000000000000ULL
9576   return
9577   IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frA_isSNaN)),
9578                /* else:  if frB is a SNaN */
9579                IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isSNaN)),
9580                             /* else:  if frB is a QNaN */
9581                             IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isQNaN)),
9582                                          /* else:  frA is a QNaN, so result = frB */
9583                                          mkexpr(frB_I64),
9584                                          /* then: result = frA */
9585                                          mkexpr(frA_I64)),
9586                             /* then: result = frB converted to QNaN */
9587                             binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK))),
9588                /* then: result = frA converted to QNaN */
9589                binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)));
9590}
9591
9592/*
9593 * Helper function for get_max_min_fp.
9594 */
9595static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
9596{
9597   IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
9598                                                  unop( Iop_ReinterpI64asF64,
9599                                                        mkexpr( src1 ) ),
9600                                                  unop( Iop_ReinterpI64asF64,
9601                                                        mkexpr( src2 ) ) ) );
9602
9603   return IRExpr_Mux0X( unop( Iop_1Uto8,
9604                              binop( Iop_CmpEQ32,
9605                                     mkexpr( src1cmpsrc2 ),
9606                                     mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ) ),
9607                        /* else: use src2 */
9608                        mkexpr( src2 ),
9609                        /* then: use src1 */
9610                        mkexpr( src1 ) );
9611}
9612
9613/*
9614 * Helper function for "Maximum/Minimum Double Precision" operations.
9615 * Arguments: frA and frb are Ity_I64
9616 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
9617 */
9618static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
9619{
9620   /* There are three special cases where get_fp_cmp_CR_val is not helpful
9621    * for ascertaining the maximum between two doubles:
9622    *   1. The max/min of +0 and -0 is +0.
9623    *   2. The max/min of a QNaN and any value is that value.
9624    *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
9625    * We perform the check for [+/-]0 here in this function and use the
9626    * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
9627    * to do the standard comparison function.
9628    */
9629   IRTemp anyNaN = newTemp(Ity_I1);
9630   IRTemp frA_isZero = newTemp(Ity_I1);
9631   IRTemp frB_isZero = newTemp(Ity_I1);
9632   assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
9633   assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
9634   assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
9635#define MINUS_ZERO 0x8000000000000000ULL
9636
9637   return IRExpr_Mux0X( unop( Iop_1Uto8,
9638                              /* If both arguments are zero . . . */
9639                              mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ) ),
9640                        /* else: check if either input is a NaN*/
9641                        IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( anyNaN ) ),
9642                                      /* else: use "comparison helper" */
9643                                      _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ),
9644                                      /* then: use "NaN helper" */
9645                                      _get_maxmin_fp_NaN( frA_I64, frB_I64 ) ),
9646                        /* then: if frA is -0 and isMin==True, return -0;
9647                         *     else if frA is +0 and isMin==False; return +0;
9648                         *     otherwise, simply return frB. */
9649                        IRExpr_Mux0X( unop( Iop_1Uto8,
9650                                            binop( Iop_CmpEQ32,
9651                                                   unop( Iop_64HIto32,
9652                                                         mkexpr( frA_I64 ) ),
9653                                                   mkU32( isMin ? 0x80000000 : 0 ) ) ),
9654                                      mkexpr( frB_I64 ),
9655                                      mkU64( isMin ? MINUS_ZERO : 0ULL ) ) );
9656}
9657
9658/*
9659 * Helper function for vector/scalar double precision fp round to integer instructions.
9660 */
9661static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2, UChar * insn_suffix)
9662{
9663
9664   /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
9665   IRTemp frB = newTemp(Ity_F64);
9666   IRTemp frD = newTemp(Ity_F64);
9667   IRTemp intermediateResult = newTemp(Ity_I64);
9668   IRTemp is_SNAN = newTemp(Ity_I1);
9669   IRExpr * hi32;
9670   IRExpr * rxpi_rm;
9671   switch (opc2 & 0x7F) {
9672      case 0x72:
9673         insn_suffix = "m";
9674         rxpi_rm = mkU32(Irrm_NegINF);
9675         break;
9676      case 0x52:
9677         insn_suffix = "p";
9678         rxpi_rm = mkU32(Irrm_PosINF);
9679         break;
9680      case 0x56:
9681         insn_suffix = "c";
9682         rxpi_rm = get_IR_roundingmode();
9683         break;
9684      case 0x32:
9685         insn_suffix = "z";
9686         rxpi_rm = mkU32(Irrm_ZERO);
9687         break;
9688      case 0x12:
9689         insn_suffix = "";
9690         rxpi_rm = mkU32(Irrm_NEAREST);
9691         break;
9692
9693      default: // Impossible to get here
9694         vex_printf( "_do_vsx_fp_roundToInt(ppc)(opc2)\n" );
9695         return NULL;
9696   }
9697   assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
9698   assign( intermediateResult,
9699           binop( Iop_F64toI64S, rxpi_rm,
9700                  mkexpr( frB ) ) );
9701
9702   /* don't use the rounded integer if frB is outside -9e18..9e18 */
9703   /* F64 has only log10(2**52) significant digits anyway */
9704   /* need to preserve sign of zero */
9705   /*   frD = (fabs(frB) > 9e18) ? frB :
9706            (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
9707   assign( frD,
9708           IRExpr_Mux0X( unop( Iop_32to8,
9709                               binop( Iop_CmpF64,
9710                                      IRExpr_Const( IRConst_F64( 9e18 ) ),
9711                                      unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
9712                         IRExpr_Mux0X( unop( Iop_32to8,
9713                                             binop( Iop_Shr32,
9714                                                    unop( Iop_64HIto32,
9715                                                          mkexpr( frB_I64 ) ),
9716                                                    mkU8( 31 ) ) ),
9717                                       binop( Iop_I64StoF64,
9718                                              mkU32( 0 ),
9719                                              mkexpr( intermediateResult ) ),
9720                                       unop( Iop_NegF64,
9721                                             unop( Iop_AbsF64,
9722                                                   binop( Iop_I64StoF64,
9723                                                          mkU32( 0 ),
9724                                                          mkexpr( intermediateResult ) ) ) ) ),
9725                         mkexpr( frB ) ) );
9726
9727   /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
9728    * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
9729    */
9730#define SNAN_MASK 0x0008000000000000ULL
9731   hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
9732   assign( is_SNAN,
9733           mkAND1( is_NaN( frB_I64 ),
9734                   binop( Iop_CmpEQ32,
9735                          binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
9736                          mkU32( 0 ) ) ) );
9737
9738   return IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( is_SNAN ) ),
9739                        mkexpr( frD ),
9740                        unop( Iop_ReinterpI64asF64,
9741                              binop( Iop_Xor64,
9742                                     mkU64( SNAN_MASK ),
9743                                     mkexpr( frB_I64 ) ) ) );
9744}
9745
9746/*
9747 * Miscellaneous VSX vector instructions
9748 */
9749static Bool
9750dis_vxv_misc ( UInt theInstr, UInt opc2 )
9751{
9752   /* XX3-Form */
9753   UChar opc1 = ifieldOPC( theInstr );
9754   UChar XT = ifieldRegXT( theInstr );
9755   UChar XB = ifieldRegXB( theInstr );
9756
9757   if (opc1 != 0x3C) {
9758      vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
9759      return False;
9760   }
9761
9762   switch (opc2) {
9763      case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
9764      case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
9765                   //             Double-Precision)
9766      {
9767         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
9768         IRExpr* rm  = get_IR_roundingmode();
9769         IRTemp frB = newTemp(Ity_I64);
9770         IRTemp frB2 = newTemp(Ity_I64);
9771         Bool redp = opc2 == 0x1B4;
9772         IRTemp sqrtHi = newTemp(Ity_F64);
9773         IRTemp sqrtLo = newTemp(Ity_F64);
9774         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
9775         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
9776
9777         DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB);
9778         if (!redp) {
9779            assign( sqrtHi,
9780                    binop( Iop_SqrtF64,
9781                           rm,
9782                           unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
9783            assign( sqrtLo,
9784                    binop( Iop_SqrtF64,
9785                           rm,
9786                           unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
9787         }
9788         putVSReg( XT,
9789                   binop( Iop_64HLtoV128,
9790                          unop( Iop_ReinterpF64asI64,
9791                                triop( Iop_DivF64,
9792                                       rm,
9793                                       ieee_one,
9794                                       redp ? unop( Iop_ReinterpI64asF64,
9795                                                    mkexpr( frB ) )
9796                                            : mkexpr( sqrtHi ) ) ),
9797                          unop( Iop_ReinterpF64asI64,
9798                                triop( Iop_DivF64,
9799                                       rm,
9800                                       ieee_one,
9801                                       redp ? unop( Iop_ReinterpI64asF64,
9802                                                    mkexpr( frB2 ) )
9803                                            : mkexpr( sqrtLo ) ) ) ) );
9804         break;
9805
9806      }
9807      case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
9808      case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
9809      {
9810         IRTemp b3, b2, b1, b0;
9811         IRTemp res0 = newTemp(Ity_I32);
9812         IRTemp res1 = newTemp(Ity_I32);
9813         IRTemp res2 = newTemp(Ity_I32);
9814         IRTemp res3 = newTemp(Ity_I32);
9815         IRTemp sqrt3 = newTemp(Ity_F64);
9816         IRTemp sqrt2 = newTemp(Ity_F64);
9817         IRTemp sqrt1 = newTemp(Ity_F64);
9818         IRTemp sqrt0 = newTemp(Ity_F64);
9819         IRExpr* rm  = get_IR_roundingmode();
9820         Bool resp = opc2 == 0x134;
9821
9822         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
9823
9824         b3 = b2 = b1 = b0 = IRTemp_INVALID;
9825         DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB);
9826         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9827
9828         if (!resp) {
9829            assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
9830            assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
9831            assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
9832            assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
9833         }
9834
9835         assign( res0,
9836                 unop( Iop_ReinterpF32asI32,
9837                       unop( Iop_TruncF64asF32,
9838                             triop( Iop_DivF64r32,
9839                                    rm,
9840                                    ieee_one,
9841                                    resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
9842         assign( res1,
9843                 unop( Iop_ReinterpF32asI32,
9844                       unop( Iop_TruncF64asF32,
9845                             triop( Iop_DivF64r32,
9846                                    rm,
9847                                    ieee_one,
9848                                    resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
9849         assign( res2,
9850                 unop( Iop_ReinterpF32asI32,
9851                       unop( Iop_TruncF64asF32,
9852                             triop( Iop_DivF64r32,
9853                                    rm,
9854                                    ieee_one,
9855                                    resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
9856         assign( res3,
9857                 unop( Iop_ReinterpF32asI32,
9858                       unop( Iop_TruncF64asF32,
9859                             triop( Iop_DivF64r32,
9860                                    rm,
9861                                    ieee_one,
9862                                    resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
9863         putVSReg( XT,
9864                   binop( Iop_64HLtoV128,
9865                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
9866                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
9867         break;
9868      }
9869      case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
9870      case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
9871      {
9872         UChar XA = ifieldRegXA( theInstr );
9873         IRTemp a3, a2, a1, a0;
9874         IRTemp b3, b2, b1, b0;
9875         IRTemp res0 = newTemp( Ity_I32 );
9876         IRTemp res1 = newTemp( Ity_I32 );
9877         IRTemp res2 = newTemp( Ity_I32 );
9878         IRTemp res3 = newTemp( Ity_I32 );
9879         IRTemp a0_I64 = newTemp( Ity_I64 );
9880         IRTemp a1_I64 = newTemp( Ity_I64 );
9881         IRTemp a2_I64 = newTemp( Ity_I64 );
9882         IRTemp a3_I64 = newTemp( Ity_I64 );
9883         IRTemp b0_I64 = newTemp( Ity_I64 );
9884         IRTemp b1_I64 = newTemp( Ity_I64 );
9885         IRTemp b2_I64 = newTemp( Ity_I64 );
9886         IRTemp b3_I64 = newTemp( Ity_I64 );
9887
9888         Bool isMin = opc2 == 0x320 ? True : False;
9889
9890         a3 = a2 = a1 = a0 = IRTemp_INVALID;
9891         b3 = b2 = b1 = b0 = IRTemp_INVALID;
9892         DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB);
9893         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
9894         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9895         assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
9896         assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
9897         assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
9898         assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
9899         assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
9900         assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
9901         assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
9902         assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
9903         assign( res0,
9904                 unop( Iop_ReinterpF32asI32,
9905                       unop( Iop_TruncF64asF32,
9906                             unop( Iop_ReinterpI64asF64,
9907                                   get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
9908         assign( res1,
9909                 unop( Iop_ReinterpF32asI32,
9910                       unop( Iop_TruncF64asF32,
9911                             unop( Iop_ReinterpI64asF64,
9912                                   get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
9913         assign( res2,
9914                 unop( Iop_ReinterpF32asI32,
9915                       unop( Iop_TruncF64asF32,
9916                             unop( Iop_ReinterpI64asF64,
9917                                   get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
9918         assign( res3,
9919                 unop( Iop_ReinterpF32asI32,
9920                       unop( Iop_TruncF64asF32,
9921                             unop( Iop_ReinterpI64asF64,
9922                                   get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
9923         putVSReg( XT,
9924                   binop( Iop_64HLtoV128,
9925                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
9926                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
9927         break;
9928      }
9929      case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
9930      case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
9931      {
9932         UChar XA = ifieldRegXA( theInstr );
9933         IRTemp frA = newTemp(Ity_I64);
9934         IRTemp frB = newTemp(Ity_I64);
9935         IRTemp frA2 = newTemp(Ity_I64);
9936         IRTemp frB2 = newTemp(Ity_I64);
9937         Bool isMin = opc2 == 0x3A0 ? True : False;
9938
9939         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
9940         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
9941         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
9942         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
9943         DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB);
9944         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
9945
9946         break;
9947      }
9948      case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
9949      {
9950         UChar XA = ifieldRegXA( theInstr );
9951         IRTemp frA = newTemp(Ity_I64);
9952         IRTemp frB = newTemp(Ity_I64);
9953         IRTemp frA2 = newTemp(Ity_I64);
9954         IRTemp frB2 = newTemp(Ity_I64);
9955         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
9956         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
9957         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
9958         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
9959
9960         DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
9961         putVSReg( XT,
9962                   binop( Iop_64HLtoV128,
9963                          binop( Iop_Or64,
9964                                 binop( Iop_And64,
9965                                        mkexpr( frA ),
9966                                        mkU64( SIGN_BIT ) ),
9967                                 binop( Iop_And64,
9968                                        mkexpr( frB ),
9969                                        mkU64( SIGN_MASK ) ) ),
9970                          binop( Iop_Or64,
9971                                 binop( Iop_And64,
9972                                        mkexpr( frA2 ),
9973                                        mkU64( SIGN_BIT ) ),
9974                                 binop( Iop_And64,
9975                                        mkexpr( frB2 ),
9976                                        mkU64( SIGN_MASK ) ) ) ) );
9977         break;
9978      }
9979      case 0x340: // xvcpsgnsp
9980      {
9981         UChar XA = ifieldRegXA( theInstr );
9982         IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
9983         IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
9984         IRTemp resHi = newTemp(Ity_I64);
9985         IRTemp resLo = newTemp(Ity_I64);
9986
9987         a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
9988         b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
9989         DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB);
9990         breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
9991         breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
9992
9993         assign( resHi,
9994                 binop( Iop_32HLto64,
9995                        binop( Iop_Or32,
9996                               binop( Iop_And32,
9997                                      unop(Iop_64to32, mkexpr( a3_I64 ) ),
9998                                      mkU32( SIGN_BIT32 ) ),
9999                               binop( Iop_And32,
10000                                      unop(Iop_64to32, mkexpr( b3_I64 ) ),
10001                                      mkU32( SIGN_MASK32) ) ),
10002
10003                        binop( Iop_Or32,
10004                               binop( Iop_And32,
10005                                      unop(Iop_64to32, mkexpr( a2_I64 ) ),
10006                                      mkU32( SIGN_BIT32 ) ),
10007                               binop( Iop_And32,
10008                                      unop(Iop_64to32, mkexpr( b2_I64 ) ),
10009                                      mkU32( SIGN_MASK32 ) ) ) ) );
10010         assign( resLo,
10011                 binop( Iop_32HLto64,
10012                        binop( Iop_Or32,
10013                               binop( Iop_And32,
10014                                      unop(Iop_64to32, mkexpr( a1_I64 ) ),
10015                                      mkU32( SIGN_BIT32 ) ),
10016                               binop( Iop_And32,
10017                                      unop(Iop_64to32, mkexpr( b1_I64 ) ),
10018                                      mkU32( SIGN_MASK32 ) ) ),
10019
10020                        binop( Iop_Or32,
10021                               binop( Iop_And32,
10022                                      unop(Iop_64to32, mkexpr( a0_I64 ) ),
10023                                      mkU32( SIGN_BIT32 ) ),
10024                               binop( Iop_And32,
10025                                      unop(Iop_64to32, mkexpr( b0_I64 ) ),
10026                                      mkU32( SIGN_MASK32 ) ) ) ) );
10027         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
10028         break;
10029      }
10030      case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
10031      case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
10032      {
10033         IRTemp frB = newTemp(Ity_F64);
10034         IRTemp frB2 = newTemp(Ity_F64);
10035         IRTemp abs_resultHi = newTemp(Ity_F64);
10036         IRTemp abs_resultLo = newTemp(Ity_F64);
10037         Bool make_negative = (opc2 == 0x3D2) ? True : False;
10038         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
10039         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
10040
10041         DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB);
10042         if (make_negative) {
10043            assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
10044            assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
10045
10046         } else {
10047            assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
10048            assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
10049         }
10050         putVSReg( XT, binop( Iop_64HLtoV128,
10051                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
10052                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
10053         break;
10054      }
10055      case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
10056      case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
10057      {
10058         /*
10059          * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
10060          * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
10061          * of this function is so easy using shifts, I choose to emulate this instruction that
10062          * way versus a native instruction method of implementation.
10063          */
10064         Bool make_negative = (opc2 == 0x352) ? True : False;
10065         IRTemp shiftVector = newTemp(Ity_V128);
10066         IRTemp absVal_vector = newTemp(Ity_V128);
10067         assign( shiftVector,
10068                 binop( Iop_64HLtoV128,
10069                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
10070                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
10071         assign( absVal_vector,
10072                   binop( Iop_Shr32x4,
10073                          binop( Iop_Shl32x4,
10074                                 getVSReg( XB ),
10075                                 mkexpr( shiftVector ) ),
10076                          mkexpr( shiftVector ) ) );
10077         if (make_negative) {
10078            IRTemp signBit_vector = newTemp(Ity_V128);
10079            assign( signBit_vector,
10080                    binop( Iop_64HLtoV128,
10081                           binop( Iop_32HLto64,
10082                                  mkU32( 0x80000000 ),
10083                                  mkU32( 0x80000000 ) ),
10084                           binop( Iop_32HLto64,
10085                                  mkU32( 0x80000000 ),
10086                                  mkU32( 0x80000000 ) ) ) );
10087            putVSReg( XT,
10088                      binop( Iop_OrV128,
10089                             mkexpr( absVal_vector ),
10090                             mkexpr( signBit_vector ) ) );
10091         } else {
10092            putVSReg( XT, mkexpr( absVal_vector ) );
10093         }
10094         break;
10095      }
10096      case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
10097      {
10098         IRTemp frB = newTemp(Ity_F64);
10099         IRTemp frB2 = newTemp(Ity_F64);
10100         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
10101         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
10102         DIP("xvnegdp v%d,v%d\n",  (UInt)XT, (UInt)XB);
10103         putVSReg( XT,
10104                   binop( Iop_64HLtoV128,
10105                          unop( Iop_ReinterpF64asI64,
10106                                unop( Iop_NegF64, mkexpr( frB ) ) ),
10107                          unop( Iop_ReinterpF64asI64,
10108                                unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
10109         break;
10110      }
10111      case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
10112      case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
10113      case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
10114      case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
10115      case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
10116      {
10117         IRTemp frBHi_I64 = newTemp(Ity_I64);
10118         IRTemp frBLo_I64 = newTemp(Ity_I64);
10119         IRExpr * frD_fp_roundHi = NULL;
10120         IRExpr * frD_fp_roundLo = NULL;
10121         UChar * insn_suffix = NULL;
10122
10123         assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
10124         frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2, insn_suffix);
10125         assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
10126         frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2, insn_suffix);
10127
10128         DIP("xvrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
10129         putVSReg( XT,
10130                   binop( Iop_64HLtoV128,
10131                          unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
10132                          unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
10133         break;
10134      }
10135      case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
10136      case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
10137      case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
10138      case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
10139      case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
10140      {
10141         UChar * insn_suffix = NULL;
10142         IROp op;
10143         if (opc2 != 0x156) {
10144            // Use pre-defined IRop's for vrfi{m|n|p|z}
10145            switch (opc2) {
10146               case 0x112:
10147                  insn_suffix = "";
10148                  op = Iop_RoundF32x4_RN;
10149                  break;
10150               case 0x172:
10151                  insn_suffix = "m";
10152                  op = Iop_RoundF32x4_RM;
10153                  break;
10154               case 0x152:
10155                  insn_suffix = "p";
10156                  op = Iop_RoundF32x4_RP;
10157                  break;
10158               case 0x132:
10159                  insn_suffix = "z";
10160                  op = Iop_RoundF32x4_RZ;
10161                  break;
10162
10163               default:
10164                  vex_printf( "dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n" );
10165                  return False;
10166            }
10167            DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
10168            putVSReg( XT, unop( op, getVSReg(XB) ) );
10169         } else {
10170            // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
10171            IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
10172            IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
10173            IRTemp b3_I64 = newTemp(Ity_I64);
10174            IRTemp b2_I64 = newTemp(Ity_I64);
10175            IRTemp b1_I64 = newTemp(Ity_I64);
10176            IRTemp b0_I64 = newTemp(Ity_I64);
10177
10178            b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
10179            frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
10180            breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
10181            assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
10182            assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
10183            assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
10184            assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
10185            frD_fp_roundb3 = unop(Iop_TruncF64asF32,
10186                                  _do_vsx_fp_roundToInt(b3_I64, opc2, insn_suffix));
10187            frD_fp_roundb2 = unop(Iop_TruncF64asF32,
10188                                  _do_vsx_fp_roundToInt(b2_I64, opc2, insn_suffix));
10189            frD_fp_roundb1 = unop(Iop_TruncF64asF32,
10190                                  _do_vsx_fp_roundToInt(b1_I64, opc2, insn_suffix));
10191            frD_fp_roundb0 = unop(Iop_TruncF64asF32,
10192                                  _do_vsx_fp_roundToInt(b0_I64, opc2, insn_suffix));
10193            DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB);
10194            putVSReg( XT,
10195                      binop( Iop_64HLtoV128,
10196                             binop( Iop_32HLto64,
10197                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
10198                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
10199                             binop( Iop_32HLto64,
10200                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
10201                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
10202         }
10203         break;
10204      }
10205
10206      default:
10207         vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
10208         return False;
10209   }
10210   return True;
10211}
10212
10213
10214/*
10215 * VSX Scalar Floating Point Arithmetic Instructions
10216 */
10217static Bool
10218dis_vxs_arith ( UInt theInstr, UInt opc2 )
10219{
10220   /* XX3-Form */
10221   UChar opc1 = ifieldOPC( theInstr );
10222   UChar XT = ifieldRegXT( theInstr );
10223   UChar XA = ifieldRegXA( theInstr );
10224   UChar XB = ifieldRegXB( theInstr );
10225   IRExpr* rm = get_IR_roundingmode();
10226   IRTemp frA = newTemp(Ity_F64);
10227   IRTemp frB = newTemp(Ity_F64);
10228
10229   if (opc1 != 0x3C) {
10230      vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
10231      return False;
10232   }
10233
10234   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
10235   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
10236
10237   /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
10238    * of VSX[XT] are undefined after the operation; therefore, we can simply set
10239    * element to zero where it makes sense to do so.
10240    */
10241   switch (opc2) {
10242      case 0x080: // xsadddp (VSX scalar add double-precision)
10243         DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10244         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10245                                                    triop( Iop_AddF64, rm,
10246                                                           mkexpr( frA ),
10247                                                           mkexpr( frB ) ) ),
10248                              mkU64( 0 ) ) );
10249         break;
10250      case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
10251         DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10252         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10253                                                    triop( Iop_DivF64, rm,
10254                                                           mkexpr( frA ),
10255                                                           mkexpr( frB ) ) ),
10256                              mkU64( 0 ) ) );
10257         break;
10258      case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
10259      {
10260         IRTemp frT = newTemp(Ity_F64);
10261         Bool mdp = opc2 == 0x0A4;
10262         DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
10263         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
10264                                                        getVSReg( XT ) ) ) );
10265         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10266                                                    qop( Iop_MAddF64, rm,
10267                                                         mkexpr( frA ),
10268                                                         mkexpr( mdp ? frT : frB ),
10269                                                         mkexpr( mdp ? frB : frT ) ) ),
10270                              mkU64( 0 ) ) );
10271         break;
10272      }
10273      case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
10274      {
10275         IRTemp frT = newTemp(Ity_F64);
10276         Bool mdp = opc2 == 0x0E4;
10277         DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
10278         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
10279                                                        getVSReg( XT ) ) ) );
10280         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10281                                                    qop( Iop_MSubF64, rm,
10282                                                         mkexpr( frA ),
10283                                                         mkexpr( mdp ? frT : frB ),
10284                                                         mkexpr( mdp ? frB : frT ) ) ),
10285                              mkU64( 0 ) ) );
10286         break;
10287      }
10288      case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
10289      {
10290         /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
10291          * of fnmadd and use pretty much the same code. However, that code has a bug in the
10292          * way it blindly negates the signbit, even if the floating point result is a NaN.
10293          * So, the TODO is to fix fnmadd (which I'll do in a different patch).
10294          */
10295         Bool mdp = opc2 == 0x2A4;
10296         IRTemp frT = newTemp(Ity_F64);
10297         IRTemp maddResult = newTemp(Ity_I64);
10298
10299         DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
10300         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
10301                                                        getVSReg( XT ) ) ) );
10302         assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
10303                                                              mkexpr( frA ),
10304                                                              mkexpr( mdp ? frT : frB ),
10305                                                              mkexpr( mdp ? frB : frT ) ) ) );
10306
10307         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
10308                              mkU64( 0 ) ) );
10309         break;
10310      }
10311      case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
10312      {
10313         IRTemp frT = newTemp(Ity_F64);
10314         Bool mdp = opc2 == 0x2E4;
10315         IRTemp msubResult = newTemp(Ity_I64);
10316
10317         DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
10318         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
10319                                                        getVSReg( XT ) ) ) );
10320         assign(msubResult, unop( Iop_ReinterpF64asI64,
10321                                      qop( Iop_MSubF64,
10322                                           rm,
10323                                           mkexpr( frA ),
10324                                           mkexpr( mdp ? frT : frB ),
10325                                           mkexpr( mdp ? frB : frT ) ) ));
10326
10327         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
10328
10329         break;
10330      }
10331
10332      case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
10333         DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10334         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10335                                                    triop( Iop_MulF64, rm,
10336                                                           mkexpr( frA ),
10337                                                           mkexpr( frB ) ) ),
10338                              mkU64( 0 ) ) );
10339         break;
10340      case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
10341         DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10342         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10343                                                    triop( Iop_SubF64, rm,
10344                                                           mkexpr( frA ),
10345                                                           mkexpr( frB ) ) ),
10346                              mkU64( 0 ) ) );
10347         break;
10348
10349      case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
10350         DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
10351         putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10352                                                     binop( Iop_SqrtF64, rm,
10353                                                            mkexpr( frB ) ) ),
10354                               mkU64( 0 ) ) );
10355         break;
10356
10357      case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
10358      {
10359         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
10360         IRTemp frA_I64 = newTemp(Ity_I64);
10361         IRTemp frB_I64 = newTemp(Ity_I64);
10362         DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB);
10363         assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
10364         assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
10365         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
10366         break;
10367      }
10368      case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
10369      {
10370         IRTemp frB_I64 = newTemp(Ity_I64);
10371         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
10372         IRTemp flags = newTemp(Ity_I32);
10373         IRTemp  fe_flag, fg_flag;
10374         fe_flag = fg_flag = IRTemp_INVALID;
10375         DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
10376         assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
10377         do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
10378         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
10379          * where fl_flag == 1 on ppc64.
10380          */
10381         assign( flags,
10382                 binop( Iop_Or32,
10383                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
10384                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
10385                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
10386         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
10387         break;
10388      }
10389
10390      default:
10391         vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
10392         return False;
10393   }
10394
10395   return True;
10396}
10397
10398
10399/*
10400 * VSX Floating Point Compare Instructions
10401 */
10402static Bool
10403dis_vx_cmp( UInt theInstr, UInt opc2 )
10404{
10405   /* XX3-Form and XX2-Form */
10406   UChar opc1 = ifieldOPC( theInstr );
10407   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
10408   IRTemp ccPPC32;
10409   UChar XA       = ifieldRegXA ( theInstr );
10410   UChar XB       = ifieldRegXB ( theInstr );
10411   IRTemp frA     = newTemp(Ity_F64);
10412   IRTemp frB     = newTemp(Ity_F64);
10413
10414   if (opc1 != 0x3C) {
10415      vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
10416      return False;
10417   }
10418
10419   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
10420   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
10421   switch (opc2) {
10422      case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
10423         /* Note: Differences between xscmpudp and xscmpodp are only in
10424          * exception flag settings, which aren't supported anyway. */
10425         DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
10426                                           crfD, (UInt)XA, (UInt)XB);
10427         ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
10428         putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
10429         break;
10430
10431      default:
10432         vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
10433         return False;
10434   }
10435   return True;
10436}
10437
10438static void
10439do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
10440                 ppc_cmp_t cmp_type )
10441{
10442   IRTemp frA_hi     = newTemp(Ity_F64);
10443   IRTemp frB_hi     = newTemp(Ity_F64);
10444   IRTemp frA_lo     = newTemp(Ity_F64);
10445   IRTemp frB_lo     = newTemp(Ity_F64);
10446   IRTemp ccPPC32    = newTemp(Ity_I32);
10447   IRTemp ccIR_hi;
10448   IRTemp ccIR_lo;
10449
10450   IRTemp hiResult = newTemp(Ity_I64);
10451   IRTemp loResult = newTemp(Ity_I64);
10452   IRTemp hiEQlo = newTemp(Ity_I1);
10453   IRTemp all_elem_true = newTemp(Ity_I32);
10454   IRTemp all_elem_false = newTemp(Ity_I32);
10455
10456   assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
10457   assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
10458   assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
10459   assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
10460
10461   ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
10462                                       mkexpr( frA_hi ),
10463                                       mkexpr( frB_hi ) ) );
10464   ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
10465                                       mkexpr( frA_lo ),
10466                                       mkexpr( frB_lo ) ) );
10467
10468   if (cmp_type != PPC_CMP_GE) {
10469      assign( hiResult,
10470              unop( Iop_1Sto64,
10471                    binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
10472      assign( loResult,
10473              unop( Iop_1Sto64,
10474                    binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
10475   } else {
10476      // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
10477      // the other element compare may return "2" (for "equal to").
10478      IRTemp lo_GE = newTemp(Ity_I1);
10479      IRTemp hi_GE = newTemp(Ity_I1);
10480
10481      assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
10482                           binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
10483      assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
10484
10485      assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
10486                           binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
10487      assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
10488   }
10489
10490   // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
10491   assign( hiEQlo,
10492           binop( Iop_CmpEQ32,
10493                  unop( Iop_64to32, mkexpr( hiResult ) ),
10494                  unop( Iop_64to32, mkexpr( loResult ) ) ) );
10495   putVSReg( XT,
10496             binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
10497
10498   assign( all_elem_true,
10499           unop( Iop_1Uto32,
10500                 mkAND1( mkexpr( hiEQlo ),
10501                         binop( Iop_CmpEQ32,
10502                                mkU32( 0xffffffff ),
10503                                unop( Iop_64to32,
10504                                mkexpr( hiResult ) ) ) ) ) );
10505
10506   assign( all_elem_false,
10507           unop( Iop_1Uto32,
10508                 mkAND1( mkexpr( hiEQlo ),
10509                         binop( Iop_CmpEQ32,
10510                                mkU32( 0 ),
10511                                unop( Iop_64to32,
10512                                mkexpr( hiResult ) ) ) ) ) );
10513   assign( ccPPC32,
10514           binop( Iop_Or32,
10515                  binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
10516                  binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
10517
10518   if (flag_rC) {
10519      putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
10520   }
10521}
10522
10523/*
10524 * VSX Vector Compare Instructions
10525 */
10526static Bool
10527dis_vvec_cmp( UInt theInstr, UInt opc2 )
10528{
10529   /* XX3-Form */
10530   UChar opc1 = ifieldOPC( theInstr );
10531   UChar XT = ifieldRegXT ( theInstr );
10532   UChar XA = ifieldRegXA ( theInstr );
10533   UChar XB = ifieldRegXB ( theInstr );
10534   UChar flag_rC  = ifieldBIT10(theInstr);
10535   IRTemp vA = newTemp( Ity_V128 );
10536   IRTemp vB = newTemp( Ity_V128 );
10537
10538   if (opc1 != 0x3C) {
10539      vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
10540      return False;
10541   }
10542
10543   assign( vA, getVSReg( XA ) );
10544   assign( vB, getVSReg( XB ) );
10545
10546   switch (opc2) {
10547      case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
10548      {
10549         DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10550             (UInt)XT, (UInt)XA, (UInt)XB);
10551         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
10552         break;
10553      }
10554
10555      case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
10556      {
10557         DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10558             (UInt)XT, (UInt)XA, (UInt)XB);
10559         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
10560         break;
10561      }
10562
10563      case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
10564      {
10565         DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10566             (UInt)XT, (UInt)XA, (UInt)XB);
10567         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
10568         break;
10569      }
10570
10571      case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
10572      {
10573         IRTemp vD = newTemp(Ity_V128);
10574
10575         DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10576             (UInt)XT, (UInt)XA, (UInt)XB);
10577         assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
10578         putVSReg( XT, mkexpr(vD) );
10579         if (flag_rC) {
10580            set_AV_CR6( mkexpr(vD), True );
10581         }
10582         break;
10583      }
10584
10585      case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
10586      {
10587         IRTemp vD = newTemp(Ity_V128);
10588
10589         DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10590             (UInt)XT, (UInt)XA, (UInt)XB);
10591         assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
10592         putVSReg( XT, mkexpr(vD) );
10593         if (flag_rC) {
10594            set_AV_CR6( mkexpr(vD), True );
10595         }
10596         break;
10597      }
10598
10599      case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
10600      {
10601         IRTemp vD = newTemp(Ity_V128);
10602
10603         DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10604             (UInt)XT, (UInt)XA, (UInt)XB);
10605         assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
10606         putVSReg( XT, mkexpr(vD) );
10607         if (flag_rC) {
10608            set_AV_CR6( mkexpr(vD), True );
10609         }
10610         break;
10611      }
10612
10613      default:
10614         vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
10615         return False;
10616   }
10617   return True;
10618}
10619/*
10620 * Miscellaneous VSX Scalar Instructions
10621 */
10622static Bool
10623dis_vxs_misc( UInt theInstr, UInt opc2 )
10624{
10625   /* XX3-Form and XX2-Form */
10626   UChar opc1 = ifieldOPC( theInstr );
10627   UChar XT = ifieldRegXT ( theInstr );
10628   UChar XA = ifieldRegXA ( theInstr );
10629   UChar XB = ifieldRegXB ( theInstr );
10630   IRTemp vA = newTemp( Ity_V128 );
10631   IRTemp vB = newTemp( Ity_V128 );
10632
10633   if (opc1 != 0x3C) {
10634      vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
10635      return False;
10636   }
10637
10638   assign( vA, getVSReg( XA ) );
10639   assign( vB, getVSReg( XB ) );
10640
10641   /* For all the VSX move instructions, the contents of doubleword element 1
10642    * of VSX[XT] are undefined after the operation; therefore, we can simply
10643    * move the entire array element where it makes sense to do so.
10644    */
10645
10646   switch (opc2) {
10647      case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
10648      {
10649         /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
10650         IRTemp absVal = newTemp(Ity_V128);
10651         assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1)));
10652         DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
10653         putVSReg(XT, mkexpr(absVal));
10654         break;
10655      }
10656      case 0x2C0: // xscpsgndp
10657      {
10658         /* Scalar copy sign double-precision */
10659         IRTemp vecA_signbit = newTemp(Ity_V128);
10660         IRTemp vecB_no_signbit = newTemp(Ity_V128);
10661         IRTemp vec_result = newTemp(Ity_V128);
10662         DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10663         assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
10664                                                             mkexpr( vB ),
10665                                                             mkU8( 1 ) ),
10666                                         mkU8( 1 ) ) );
10667         assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128,
10668                                                          mkexpr( vA ),
10669                                                          mkU8( 127 ) ),
10670                                      mkU8( 127 ) ) );
10671         assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) );
10672         putVSReg(XT, mkexpr(vec_result));
10673         break;
10674      }
10675      case 0x2D2: // xsnabsdp
10676      {
10677         /* Scalar negative absolute value double-precision */
10678         IRTemp vec_neg_signbit = newTemp(Ity_V128);
10679         DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
10680         assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128,
10681                                                            mkV128( 0xffff ),
10682                                                            mkU8( 1 ) ) ) );
10683         putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB)));
10684         break;
10685      }
10686      case 0x2F2: // xsnegdp
10687      {
10688         /* Scalar negate double-precision */
10689         IRTemp vecB_no_signbit = newTemp(Ity_V128);
10690         IRTemp vecB_signbit_comp = newTemp(Ity_V128);
10691         DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
10692         assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
10693                                                             mkexpr( vB ),
10694                                                             mkU8( 1 ) ),
10695                                         mkU8( 1 ) ) );
10696         assign( vecB_signbit_comp, binop( Iop_ShlV128,
10697                                           unop( Iop_NotV128,
10698                                                 binop( Iop_ShrV128,
10699                                                        mkexpr( vB ),
10700                                                        mkU8( 127 ) ) ),
10701                                           mkU8( 127 ) ) );
10702         putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ),
10703                              mkexpr( vecB_signbit_comp ) ) );
10704         break;
10705      }
10706      case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
10707      case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
10708      {
10709         IRTemp frA     = newTemp(Ity_I64);
10710         IRTemp frB     = newTemp(Ity_I64);
10711         Bool isMin = opc2 == 0x2A0 ? True : False;
10712         DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB);
10713
10714         assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
10715         assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
10716         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
10717
10718         break;
10719      }
10720      case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
10721      case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
10722      case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
10723      case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
10724      case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
10725      {
10726         IRTemp frB_I64 = newTemp(Ity_I64);
10727         IRExpr * frD_fp_round = NULL;
10728         UChar * insn_suffix = NULL;
10729
10730         assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
10731         frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2, insn_suffix);
10732
10733         DIP("xsrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
10734         putVSReg( XT,
10735                   binop( Iop_64HLtoV128,
10736                          unop( Iop_ReinterpF64asI64, frD_fp_round),
10737                          mkU64( 0 ) ) );
10738         break;
10739      }
10740      case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
10741      case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
10742
10743      {
10744         IRTemp frB = newTemp(Ity_F64);
10745         IRTemp sqrt = newTemp(Ity_F64);
10746         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
10747         IRExpr* rm  = get_IR_roundingmode();
10748         Bool redp = opc2 == 0x0B4;
10749         DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB);
10750         assign( frB,
10751                 unop( Iop_ReinterpI64asF64,
10752                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
10753
10754         if (!redp)
10755            assign( sqrt,
10756                    binop( Iop_SqrtF64,
10757                           rm,
10758                           mkexpr(frB) ) );
10759         putVSReg( XT,
10760                      binop( Iop_64HLtoV128,
10761                             unop( Iop_ReinterpF64asI64,
10762                                   triop( Iop_DivF64,
10763                                          rm,
10764                                          ieee_one,
10765                                          redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
10766                             mkU64( 0 ) ) );
10767         break;
10768      }
10769
10770      default:
10771         vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
10772         return False;
10773   }
10774   return True;
10775}
10776
10777/*
10778 * VSX Logical Instructions
10779 */
10780static Bool
10781dis_vx_logic ( UInt theInstr, UInt opc2 )
10782{
10783   /* XX3-Form */
10784   UChar opc1 = ifieldOPC( theInstr );
10785   UChar XT = ifieldRegXT ( theInstr );
10786   UChar XA = ifieldRegXA ( theInstr );
10787   UChar XB = ifieldRegXB ( theInstr );
10788   IRTemp vA = newTemp( Ity_V128 );
10789   IRTemp vB = newTemp( Ity_V128 );
10790
10791   if (opc1 != 0x3C) {
10792      vex_printf( "dis_vx_logic(ppc)(instr)\n" );
10793      return False;
10794   }
10795
10796   assign( vA, getVSReg( XA ) );
10797   assign( vB, getVSReg( XB ) );
10798
10799   switch (opc2) {
10800      case 0x268: // xxlxor
10801         DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10802         putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
10803         break;
10804      case 0x248: // xxlor
10805         DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10806         putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
10807         break;
10808      case 0x288: // xxlnor
10809         DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10810         putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
10811                                                 mkexpr( vB ) ) ) );
10812         break;
10813      case 0x208: // xxland
10814         DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10815         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
10816         break;
10817      case 0x228: //xxlandc
10818         DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10819         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
10820                                                               mkexpr( vB ) ) ) );
10821         break;
10822      default:
10823         vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
10824         return False;
10825   }
10826   return True;
10827}
10828
10829/*
10830 * VSX Load Instructions
10831 * NOTE: VSX supports word-aligned storage access.
10832 */
10833static Bool
10834dis_vx_load ( UInt theInstr )
10835{
10836   /* XX1-Form */
10837   UChar opc1 = ifieldOPC( theInstr );
10838   UChar XT = ifieldRegXT ( theInstr );
10839   UChar rA_addr = ifieldRegA( theInstr );
10840   UChar rB_addr = ifieldRegB( theInstr );
10841   UInt opc2 = ifieldOPClo10( theInstr );
10842
10843   IRType ty = mode64 ? Ity_I64 : Ity_I32;
10844   IRTemp EA = newTemp( ty );
10845
10846   if (opc1 != 0x1F) {
10847      vex_printf( "dis_vx_load(ppc)(instr)\n" );
10848      return False;
10849   }
10850
10851   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
10852
10853   switch (opc2) {
10854   case 0x24C: // lxsdx
10855   {
10856      IRExpr * exp;
10857      DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
10858      exp = loadBE( Ity_I64, mkexpr( EA ) );
10859      // We need to pass an expression of type Ity_V128 with putVSReg, but the load
10860      // we just performed is only a DW.  But since the contents of VSR[XT] element 1
10861      // are undefined after this operation, we can just do a splat op.
10862      putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
10863      break;
10864   }
10865   case 0x34C: // lxvd2x
10866   {
10867      IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
10868      IRExpr * high, *low;
10869      ULong ea_off = 8;
10870      IRExpr* high_addr;
10871      DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
10872      high = loadBE( Ity_I64, mkexpr( EA ) );
10873      high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
10874            : mkU32( ea_off ) );
10875      low = loadBE( Ity_I64, high_addr );
10876      putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
10877      break;
10878   }
10879   case 0x14C: // lxvdsx
10880   {
10881      IRTemp data = newTemp(Ity_I64);
10882      DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
10883      assign( data, loadBE( Ity_I64, mkexpr( EA ) ) );
10884      putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
10885      break;
10886   }
10887   case 0x30C:
10888   {
10889      IRExpr * t3, *t2, *t1, *t0;
10890      UInt ea_off = 0;
10891      IRExpr* irx_addr;
10892
10893      DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
10894      t3 = loadBE( Ity_I32,  mkexpr( EA ) );
10895      ea_off += 4;
10896      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10897                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10898      t2 = loadBE( Ity_I32, irx_addr );
10899      ea_off += 4;
10900      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10901                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10902      t1 = loadBE( Ity_I32, irx_addr );
10903      ea_off += 4;
10904      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10905                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10906      t0 = loadBE( Ity_I32, irx_addr );
10907      putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ),
10908                           binop( Iop_32HLto64, t1, t0 ) ) );
10909      break;
10910   }
10911   default:
10912      vex_printf( "dis_vx_load(ppc)(opc2)\n" );
10913      return False;
10914   }
10915   return True;
10916}
10917
10918/*
10919 * VSX Store Instructions
10920 * NOTE: VSX supports word-aligned storage access.
10921 */
10922static Bool
10923dis_vx_store ( UInt theInstr )
10924{
10925   /* XX1-Form */
10926   UChar opc1 = ifieldOPC( theInstr );
10927   UChar XS = ifieldRegXS( theInstr );
10928   UChar rA_addr = ifieldRegA( theInstr );
10929   UChar rB_addr = ifieldRegB( theInstr );
10930   IRTemp vS = newTemp( Ity_V128 );
10931   UInt opc2 = ifieldOPClo10( theInstr );
10932
10933   IRType ty = mode64 ? Ity_I64 : Ity_I32;
10934   IRTemp EA = newTemp( ty );
10935
10936   if (opc1 != 0x1F) {
10937      vex_printf( "dis_vx_store(ppc)(instr)\n" );
10938      return False;
10939   }
10940
10941   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
10942   assign( vS, getVSReg( XS ) );
10943
10944   switch (opc2) {
10945   case 0x2CC:
10946   {
10947      IRExpr * high64;
10948      DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
10949      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
10950      storeBE( mkexpr( EA ), high64 );
10951      break;
10952   }
10953   case 0x3CC:
10954   {
10955      IRExpr * high64, *low64;
10956      DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
10957      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
10958      low64 = unop( Iop_V128to64, mkexpr( vS ) );
10959      storeBE( mkexpr( EA ), high64 );
10960      storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 )
10961            : mkU32( 8 ) ), low64 );
10962      break;
10963   }
10964   case 0x38C:
10965   {
10966      UInt ea_off = 0;
10967      IRExpr* irx_addr;
10968      IRTemp hi64 = newTemp( Ity_I64 );
10969      IRTemp lo64 = newTemp( Ity_I64 );
10970
10971      DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
10972
10973      // This instruction supports word-aligned stores, so EA may not be
10974      // quad-word aligned.  Therefore, do 4 individual word-size stores.
10975      assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
10976      assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
10977
10978      storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
10979      ea_off += 4;
10980      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10981                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10982      storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
10983      ea_off += 4;
10984      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10985                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10986      storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
10987      ea_off += 4;
10988      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10989                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10990      storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
10991
10992      break;
10993   }
10994   default:
10995      vex_printf( "dis_vx_store(ppc)(opc2)\n" );
10996      return False;
10997   }
10998   return True;
10999}
11000
11001/*
11002 * VSX permute and other miscealleous instructions
11003 */
11004static Bool
11005dis_vx_permute_misc( UInt theInstr, UInt opc2 )
11006{
11007   /* XX3-Form */
11008   UChar opc1 = ifieldOPC( theInstr );
11009   UChar XT = ifieldRegXT ( theInstr );
11010   UChar XA = ifieldRegXA ( theInstr );
11011   UChar XB = ifieldRegXB ( theInstr );
11012   IRTemp vT = newTemp( Ity_V128 );
11013   IRTemp vA = newTemp( Ity_V128 );
11014   IRTemp vB = newTemp( Ity_V128 );
11015
11016   if (opc1 != 0x3C) {
11017      vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
11018      return False;
11019   }
11020
11021   assign( vA, getVSReg( XA ) );
11022   assign( vB, getVSReg( XB ) );
11023
11024   switch (opc2) {
11025      case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
11026      {
11027         UChar SHW = ifieldSHW ( theInstr );
11028         IRTemp result = newTemp(Ity_V128);
11029         if ( SHW != 0 ) {
11030             IRTemp hi = newTemp(Ity_V128);
11031             IRTemp lo = newTemp(Ity_V128);
11032             assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
11033             assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
11034             assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
11035         } else
11036             assign ( result, mkexpr(vA) );
11037         DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW);
11038         putVSReg( XT, mkexpr(result) );
11039         break;
11040      }
11041      case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
11042      {
11043         UChar DM = ifieldDM ( theInstr );
11044         IRTemp hi = newTemp(Ity_I64);
11045         IRTemp lo = newTemp(Ity_I64);
11046
11047         if (DM & 0x2)
11048           assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
11049         else
11050           assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
11051
11052         if (DM & 0x1)
11053           assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
11054         else
11055           assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
11056
11057         assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
11058
11059         DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM);
11060         putVSReg( XT, mkexpr( vT ) );
11061         break;
11062      }
11063      case 0x48: // xxmrghw (VSX Merge High Word)
11064      case 0xc8: // xxmrglw (VSX Merge Low Word)
11065      {
11066         char type = (opc2 == 0x48) ? 'h' : 'l';
11067         IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
11068         IRTemp a64 = newTemp(Ity_I64);
11069         IRTemp ahi32 = newTemp(Ity_I32);
11070         IRTemp alo32 = newTemp(Ity_I32);
11071         IRTemp b64 = newTemp(Ity_I64);
11072         IRTemp bhi32 = newTemp(Ity_I32);
11073         IRTemp blo32 = newTemp(Ity_I32);
11074
11075         assign( a64, unop(word_op, mkexpr(vA)) );
11076         assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
11077         assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
11078
11079         assign( b64, unop(word_op, mkexpr(vB)) );
11080         assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
11081         assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
11082
11083         assign( vT, binop(Iop_64HLtoV128,
11084                           binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
11085                           binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
11086
11087         DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB);
11088         putVSReg( XT, mkexpr( vT ) );
11089         break;
11090      }
11091      case 0x018: // xxsel (VSX Select)
11092      {
11093         UChar XC = ifieldRegXC(theInstr);
11094         IRTemp vC = newTemp( Ity_V128 );
11095         assign( vC, getVSReg( XC ) );
11096         DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC);
11097         /* vD = (vA & ~vC) | (vB & vC) */
11098         putVSReg( XT, binop(Iop_OrV128,
11099            binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
11100            binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
11101         break;
11102      }
11103      case 0x148: // xxspltw (VSX Splat Word)
11104      {
11105         UChar UIM   = ifieldRegA(theInstr) & 3;
11106         UChar sh_uim = (3 - (UIM)) * 32;
11107         DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM);
11108         putVSReg( XT,
11109                   unop( Iop_Dup32x4,
11110                         unop( Iop_V128to32,
11111                               binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
11112         break;
11113      }
11114
11115      default:
11116         vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
11117         return False;
11118   }
11119   return True;
11120}
11121
11122/*
11123  AltiVec Load Instructions
11124*/
11125static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
11126{
11127   /* X-Form */
11128   UChar opc1     = ifieldOPC(theInstr);
11129   UChar vD_addr  = ifieldRegDS(theInstr);
11130   UChar rA_addr  = ifieldRegA(theInstr);
11131   UChar rB_addr  = ifieldRegB(theInstr);
11132   UInt  opc2     = ifieldOPClo10(theInstr);
11133   UChar b0       = ifieldBIT0(theInstr);
11134
11135   IRType ty         = mode64 ? Ity_I64 : Ity_I32;
11136   IRTemp EA         = newTemp(ty);
11137   IRTemp EA_align16 = newTemp(ty);
11138
11139   if (opc1 != 0x1F || b0 != 0) {
11140      vex_printf("dis_av_load(ppc)(instr)\n");
11141      return False;
11142   }
11143
11144   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
11145   assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
11146
11147   switch (opc2) {
11148
11149   case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
11150      IRDirty* d;
11151      UInt vD_off = vectorGuestRegOffset(vD_addr);
11152      IRExpr** args = mkIRExprVec_3(
11153                         mkU32(vD_off),
11154                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
11155                                          mkU32(0xF)),
11156                         mkU32(0)/*left*/ );
11157      if (!mode64) {
11158         d = unsafeIRDirty_0_N (
11159                        0/*regparms*/,
11160                        "ppc32g_dirtyhelper_LVS",
11161                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
11162                        args );
11163      } else {
11164         d = unsafeIRDirty_0_N (
11165                        0/*regparms*/,
11166                        "ppc64g_dirtyhelper_LVS",
11167                        fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
11168                        args );
11169      }
11170      DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11171      /* declare guest state effects */
11172      d->needsBBP = True;
11173      d->nFxState = 1;
11174      d->fxState[0].fx     = Ifx_Write;
11175      d->fxState[0].offset = vD_off;
11176      d->fxState[0].size   = sizeof(U128);
11177
11178      /* execute the dirty call, side-effecting guest state */
11179      stmt( IRStmt_Dirty(d) );
11180      break;
11181   }
11182   case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
11183      IRDirty* d;
11184      UInt vD_off = vectorGuestRegOffset(vD_addr);
11185      IRExpr** args = mkIRExprVec_3(
11186                         mkU32(vD_off),
11187                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
11188                                          mkU32(0xF)),
11189                         mkU32(1)/*right*/ );
11190      if (!mode64) {
11191         d = unsafeIRDirty_0_N (
11192                        0/*regparms*/,
11193                        "ppc32g_dirtyhelper_LVS",
11194                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
11195                        args );
11196      } else {
11197         d = unsafeIRDirty_0_N (
11198                        0/*regparms*/,
11199                        "ppc64g_dirtyhelper_LVS",
11200                        fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
11201                        args );
11202      }
11203      DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11204      /* declare guest state effects */
11205      d->needsBBP = True;
11206      d->nFxState = 1;
11207      d->fxState[0].fx     = Ifx_Write;
11208      d->fxState[0].offset = vD_off;
11209      d->fxState[0].size   = sizeof(U128);
11210
11211      /* execute the dirty call, side-effecting guest state */
11212      stmt( IRStmt_Dirty(d) );
11213      break;
11214   }
11215   case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
11216      DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11217      /* loads addressed byte into vector[EA[0:3]
11218         since all other destination bytes are undefined,
11219         can simply load entire vector from 16-aligned EA */
11220      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
11221      break;
11222
11223   case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
11224      DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11225      /* see note for lvebx */
11226      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
11227      break;
11228
11229   case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
11230      DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11231      /* see note for lvebx */
11232      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
11233      break;
11234
11235   case 0x067: // lvx (Load Vector Indexed, AV p127)
11236      DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11237      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
11238      break;
11239
11240   case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
11241      DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11242      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
11243      break;
11244
11245   default:
11246      vex_printf("dis_av_load(ppc)(opc2)\n");
11247      return False;
11248   }
11249   return True;
11250}
11251
11252/*
11253  AltiVec Store Instructions
11254*/
11255static Bool dis_av_store ( UInt theInstr )
11256{
11257   /* X-Form */
11258   UChar opc1     = ifieldOPC(theInstr);
11259   UChar vS_addr  = ifieldRegDS(theInstr);
11260   UChar rA_addr  = ifieldRegA(theInstr);
11261   UChar rB_addr  = ifieldRegB(theInstr);
11262   UInt  opc2     = ifieldOPClo10(theInstr);
11263   UChar b0       = ifieldBIT0(theInstr);
11264
11265   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
11266   IRTemp EA           = newTemp(ty);
11267   IRTemp addr_aligned = newTemp(ty);
11268   IRTemp vS           = newTemp(Ity_V128);
11269   IRTemp eb           = newTemp(Ity_I8);
11270   IRTemp idx          = newTemp(Ity_I8);
11271
11272   if (opc1 != 0x1F || b0 != 0) {
11273      vex_printf("dis_av_store(ppc)(instr)\n");
11274      return False;
11275   }
11276
11277   assign( vS, getVReg(vS_addr));
11278   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
11279
11280   switch (opc2) {
11281   case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
11282      DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
11283      assign( eb, binop(Iop_And8, mkU8(0xF),
11284                        unop(Iop_32to8,
11285                             mkNarrowTo32(ty, mkexpr(EA)) )) );
11286      assign( idx, binop(Iop_Shl8,
11287                         binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
11288                         mkU8(3)) );
11289      storeBE( mkexpr(EA),
11290               unop(Iop_32to8, unop(Iop_V128to32,
11291                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
11292      break;
11293   }
11294   case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
11295      DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
11296      assign( addr_aligned, addr_align(mkexpr(EA), 2) );
11297      assign( eb, binop(Iop_And8, mkU8(0xF),
11298                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
11299      assign( idx, binop(Iop_Shl8,
11300                         binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
11301                         mkU8(3)) );
11302      storeBE( mkexpr(addr_aligned),
11303               unop(Iop_32to16, unop(Iop_V128to32,
11304                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
11305      break;
11306   }
11307   case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
11308      DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
11309      assign( addr_aligned, addr_align(mkexpr(EA), 4) );
11310      assign( eb, binop(Iop_And8, mkU8(0xF),
11311                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
11312      assign( idx, binop(Iop_Shl8,
11313                         binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
11314                         mkU8(3)) );
11315      storeBE( mkexpr(addr_aligned),
11316               unop(Iop_V128to32,
11317                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
11318      break;
11319   }
11320
11321   case 0x0E7: // stvx (Store Vector Indexed, AV p134)
11322      DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
11323      storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
11324      break;
11325
11326   case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
11327      DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
11328      storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
11329      break;
11330
11331   default:
11332      vex_printf("dis_av_store(ppc)(opc2)\n");
11333      return False;
11334   }
11335   return True;
11336}
11337
11338/*
11339  AltiVec Arithmetic Instructions
11340*/
11341static Bool dis_av_arith ( UInt theInstr )
11342{
11343   /* VX-Form */
11344   UChar opc1     = ifieldOPC(theInstr);
11345   UChar vD_addr  = ifieldRegDS(theInstr);
11346   UChar vA_addr  = ifieldRegA(theInstr);
11347   UChar vB_addr  = ifieldRegB(theInstr);
11348   UInt  opc2     = IFIELD( theInstr, 0, 11 );
11349
11350   IRTemp vA = newTemp(Ity_V128);
11351   IRTemp vB = newTemp(Ity_V128);
11352   IRTemp z3 = newTemp(Ity_I64);
11353   IRTemp z2 = newTemp(Ity_I64);
11354   IRTemp z1 = newTemp(Ity_I64);
11355   IRTemp z0 = newTemp(Ity_I64);
11356   IRTemp aEvn, aOdd;
11357   IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
11358   IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
11359   IRTemp b3, b2, b1, b0;
11360
11361   aEvn = aOdd = IRTemp_INVALID;
11362   a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
11363   a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
11364   b3 = b2 = b1 = b0 = IRTemp_INVALID;
11365
11366   assign( vA, getVReg(vA_addr));
11367   assign( vB, getVReg(vB_addr));
11368
11369   if (opc1 != 0x4) {
11370      vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
11371      return False;
11372   }
11373
11374   switch (opc2) {
11375   /* Add */
11376   case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
11377      DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11378      /* unsigned_ov(x+y) = (y >u not(x)) */
11379      putVReg( vD_addr, binop(Iop_ShrN32x4,
11380                              binop(Iop_CmpGT32Ux4, mkexpr(vB),
11381                                    unop(Iop_NotV128, mkexpr(vA))),
11382                              mkU8(31)) );
11383      break;
11384   }
11385   case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
11386      DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11387      putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
11388      break;
11389
11390   case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
11391      DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11392      putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
11393      break;
11394
11395   case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
11396      DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11397      putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
11398      break;
11399
11400   case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
11401      DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11402      putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
11403      // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
11404      break;
11405
11406   case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
11407      DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11408      putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
11409      // TODO: set VSCR[SAT]
11410      break;
11411
11412   case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
11413      DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11414      putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
11415      // TODO: set VSCR[SAT]
11416      break;
11417
11418   case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
11419      DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11420      putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
11421      // TODO: set VSCR[SAT]
11422      break;
11423
11424   case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
11425      DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11426      putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
11427      // TODO: set VSCR[SAT]
11428      break;
11429
11430   case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
11431      DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11432      putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
11433      // TODO: set VSCR[SAT]
11434      break;
11435
11436
11437   /* Subtract */
11438   case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
11439      DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11440      /* unsigned_ov(x-y) = (y >u x) */
11441      putVReg( vD_addr, binop(Iop_ShrN32x4,
11442                              unop(Iop_NotV128,
11443                                   binop(Iop_CmpGT32Ux4, mkexpr(vB),
11444                                         mkexpr(vA))),
11445                              mkU8(31)) );
11446      break;
11447   }
11448   case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
11449      DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11450      putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
11451      break;
11452
11453   case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
11454      DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11455      putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
11456      break;
11457
11458   case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
11459      DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11460      putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
11461      break;
11462
11463   case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
11464      DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11465      putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
11466      // TODO: set VSCR[SAT]
11467      break;
11468
11469   case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
11470      DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11471      putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
11472      // TODO: set VSCR[SAT]
11473      break;
11474
11475   case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
11476      DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11477      putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
11478      // TODO: set VSCR[SAT]
11479      break;
11480
11481   case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
11482      DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11483      putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
11484      // TODO: set VSCR[SAT]
11485      break;
11486
11487   case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
11488      DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11489      putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
11490      // TODO: set VSCR[SAT]
11491      break;
11492
11493   case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
11494      DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11495      putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
11496      // TODO: set VSCR[SAT]
11497      break;
11498
11499
11500   /* Maximum */
11501   case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
11502      DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11503      putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
11504      break;
11505
11506   case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
11507      DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11508      putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
11509      break;
11510
11511   case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
11512      DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11513      putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
11514      break;
11515
11516   case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
11517      DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11518      putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
11519      break;
11520
11521   case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
11522      DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11523      putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
11524      break;
11525
11526   case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
11527      DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11528      putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
11529      break;
11530
11531
11532   /* Minimum */
11533   case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
11534      DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11535      putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
11536      break;
11537
11538   case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
11539      DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11540      putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
11541      break;
11542
11543   case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
11544      DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11545      putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
11546      break;
11547
11548   case 0x302: // vminsb (Minimum Signed Byte, AV p188)
11549      DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11550      putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
11551      break;
11552
11553   case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
11554      DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11555      putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
11556      break;
11557
11558   case 0x382: // vminsw (Minimum Signed Word, AV p190)
11559      DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11560      putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
11561      break;
11562
11563
11564   /* Average */
11565   case 0x402: // vavgub (Average Unsigned Byte, AV p152)
11566      DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11567      putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
11568      break;
11569
11570   case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
11571      DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11572      putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
11573      break;
11574
11575   case 0x482: // vavguw (Average Unsigned Word, AV p154)
11576      DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11577      putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
11578      break;
11579
11580   case 0x502: // vavgsb (Average Signed Byte, AV p149)
11581      DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11582      putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
11583      break;
11584
11585   case 0x542: // vavgsh (Average Signed Half Word, AV p150)
11586      DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11587      putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
11588      break;
11589
11590   case 0x582: // vavgsw (Average Signed Word, AV p151)
11591      DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11592      putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
11593      break;
11594
11595
11596   /* Multiply */
11597   case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
11598      DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11599      putVReg( vD_addr,
11600               binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
11601      break;
11602
11603   case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
11604      DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11605      putVReg( vD_addr,
11606               binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
11607      break;
11608
11609   case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
11610      DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11611      putVReg( vD_addr,
11612               binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
11613      break;
11614
11615   case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
11616      DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11617      putVReg( vD_addr,
11618               binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
11619      break;
11620
11621   case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
11622      DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11623      putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
11624      break;
11625
11626   case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
11627      DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11628      putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
11629      break;
11630
11631   case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
11632      DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11633      putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
11634      break;
11635
11636   case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
11637      DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11638      putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
11639      break;
11640
11641
11642   /* Sum Across Partial */
11643   case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
11644      IRTemp aEE, aEO, aOE, aOO;
11645      aEE = aEO = aOE = aOO = IRTemp_INVALID;
11646      DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11647
11648      /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
11649      expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
11650      expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
11651      expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
11652
11653      /* break V128 to 4xI32's, zero-extending to I64's */
11654      breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
11655      breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
11656      breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
11657      breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
11658      breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
11659
11660      /* add lanes */
11661      assign( z3, binop(Iop_Add64, mkexpr(b3),
11662                     binop(Iop_Add64,
11663                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
11664                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
11665      assign( z2, binop(Iop_Add64, mkexpr(b2),
11666                     binop(Iop_Add64,
11667                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
11668                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
11669      assign( z1, binop(Iop_Add64, mkexpr(b1),
11670                     binop(Iop_Add64,
11671                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
11672                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
11673      assign( z0, binop(Iop_Add64, mkexpr(b0),
11674                     binop(Iop_Add64,
11675                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
11676                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
11677
11678      /* saturate-narrow to 32bit, and combine to V128 */
11679      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
11680                                         mkexpr(z1), mkexpr(z0)) );
11681      break;
11682   }
11683   case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
11684      IRTemp aEE, aEO, aOE, aOO;
11685      aEE = aEO = aOE = aOO = IRTemp_INVALID;
11686      DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11687
11688      /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
11689      expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
11690      expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
11691      expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
11692
11693      /* break V128 to 4xI32's, sign-extending to I64's */
11694      breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
11695      breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
11696      breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
11697      breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
11698      breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
11699
11700      /* add lanes */
11701      assign( z3, binop(Iop_Add64, mkexpr(b3),
11702                     binop(Iop_Add64,
11703                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
11704                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
11705      assign( z2, binop(Iop_Add64, mkexpr(b2),
11706                     binop(Iop_Add64,
11707                        binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
11708                        binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
11709      assign( z1, binop(Iop_Add64, mkexpr(b1),
11710                     binop(Iop_Add64,
11711                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
11712                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
11713      assign( z0, binop(Iop_Add64, mkexpr(b0),
11714                     binop(Iop_Add64,
11715                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
11716                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
11717
11718      /* saturate-narrow to 32bit, and combine to V128 */
11719      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
11720                                         mkexpr(z1), mkexpr(z0)) );
11721      break;
11722   }
11723   case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
11724      DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11725
11726      /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
11727      expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
11728
11729      /* break V128 to 4xI32's, sign-extending to I64's */
11730      breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
11731      breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
11732      breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
11733
11734      /* add lanes */
11735      assign( z3, binop(Iop_Add64, mkexpr(b3),
11736                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
11737      assign( z2, binop(Iop_Add64, mkexpr(b2),
11738                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
11739      assign( z1, binop(Iop_Add64, mkexpr(b1),
11740                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
11741      assign( z0, binop(Iop_Add64, mkexpr(b0),
11742                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
11743
11744      /* saturate-narrow to 32bit, and combine to V128 */
11745      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
11746                                         mkexpr(z1), mkexpr(z0)) );
11747      break;
11748   }
11749   case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
11750      DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11751
11752      /* break V128 to 4xI32's, sign-extending to I64's */
11753      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
11754      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
11755
11756      /* add lanes */
11757      assign( z2, binop(Iop_Add64, mkexpr(b2),
11758                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
11759      assign( z0, binop(Iop_Add64, mkexpr(b0),
11760                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
11761
11762      /* saturate-narrow to 32bit, and combine to V128 */
11763      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
11764                                         mkU64(0), mkexpr(z0)) );
11765      break;
11766   }
11767   case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
11768      DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11769
11770      /* break V128 to 4xI32's, sign-extending to I64's */
11771      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
11772      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
11773
11774      /* add lanes */
11775      assign( z0, binop(Iop_Add64, mkexpr(b0),
11776                     binop(Iop_Add64,
11777                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
11778                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
11779
11780      /* saturate-narrow to 32bit, and combine to V128 */
11781      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
11782                                         mkU64(0), mkexpr(z0)) );
11783      break;
11784   }
11785   default:
11786      vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
11787      return False;
11788   }
11789   return True;
11790}
11791
11792/*
11793  AltiVec Logic Instructions
11794*/
11795static Bool dis_av_logic ( UInt theInstr )
11796{
11797   /* VX-Form */
11798   UChar opc1    = ifieldOPC(theInstr);
11799   UChar vD_addr = ifieldRegDS(theInstr);
11800   UChar vA_addr = ifieldRegA(theInstr);
11801   UChar vB_addr = ifieldRegB(theInstr);
11802   UInt  opc2    = IFIELD( theInstr, 0, 11 );
11803
11804   IRTemp vA = newTemp(Ity_V128);
11805   IRTemp vB = newTemp(Ity_V128);
11806   assign( vA, getVReg(vA_addr));
11807   assign( vB, getVReg(vB_addr));
11808
11809   if (opc1 != 0x4) {
11810      vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
11811      return False;
11812   }
11813
11814   switch (opc2) {
11815   case 0x404: // vand (And, AV p147)
11816      DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11817      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
11818      break;
11819
11820   case 0x444: // vandc (And, AV p148)
11821      DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11822      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
11823                              unop(Iop_NotV128, mkexpr(vB))) );
11824      break;
11825
11826   case 0x484: // vor (Or, AV p217)
11827      DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11828      putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
11829      break;
11830
11831   case 0x4C4: // vxor (Xor, AV p282)
11832      DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11833      putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
11834      break;
11835
11836   case 0x504: // vnor (Nor, AV p216)
11837      DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11838      putVReg( vD_addr,
11839         unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
11840      break;
11841
11842   default:
11843      vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
11844      return False;
11845   }
11846   return True;
11847}
11848
11849/*
11850  AltiVec Compare Instructions
11851*/
11852static Bool dis_av_cmp ( UInt theInstr )
11853{
11854   /* VXR-Form */
11855   UChar opc1     = ifieldOPC(theInstr);
11856   UChar vD_addr  = ifieldRegDS(theInstr);
11857   UChar vA_addr  = ifieldRegA(theInstr);
11858   UChar vB_addr  = ifieldRegB(theInstr);
11859   UChar flag_rC  = ifieldBIT10(theInstr);
11860   UInt  opc2     = IFIELD( theInstr, 0, 10 );
11861
11862   IRTemp vA = newTemp(Ity_V128);
11863   IRTemp vB = newTemp(Ity_V128);
11864   IRTemp vD = newTemp(Ity_V128);
11865   assign( vA, getVReg(vA_addr));
11866   assign( vB, getVReg(vB_addr));
11867
11868   if (opc1 != 0x4) {
11869      vex_printf("dis_av_cmp(ppc)(instr)\n");
11870      return False;
11871   }
11872
11873   switch (opc2) {
11874   case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
11875      DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11876                                      vD_addr, vA_addr, vB_addr);
11877      assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
11878      break;
11879
11880   case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
11881      DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11882                                      vD_addr, vA_addr, vB_addr);
11883      assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
11884      break;
11885
11886   case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
11887      DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11888                                      vD_addr, vA_addr, vB_addr);
11889      assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
11890      break;
11891
11892   case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
11893      DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11894                                      vD_addr, vA_addr, vB_addr);
11895      assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
11896      break;
11897
11898   case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
11899      DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11900                                      vD_addr, vA_addr, vB_addr);
11901      assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
11902      break;
11903
11904   case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
11905      DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11906                                       vD_addr, vA_addr, vB_addr);
11907      assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
11908      break;
11909
11910   case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
11911      DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11912                                       vD_addr, vA_addr, vB_addr);
11913      assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
11914      break;
11915
11916   case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
11917      DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11918                                      vD_addr, vA_addr, vB_addr);
11919      assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
11920      break;
11921
11922   case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
11923      DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11924                                      vD_addr, vA_addr, vB_addr);
11925      assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
11926      break;
11927
11928   default:
11929      vex_printf("dis_av_cmp(ppc)(opc2)\n");
11930      return False;
11931   }
11932
11933   putVReg( vD_addr, mkexpr(vD) );
11934
11935   if (flag_rC) {
11936      set_AV_CR6( mkexpr(vD), True );
11937   }
11938   return True;
11939}
11940
11941/*
11942  AltiVec Multiply-Sum Instructions
11943*/
11944static Bool dis_av_multarith ( UInt theInstr )
11945{
11946   /* VA-Form */
11947   UChar opc1     = ifieldOPC(theInstr);
11948   UChar vD_addr  = ifieldRegDS(theInstr);
11949   UChar vA_addr  = ifieldRegA(theInstr);
11950   UChar vB_addr  = ifieldRegB(theInstr);
11951   UChar vC_addr  = ifieldRegC(theInstr);
11952   UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
11953
11954   IRTemp vA    = newTemp(Ity_V128);
11955   IRTemp vB    = newTemp(Ity_V128);
11956   IRTemp vC    = newTemp(Ity_V128);
11957   IRTemp zeros = newTemp(Ity_V128);
11958   IRTemp aLo   = newTemp(Ity_V128);
11959   IRTemp bLo   = newTemp(Ity_V128);
11960   IRTemp cLo   = newTemp(Ity_V128);
11961   IRTemp zLo   = newTemp(Ity_V128);
11962   IRTemp aHi   = newTemp(Ity_V128);
11963   IRTemp bHi   = newTemp(Ity_V128);
11964   IRTemp cHi   = newTemp(Ity_V128);
11965   IRTemp zHi   = newTemp(Ity_V128);
11966   IRTemp abEvn = newTemp(Ity_V128);
11967   IRTemp abOdd = newTemp(Ity_V128);
11968   IRTemp z3    = newTemp(Ity_I64);
11969   IRTemp z2    = newTemp(Ity_I64);
11970   IRTemp z1    = newTemp(Ity_I64);
11971   IRTemp z0    = newTemp(Ity_I64);
11972   IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
11973   IRTemp c3, c2, c1, c0;
11974
11975   ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
11976   c3 = c2 = c1 = c0 = IRTemp_INVALID;
11977
11978   assign( vA, getVReg(vA_addr));
11979   assign( vB, getVReg(vB_addr));
11980   assign( vC, getVReg(vC_addr));
11981   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
11982
11983   if (opc1 != 0x4) {
11984      vex_printf("dis_av_multarith(ppc)(instr)\n");
11985      return False;
11986   }
11987
11988   switch (opc2) {
11989   /* Multiply-Add */
11990   case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
11991      IRTemp cSigns = newTemp(Ity_V128);
11992      DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
11993          vD_addr, vA_addr, vB_addr, vC_addr);
11994      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
11995      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
11996      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
11997      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
11998      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
11999      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
12000      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
12001
12002      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
12003                         binop(Iop_SarN32x4,
12004                               binop(Iop_MullEven16Sx8,
12005                                     mkexpr(aLo), mkexpr(bLo)),
12006                               mkU8(15))) );
12007
12008      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
12009                         binop(Iop_SarN32x4,
12010                               binop(Iop_MullEven16Sx8,
12011                                     mkexpr(aHi), mkexpr(bHi)),
12012                               mkU8(15))) );
12013
12014      putVReg( vD_addr,
12015               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
12016      break;
12017   }
12018   case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
12019      IRTemp zKonst = newTemp(Ity_V128);
12020      IRTemp cSigns = newTemp(Ity_V128);
12021      DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
12022          vD_addr, vA_addr, vB_addr, vC_addr);
12023      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
12024      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
12025      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
12026      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
12027      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
12028      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
12029      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
12030
12031      /* shifting our const avoids store/load version of Dup */
12032      assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
12033                            mkU8(14)) );
12034
12035      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
12036                         binop(Iop_SarN32x4,
12037                               binop(Iop_Add32x4, mkexpr(zKonst),
12038                                     binop(Iop_MullEven16Sx8,
12039                                           mkexpr(aLo), mkexpr(bLo))),
12040                               mkU8(15))) );
12041
12042      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
12043                         binop(Iop_SarN32x4,
12044                               binop(Iop_Add32x4, mkexpr(zKonst),
12045                                     binop(Iop_MullEven16Sx8,
12046                                           mkexpr(aHi), mkexpr(bHi))),
12047                               mkU8(15))) );
12048
12049      putVReg( vD_addr,
12050               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
12051      break;
12052   }
12053   case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
12054      DIP("vmladduhm v%d,v%d,v%d,v%d\n",
12055          vD_addr, vA_addr, vB_addr, vC_addr);
12056      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
12057      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
12058      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
12059      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
12060      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
12061      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
12062      assign(zLo, binop(Iop_Add32x4,
12063                     binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
12064                     mkexpr(cLo)) );
12065      assign(zHi, binop(Iop_Add32x4,
12066                     binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
12067                     mkexpr(cHi)));
12068      putVReg( vD_addr,
12069               binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
12070      break;
12071   }
12072
12073
12074   /* Multiply-Sum */
12075   case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
12076      IRTemp abEE, abEO, abOE, abOO;
12077      abEE = abEO = abOE = abOO = IRTemp_INVALID;
12078      DIP("vmsumubm v%d,v%d,v%d,v%d\n",
12079          vD_addr, vA_addr, vB_addr, vC_addr);
12080
12081      /* multiply vA,vB (unsigned, widening) */
12082      assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
12083      assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
12084
12085      /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
12086      expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
12087      expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
12088
12089      putVReg( vD_addr,
12090         binop(Iop_Add32x4, mkexpr(vC),
12091               binop(Iop_Add32x4,
12092                     binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
12093                     binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
12094      break;
12095   }
12096   case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
12097      IRTemp aEvn, aOdd, bEvn, bOdd;
12098      IRTemp abEE = newTemp(Ity_V128);
12099      IRTemp abEO = newTemp(Ity_V128);
12100      IRTemp abOE = newTemp(Ity_V128);
12101      IRTemp abOO = newTemp(Ity_V128);
12102      aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
12103      DIP("vmsummbm v%d,v%d,v%d,v%d\n",
12104          vD_addr, vA_addr, vB_addr, vC_addr);
12105
12106      /* sign-extend vA, zero-extend vB, for mixed-sign multiply
12107         (separating out adjacent lanes to different vectors) */
12108      expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
12109      expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
12110
12111      /* multiply vA, vB, again separating adjacent lanes */
12112      assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
12113      assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
12114      assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
12115      assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
12116
12117      /* add results together, + vC */
12118      putVReg( vD_addr,
12119         binop(Iop_QAdd32Sx4, mkexpr(vC),
12120               binop(Iop_QAdd32Sx4,
12121                     binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
12122                     binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
12123      break;
12124   }
12125   case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
12126      DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
12127          vD_addr, vA_addr, vB_addr, vC_addr);
12128      assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
12129      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
12130      putVReg( vD_addr,
12131         binop(Iop_Add32x4, mkexpr(vC),
12132               binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
12133      break;
12134   }
12135   case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
12136      DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
12137          vD_addr, vA_addr, vB_addr, vC_addr);
12138      /* widening multiply, separating lanes */
12139      assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
12140      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
12141
12142      /* break V128 to 4xI32's, zero-extending to I64's */
12143      breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
12144      breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
12145      breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
12146
12147      /* add lanes */
12148      assign( z3, binop(Iop_Add64, mkexpr(c3),
12149                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
12150      assign( z2, binop(Iop_Add64, mkexpr(c2),
12151                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
12152      assign( z1, binop(Iop_Add64, mkexpr(c1),
12153                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
12154      assign( z0, binop(Iop_Add64, mkexpr(c0),
12155                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
12156
12157      /* saturate-narrow to 32bit, and combine to V128 */
12158      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
12159                                         mkexpr(z1), mkexpr(z0)) );
12160
12161      break;
12162   }
12163   case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
12164      DIP("vmsumshm v%d,v%d,v%d,v%d\n",
12165          vD_addr, vA_addr, vB_addr, vC_addr);
12166      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
12167      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
12168      putVReg( vD_addr,
12169         binop(Iop_Add32x4, mkexpr(vC),
12170               binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
12171      break;
12172   }
12173   case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
12174      DIP("vmsumshs v%d,v%d,v%d,v%d\n",
12175          vD_addr, vA_addr, vB_addr, vC_addr);
12176      /* widening multiply, separating lanes */
12177      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
12178      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
12179
12180      /* break V128 to 4xI32's, sign-extending to I64's */
12181      breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
12182      breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
12183      breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
12184
12185      /* add lanes */
12186      assign( z3, binop(Iop_Add64, mkexpr(c3),
12187                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
12188      assign( z2, binop(Iop_Add64, mkexpr(c2),
12189                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
12190      assign( z1, binop(Iop_Add64, mkexpr(c1),
12191                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
12192      assign( z0, binop(Iop_Add64, mkexpr(c0),
12193                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
12194
12195      /* saturate-narrow to 32bit, and combine to V128 */
12196      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
12197                                         mkexpr(z1), mkexpr(z0)) );
12198      break;
12199   }
12200   default:
12201      vex_printf("dis_av_multarith(ppc)(opc2)\n");
12202      return False;
12203   }
12204   return True;
12205}
12206
12207/*
12208  AltiVec Shift/Rotate Instructions
12209*/
12210static Bool dis_av_shift ( UInt theInstr )
12211{
12212   /* VX-Form */
12213   UChar opc1    = ifieldOPC(theInstr);
12214   UChar vD_addr = ifieldRegDS(theInstr);
12215   UChar vA_addr = ifieldRegA(theInstr);
12216   UChar vB_addr = ifieldRegB(theInstr);
12217   UInt  opc2    = IFIELD( theInstr, 0, 11 );
12218
12219   IRTemp vA = newTemp(Ity_V128);
12220   IRTemp vB = newTemp(Ity_V128);
12221   assign( vA, getVReg(vA_addr));
12222   assign( vB, getVReg(vB_addr));
12223
12224   if (opc1 != 0x4){
12225      vex_printf("dis_av_shift(ppc)(instr)\n");
12226      return False;
12227   }
12228
12229   switch (opc2) {
12230   /* Rotate */
12231   case 0x004: // vrlb (Rotate Left Integer B, AV p234)
12232      DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12233      putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
12234      break;
12235
12236   case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
12237      DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12238      putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
12239      break;
12240
12241   case 0x084: // vrlw (Rotate Left Integer W, AV p236)
12242      DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12243      putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
12244      break;
12245
12246
12247   /* Shift Left */
12248   case 0x104: // vslb (Shift Left Integer B, AV p240)
12249      DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12250      putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
12251      break;
12252
12253   case 0x144: // vslh (Shift Left Integer HW, AV p242)
12254      DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12255      putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
12256      break;
12257
12258   case 0x184: // vslw (Shift Left Integer W, AV p244)
12259      DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12260      putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
12261      break;
12262
12263   case 0x1C4: { // vsl (Shift Left, AV p239)
12264      IRTemp sh = newTemp(Ity_I8);
12265      DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12266      assign( sh, binop(Iop_And8, mkU8(0x7),
12267                        unop(Iop_32to8,
12268                             unop(Iop_V128to32, mkexpr(vB)))) );
12269      putVReg( vD_addr,
12270               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
12271      break;
12272   }
12273   case 0x40C: { // vslo (Shift Left by Octet, AV p243)
12274      IRTemp sh = newTemp(Ity_I8);
12275      DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12276      assign( sh, binop(Iop_And8, mkU8(0x78),
12277                        unop(Iop_32to8,
12278                             unop(Iop_V128to32, mkexpr(vB)))) );
12279      putVReg( vD_addr,
12280               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
12281      break;
12282   }
12283
12284
12285   /* Shift Right */
12286   case 0x204: // vsrb (Shift Right B, AV p256)
12287      DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12288      putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
12289      break;
12290
12291   case 0x244: // vsrh (Shift Right HW, AV p257)
12292      DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12293      putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
12294      break;
12295
12296   case 0x284: // vsrw (Shift Right W, AV p259)
12297      DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12298      putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
12299      break;
12300
12301   case 0x2C4: { // vsr (Shift Right, AV p251)
12302      IRTemp sh = newTemp(Ity_I8);
12303      DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12304      assign( sh, binop(Iop_And8, mkU8(0x7),
12305                        unop(Iop_32to8,
12306                             unop(Iop_V128to32, mkexpr(vB)))) );
12307      putVReg( vD_addr,
12308               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
12309      break;
12310   }
12311   case 0x304: // vsrab (Shift Right Alg B, AV p253)
12312      DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12313      putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
12314      break;
12315
12316   case 0x344: // vsrah (Shift Right Alg HW, AV p254)
12317      DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12318      putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
12319      break;
12320
12321   case 0x384: // vsraw (Shift Right Alg W, AV p255)
12322      DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12323      putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
12324      break;
12325
12326   case 0x44C: { // vsro (Shift Right by Octet, AV p258)
12327      IRTemp sh = newTemp(Ity_I8);
12328      DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12329      assign( sh, binop(Iop_And8, mkU8(0x78),
12330                        unop(Iop_32to8,
12331                             unop(Iop_V128to32, mkexpr(vB)))) );
12332      putVReg( vD_addr,
12333               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
12334      break;
12335   }
12336
12337   default:
12338      vex_printf("dis_av_shift(ppc)(opc2)\n");
12339      return False;
12340   }
12341   return True;
12342}
12343
12344/*
12345  AltiVec Permute Instructions
12346*/
12347static Bool dis_av_permute ( UInt theInstr )
12348{
12349   /* VA-Form, VX-Form */
12350   UChar opc1      = ifieldOPC(theInstr);
12351   UChar vD_addr   = ifieldRegDS(theInstr);
12352   UChar vA_addr   = ifieldRegA(theInstr);
12353   UChar UIMM_5    = vA_addr;
12354   UChar vB_addr   = ifieldRegB(theInstr);
12355   UChar vC_addr   = ifieldRegC(theInstr);
12356   UChar b10       = ifieldBIT10(theInstr);
12357   UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
12358   UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
12359
12360   UChar SIMM_8 = extend_s_5to8(UIMM_5);
12361
12362   IRTemp vA = newTemp(Ity_V128);
12363   IRTemp vB = newTemp(Ity_V128);
12364   IRTemp vC = newTemp(Ity_V128);
12365   assign( vA, getVReg(vA_addr));
12366   assign( vB, getVReg(vB_addr));
12367   assign( vC, getVReg(vC_addr));
12368
12369   if (opc1 != 0x4) {
12370      vex_printf("dis_av_permute(ppc)(instr)\n");
12371      return False;
12372   }
12373
12374   switch (opc2) {
12375   case 0x2A: // vsel (Conditional Select, AV p238)
12376      DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
12377      /* vD = (vA & ~vC) | (vB & vC) */
12378      putVReg( vD_addr, binop(Iop_OrV128,
12379         binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
12380         binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
12381      return True;
12382
12383   case 0x2B: { // vperm (Permute, AV p218)
12384      /* limited to two args for IR, so have to play games... */
12385      IRTemp a_perm  = newTemp(Ity_V128);
12386      IRTemp b_perm  = newTemp(Ity_V128);
12387      IRTemp mask    = newTemp(Ity_V128);
12388      IRTemp vC_andF = newTemp(Ity_V128);
12389      DIP("vperm v%d,v%d,v%d,v%d\n",
12390          vD_addr, vA_addr, vB_addr, vC_addr);
12391      /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
12392         IR specifies, and also to hide irrelevant bits from
12393         memcheck */
12394      assign( vC_andF,
12395              binop(Iop_AndV128, mkexpr(vC),
12396                                 unop(Iop_Dup8x16, mkU8(0xF))) );
12397      assign( a_perm,
12398              binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
12399      assign( b_perm,
12400              binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
12401      // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
12402      assign( mask, binop(Iop_SarN8x16,
12403                          binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
12404                          mkU8(7)) );
12405      // dst = (a & ~mask) | (b & mask)
12406      putVReg( vD_addr, binop(Iop_OrV128,
12407                              binop(Iop_AndV128, mkexpr(a_perm),
12408                                    unop(Iop_NotV128, mkexpr(mask))),
12409                              binop(Iop_AndV128, mkexpr(b_perm),
12410                                    mkexpr(mask))) );
12411      return True;
12412   }
12413   case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
12414      if (b10 != 0) {
12415         vex_printf("dis_av_permute(ppc)(vsldoi)\n");
12416         return False;
12417      }
12418      DIP("vsldoi v%d,v%d,v%d,%d\n",
12419          vD_addr, vA_addr, vB_addr, SHB_uimm4);
12420      if (SHB_uimm4 == 0)
12421         putVReg( vD_addr, mkexpr(vA) );
12422      else
12423         putVReg( vD_addr,
12424            binop(Iop_OrV128,
12425                  binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
12426                  binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
12427      return True;
12428
12429   default:
12430     break; // Fall through...
12431   }
12432
12433   opc2 = IFIELD( theInstr, 0, 11 );
12434   switch (opc2) {
12435
12436   /* Merge */
12437   case 0x00C: // vmrghb (Merge High B, AV p195)
12438      DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12439      putVReg( vD_addr,
12440               binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
12441      break;
12442
12443   case 0x04C: // vmrghh (Merge High HW, AV p196)
12444      DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12445      putVReg( vD_addr,
12446               binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
12447      break;
12448
12449   case 0x08C: // vmrghw (Merge High W, AV p197)
12450      DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12451      putVReg( vD_addr,
12452               binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
12453      break;
12454
12455   case 0x10C: // vmrglb (Merge Low B, AV p198)
12456      DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12457      putVReg( vD_addr,
12458               binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
12459      break;
12460
12461   case 0x14C: // vmrglh (Merge Low HW, AV p199)
12462      DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12463      putVReg( vD_addr,
12464               binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
12465      break;
12466
12467   case 0x18C: // vmrglw (Merge Low W, AV p200)
12468      DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12469      putVReg( vD_addr,
12470               binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
12471      break;
12472
12473
12474   /* Splat */
12475   case 0x20C: { // vspltb (Splat Byte, AV p245)
12476      /* vD = Dup8x16( vB[UIMM_5] ) */
12477      UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
12478      DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
12479      putVReg( vD_addr, unop(Iop_Dup8x16,
12480           unop(Iop_32to8, unop(Iop_V128to32,
12481                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
12482      break;
12483   }
12484   case 0x24C: { // vsplth (Splat Half Word, AV p246)
12485      UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
12486      DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
12487      putVReg( vD_addr, unop(Iop_Dup16x8,
12488           unop(Iop_32to16, unop(Iop_V128to32,
12489                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
12490      break;
12491   }
12492   case 0x28C: { // vspltw (Splat Word, AV p250)
12493      /* vD = Dup32x4( vB[UIMM_5] ) */
12494      UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
12495      DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
12496      putVReg( vD_addr, unop(Iop_Dup32x4,
12497         unop(Iop_V128to32,
12498              binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
12499      break;
12500   }
12501   case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
12502      DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
12503      putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
12504      break;
12505
12506   case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
12507      DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
12508      putVReg( vD_addr,
12509               unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
12510      break;
12511
12512   case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
12513      DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
12514      putVReg( vD_addr,
12515               unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
12516      break;
12517
12518   default:
12519      vex_printf("dis_av_permute(ppc)(opc2)\n");
12520      return False;
12521   }
12522   return True;
12523}
12524
12525/*
12526  AltiVec Pack/Unpack Instructions
12527*/
12528static Bool dis_av_pack ( UInt theInstr )
12529{
12530   /* VX-Form */
12531   UChar opc1     = ifieldOPC(theInstr);
12532   UChar vD_addr  = ifieldRegDS(theInstr);
12533   UChar vA_addr  = ifieldRegA(theInstr);
12534   UChar vB_addr  = ifieldRegB(theInstr);
12535   UInt  opc2     = IFIELD( theInstr, 0, 11 );
12536
12537   IRTemp signs = IRTemp_INVALID;
12538   IRTemp zeros = IRTemp_INVALID;
12539   IRTemp vA    = newTemp(Ity_V128);
12540   IRTemp vB    = newTemp(Ity_V128);
12541   assign( vA, getVReg(vA_addr));
12542   assign( vB, getVReg(vB_addr));
12543
12544   if (opc1 != 0x4) {
12545      vex_printf("dis_av_pack(ppc)(instr)\n");
12546      return False;
12547   }
12548
12549   switch (opc2) {
12550   /* Packing */
12551   case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
12552      DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12553      putVReg( vD_addr,
12554               binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
12555      return True;
12556
12557   case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
12558      DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12559      putVReg( vD_addr,
12560               binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
12561      return True;
12562
12563   case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
12564      DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12565      putVReg( vD_addr,
12566               binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
12567      // TODO: set VSCR[SAT]
12568      return True;
12569
12570   case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
12571      DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12572      putVReg( vD_addr,
12573               binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
12574      // TODO: set VSCR[SAT]
12575      return True;
12576
12577   case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
12578      // This insn does a signed->unsigned saturating conversion.
12579      // Conversion done here, then uses unsigned->unsigned vpk insn:
12580      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
12581      IRTemp vA_tmp = newTemp(Ity_V128);
12582      IRTemp vB_tmp = newTemp(Ity_V128);
12583      DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12584      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
12585                            unop(Iop_NotV128,
12586                                 binop(Iop_SarN16x8,
12587                                       mkexpr(vA), mkU8(15)))) );
12588      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
12589                            unop(Iop_NotV128,
12590                                 binop(Iop_SarN16x8,
12591                                       mkexpr(vB), mkU8(15)))) );
12592      putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
12593                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
12594      // TODO: set VSCR[SAT]
12595      return True;
12596   }
12597   case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
12598      // This insn does a signed->unsigned saturating conversion.
12599      // Conversion done here, then uses unsigned->unsigned vpk insn:
12600      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
12601      IRTemp vA_tmp = newTemp(Ity_V128);
12602      IRTemp vB_tmp = newTemp(Ity_V128);
12603      DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12604      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
12605                            unop(Iop_NotV128,
12606                                 binop(Iop_SarN32x4,
12607                                       mkexpr(vA), mkU8(31)))) );
12608      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
12609                            unop(Iop_NotV128,
12610                                 binop(Iop_SarN32x4,
12611                                       mkexpr(vB), mkU8(31)))) );
12612      putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
12613                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
12614      // TODO: set VSCR[SAT]
12615      return True;
12616   }
12617   case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
12618      DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12619      putVReg( vD_addr,
12620               binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
12621      // TODO: set VSCR[SAT]
12622      return True;
12623
12624   case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
12625      DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12626      putVReg( vD_addr,
12627               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
12628      // TODO: set VSCR[SAT]
12629      return True;
12630
12631   case 0x30E: { // vpkpx (Pack Pixel, AV p219)
12632      /* CAB: Worth a new primop? */
12633      /* Using shifts to compact pixel elements, then packing them */
12634      IRTemp a1 = newTemp(Ity_V128);
12635      IRTemp a2 = newTemp(Ity_V128);
12636      IRTemp a3 = newTemp(Ity_V128);
12637      IRTemp a_tmp = newTemp(Ity_V128);
12638      IRTemp b1 = newTemp(Ity_V128);
12639      IRTemp b2 = newTemp(Ity_V128);
12640      IRTemp b3 = newTemp(Ity_V128);
12641      IRTemp b_tmp = newTemp(Ity_V128);
12642      DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12643      assign( a1, binop(Iop_ShlN16x8,
12644                        binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
12645                        mkU8(10)) );
12646      assign( a2, binop(Iop_ShlN16x8,
12647                        binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
12648                        mkU8(5)) );
12649      assign( a3,  binop(Iop_ShrN16x8,
12650                         binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
12651                         mkU8(11)) );
12652      assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
12653                           binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
12654
12655      assign( b1, binop(Iop_ShlN16x8,
12656                        binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
12657                        mkU8(10)) );
12658      assign( b2, binop(Iop_ShlN16x8,
12659                        binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
12660                        mkU8(5)) );
12661      assign( b3,  binop(Iop_ShrN16x8,
12662                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
12663                         mkU8(11)) );
12664      assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
12665                           binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
12666
12667      putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
12668                              mkexpr(a_tmp), mkexpr(b_tmp)) );
12669      return True;
12670   }
12671
12672   default:
12673      break; // Fall through...
12674   }
12675
12676
12677   if (vA_addr != 0) {
12678      vex_printf("dis_av_pack(ppc)(vA_addr)\n");
12679      return False;
12680   }
12681
12682   signs = newTemp(Ity_V128);
12683   zeros = newTemp(Ity_V128);
12684   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
12685
12686   switch (opc2) {
12687   /* Unpacking */
12688   case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
12689      DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
12690      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
12691      putVReg( vD_addr,
12692               binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
12693      break;
12694   }
12695   case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
12696      DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
12697      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
12698      putVReg( vD_addr,
12699               binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
12700      break;
12701   }
12702   case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
12703      DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
12704      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
12705      putVReg( vD_addr,
12706               binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
12707      break;
12708   }
12709   case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
12710      DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
12711      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
12712      putVReg( vD_addr,
12713               binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
12714      break;
12715   }
12716   case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
12717      /* CAB: Worth a new primop? */
12718      /* Using shifts to isolate pixel elements, then expanding them */
12719      IRTemp z0  = newTemp(Ity_V128);
12720      IRTemp z1  = newTemp(Ity_V128);
12721      IRTemp z01 = newTemp(Ity_V128);
12722      IRTemp z2  = newTemp(Ity_V128);
12723      IRTemp z3  = newTemp(Ity_V128);
12724      IRTemp z23 = newTemp(Ity_V128);
12725      DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
12726      assign( z0,  binop(Iop_ShlN16x8,
12727                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
12728                         mkU8(8)) );
12729      assign( z1,  binop(Iop_ShrN16x8,
12730                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
12731                         mkU8(11)) );
12732      assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
12733                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
12734      assign( z2,  binop(Iop_ShrN16x8,
12735                         binop(Iop_ShlN16x8,
12736                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
12737                               mkU8(11)),
12738                         mkU8(3)) );
12739      assign( z3,  binop(Iop_ShrN16x8,
12740                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
12741                         mkU8(11)) );
12742      assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
12743                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
12744      putVReg( vD_addr,
12745               binop(Iop_OrV128,
12746                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
12747                     mkexpr(z23)) );
12748      break;
12749   }
12750   case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
12751      /* identical to vupkhpx, except interleaving LO */
12752      IRTemp z0  = newTemp(Ity_V128);
12753      IRTemp z1  = newTemp(Ity_V128);
12754      IRTemp z01 = newTemp(Ity_V128);
12755      IRTemp z2  = newTemp(Ity_V128);
12756      IRTemp z3  = newTemp(Ity_V128);
12757      IRTemp z23 = newTemp(Ity_V128);
12758      DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
12759      assign( z0,  binop(Iop_ShlN16x8,
12760                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
12761                         mkU8(8)) );
12762      assign( z1,  binop(Iop_ShrN16x8,
12763                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
12764                         mkU8(11)) );
12765      assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
12766                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
12767      assign( z2,  binop(Iop_ShrN16x8,
12768                         binop(Iop_ShlN16x8,
12769                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
12770                               mkU8(11)),
12771                         mkU8(3)) );
12772      assign( z3,  binop(Iop_ShrN16x8,
12773                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
12774                         mkU8(11)) );
12775      assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
12776                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
12777      putVReg( vD_addr,
12778               binop(Iop_OrV128,
12779                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
12780                     mkexpr(z23)) );
12781      break;
12782   }
12783   default:
12784      vex_printf("dis_av_pack(ppc)(opc2)\n");
12785      return False;
12786   }
12787   return True;
12788}
12789
12790
12791/*
12792  AltiVec Floating Point Arithmetic Instructions
12793*/
12794static Bool dis_av_fp_arith ( UInt theInstr )
12795{
12796   /* VA-Form */
12797   UChar opc1     = ifieldOPC(theInstr);
12798   UChar vD_addr  = ifieldRegDS(theInstr);
12799   UChar vA_addr  = ifieldRegA(theInstr);
12800   UChar vB_addr  = ifieldRegB(theInstr);
12801   UChar vC_addr  = ifieldRegC(theInstr);
12802   UInt  opc2=0;
12803
12804   IRTemp vA = newTemp(Ity_V128);
12805   IRTemp vB = newTemp(Ity_V128);
12806   IRTemp vC = newTemp(Ity_V128);
12807   assign( vA, getVReg(vA_addr));
12808   assign( vB, getVReg(vB_addr));
12809   assign( vC, getVReg(vC_addr));
12810
12811   if (opc1 != 0x4) {
12812      vex_printf("dis_av_fp_arith(ppc)(instr)\n");
12813      return False;
12814   }
12815
12816   opc2 = IFIELD( theInstr, 0, 6 );
12817   switch (opc2) {
12818   case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
12819      DIP("vmaddfp v%d,v%d,v%d,v%d\n",
12820          vD_addr, vA_addr, vC_addr, vB_addr);
12821      putVReg( vD_addr,
12822               binop(Iop_Add32Fx4, mkexpr(vB),
12823                     binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
12824      return True;
12825
12826   case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
12827      DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
12828          vD_addr, vA_addr, vC_addr, vB_addr);
12829      putVReg( vD_addr,
12830               binop(Iop_Sub32Fx4,
12831                     mkexpr(vB),
12832                     binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
12833      return True;
12834   }
12835
12836   default:
12837     break; // Fall through...
12838   }
12839
12840   opc2 = IFIELD( theInstr, 0, 11 );
12841   switch (opc2) {
12842   case 0x00A: // vaddfp (Add FP, AV p137)
12843      DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12844      putVReg( vD_addr, binop(Iop_Add32Fx4, mkexpr(vA), mkexpr(vB)) );
12845      return True;
12846
12847  case 0x04A: // vsubfp (Subtract FP, AV p261)
12848      DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12849      putVReg( vD_addr, binop(Iop_Sub32Fx4, mkexpr(vA), mkexpr(vB)) );
12850      return True;
12851
12852   case 0x40A: // vmaxfp (Maximum FP, AV p178)
12853      DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12854      putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
12855      return True;
12856
12857   case 0x44A: // vminfp (Minimum FP, AV p187)
12858      DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12859      putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
12860      return True;
12861
12862   default:
12863      break; // Fall through...
12864   }
12865
12866
12867   if (vA_addr != 0) {
12868      vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
12869      return False;
12870   }
12871
12872   switch (opc2) {
12873   case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
12874      DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
12875      putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) );
12876      return True;
12877
12878   case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
12879      DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
12880      putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) );
12881      return True;
12882
12883   case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
12884      DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
12885      DIP(" => not implemented\n");
12886      return False;
12887
12888   case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
12889      DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
12890      DIP(" => not implemented\n");
12891      return False;
12892
12893   default:
12894      vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
12895      return False;
12896   }
12897   return True;
12898}
12899
12900/*
12901  AltiVec Floating Point Compare Instructions
12902*/
12903static Bool dis_av_fp_cmp ( UInt theInstr )
12904{
12905   /* VXR-Form */
12906   UChar opc1     = ifieldOPC(theInstr);
12907   UChar vD_addr  = ifieldRegDS(theInstr);
12908   UChar vA_addr  = ifieldRegA(theInstr);
12909   UChar vB_addr  = ifieldRegB(theInstr);
12910   UChar flag_rC  = ifieldBIT10(theInstr);
12911   UInt  opc2     = IFIELD( theInstr, 0, 10 );
12912
12913   Bool cmp_bounds = False;
12914
12915   IRTemp vA = newTemp(Ity_V128);
12916   IRTemp vB = newTemp(Ity_V128);
12917   IRTemp vD = newTemp(Ity_V128);
12918   assign( vA, getVReg(vA_addr));
12919   assign( vB, getVReg(vB_addr));
12920
12921   if (opc1 != 0x4) {
12922      vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
12923      return False;
12924   }
12925
12926   switch (opc2) {
12927   case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
12928      DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
12929                                      vD_addr, vA_addr, vB_addr);
12930      assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
12931      break;
12932
12933   case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
12934      DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
12935                                      vD_addr, vA_addr, vB_addr);
12936      assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
12937      break;
12938
12939   case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
12940      DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
12941                                      vD_addr, vA_addr, vB_addr);
12942      assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
12943      break;
12944
12945   case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
12946      IRTemp gt      = newTemp(Ity_V128);
12947      IRTemp lt      = newTemp(Ity_V128);
12948      IRTemp zeros   = newTemp(Ity_V128);
12949      DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
12950                                     vD_addr, vA_addr, vB_addr);
12951      cmp_bounds = True;
12952      assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
12953
12954      /* Note: making use of fact that the ppc backend for compare insns
12955         return zero'd lanes if either of the corresponding arg lanes is
12956         a nan.
12957
12958         Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
12959         need this for the other compares too (vcmpeqfp etc)...
12960         Better still, tighten down the spec for compare irops.
12961       */
12962      assign( gt, unop(Iop_NotV128,
12963                       binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
12964      assign( lt, unop(Iop_NotV128,
12965                       binop(Iop_CmpGE32Fx4, mkexpr(vA),
12966                             binop(Iop_Sub32Fx4, mkexpr(zeros),
12967                                                 mkexpr(vB)))) );
12968
12969      // finally, just shift gt,lt to correct position
12970      assign( vD, binop(Iop_ShlN32x4,
12971                        binop(Iop_OrV128,
12972                              binop(Iop_AndV128, mkexpr(gt),
12973                                    unop(Iop_Dup32x4, mkU32(0x2))),
12974                              binop(Iop_AndV128, mkexpr(lt),
12975                                    unop(Iop_Dup32x4, mkU32(0x1)))),
12976                        mkU8(30)) );
12977      break;
12978   }
12979
12980   default:
12981      vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
12982      return False;
12983   }
12984
12985   putVReg( vD_addr, mkexpr(vD) );
12986
12987   if (flag_rC) {
12988      set_AV_CR6( mkexpr(vD), !cmp_bounds );
12989   }
12990   return True;
12991}
12992
12993/*
12994  AltiVec Floating Point Convert/Round Instructions
12995*/
12996static Bool dis_av_fp_convert ( UInt theInstr )
12997{
12998   /* VX-Form */
12999   UChar opc1     = ifieldOPC(theInstr);
13000   UChar vD_addr  = ifieldRegDS(theInstr);
13001   UChar UIMM_5   = ifieldRegA(theInstr);
13002   UChar vB_addr  = ifieldRegB(theInstr);
13003   UInt  opc2     = IFIELD( theInstr, 0, 11 );
13004
13005   IRTemp vB        = newTemp(Ity_V128);
13006   IRTemp vScale    = newTemp(Ity_V128);
13007   IRTemp vInvScale = newTemp(Ity_V128);
13008
13009   float scale, inv_scale;
13010
13011   assign( vB, getVReg(vB_addr));
13012
13013   /* scale = 2^UIMM, cast to float, reinterpreted as uint */
13014   scale = (float)( (unsigned int) 1<<UIMM_5 );
13015   assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
13016   inv_scale = 1/scale;
13017   assign( vInvScale,
13018           unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
13019
13020   if (opc1 != 0x4) {
13021      vex_printf("dis_av_fp_convert(ppc)(instr)\n");
13022      return False;
13023   }
13024
13025   switch (opc2) {
13026   case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
13027      DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
13028      putVReg( vD_addr, binop(Iop_Mul32Fx4,
13029                              unop(Iop_I32UtoFx4, mkexpr(vB)),
13030                              mkexpr(vInvScale)) );
13031      return True;
13032
13033   case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
13034      DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
13035
13036      putVReg( vD_addr, binop(Iop_Mul32Fx4,
13037                              unop(Iop_I32StoFx4, mkexpr(vB)),
13038                              mkexpr(vInvScale)) );
13039      return True;
13040
13041   case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
13042      DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
13043      putVReg( vD_addr,
13044               unop(Iop_QFtoI32Ux4_RZ,
13045                    binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
13046      return True;
13047
13048   case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
13049      DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
13050      putVReg( vD_addr,
13051               unop(Iop_QFtoI32Sx4_RZ,
13052                     binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
13053      return True;
13054
13055   default:
13056     break;    // Fall through...
13057   }
13058
13059   if (UIMM_5 != 0) {
13060      vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
13061      return False;
13062   }
13063
13064   switch (opc2) {
13065   case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
13066      DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
13067      putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
13068      break;
13069
13070   case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
13071      DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
13072      putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
13073      break;
13074
13075   case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
13076      DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
13077      putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
13078      break;
13079
13080   case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
13081      DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
13082      putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
13083      break;
13084
13085   default:
13086      vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
13087      return False;
13088   }
13089   return True;
13090}
13091
13092
13093/* The 0x3C primary opcode (VSX category) uses several different forms of
13094 * extended opcodes:
13095 *   o XX2-form:
13096 *      - [10:2] (IBM notation [21:29])
13097 *   o XX3-form variants:
13098 *       - variant 1: [10:3] (IBM notation [21:28])
13099 *       - variant 2: [9:3] (IBM notation [22:28])
13100 *       - variant 3: [7:3] (IBM notation [24:28])
13101 *   o XX-4 form:
13102 *      - [10:6] (IBM notation [21:25])
13103 *
13104 * The XX2-form needs bit 0 masked from the standard extended opcode
13105 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
13106 * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
13107 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
13108 * front end since their encoding does not begin at bit 21 like the standard
13109 * format.
13110 *
13111 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
13112 * secondary opcode for such VSX instructions.
13113 *
13114*/
13115
13116
13117struct vsx_insn {
13118   UInt opcode;
13119   Char * name;
13120};
13121
13122//  ATTENTION:  Keep this array sorted on the opcocde!!!
13123static struct vsx_insn vsx_all[] = {
13124      { 0x8, "xxsldwi" },
13125      { 0x18, "xxsel" },
13126      { 0x28, "xxpermdi" },
13127      { 0x48, "xxmrghw" },
13128      { 0x80, "xsadddp" },
13129      { 0x84, "xsmaddadp" },
13130      { 0x8c, "xscmpudp" },
13131      { 0x90, "xscvdpuxws" },
13132      { 0x92, "xsrdpi" },
13133      { 0x94, "xsrsqrtedp" },
13134      { 0x96, "xssqrtdp" },
13135      { 0xa0, "xssubdp" },
13136      { 0xa4, "xsmaddmdp" },
13137      { 0xac, "xscmpodp" },
13138      { 0xb0, "xscvdpsxws" },
13139      { 0xb2, "xsrdpiz" },
13140      { 0xb4, "xsredp" },
13141      { 0xc0, "xsmuldp" },
13142      { 0xc4, "xsmsubadp" },
13143      { 0xc8, "xxmrglw" },
13144      { 0xd2, "xsrdpip" },
13145      { 0xd4, "xstsqrtdp" },
13146      { 0xd6, "xsrdpic" },
13147      { 0xe0, "xsdivdp" },
13148      { 0xe4, "xsmsubmdp" },
13149      { 0xf2, "xsrdpim" },
13150      { 0xf4, "xstdivdp" },
13151      { 0x100, "xvaddsp" },
13152      { 0x104, "xvmaddasp" },
13153      { 0x10c, "xvcmpeqsp" },
13154      { 0x110, "xvcvspuxws" },
13155      { 0x112, "xvrspi" },
13156      { 0x114, "xvrsqrtesp" },
13157      { 0x116, "xvsqrtsp" },
13158      { 0x120, "xvsubsp" },
13159      { 0x124, "xvmaddmsp" },
13160      { 0x12c, "xvcmpgtsp" },
13161      { 0x130, "xvcvspsxws" },
13162      { 0x132, "xvrspiz" },
13163      { 0x134, "xvresp" },
13164      { 0x140, "xvmulsp" },
13165      { 0x144, "xvmsubasp" },
13166      { 0x148, "xxspltw" },
13167      { 0x14c, "xvcmpgesp" },
13168      { 0x150, "xvcvuxwsp" },
13169      { 0x152, "xvrspip" },
13170      { 0x154, "xvtsqrtsp" },
13171      { 0x156, "xvrspic" },
13172      { 0x160, "xvdivsp" },
13173      { 0x164, "xvmsubmsp" },
13174      { 0x170, "xvcvsxwsp" },
13175      { 0x172, "xvrspim" },
13176      { 0x174, "xvtdivsp" },
13177      { 0x180, "xvadddp" },
13178      { 0x184, "xvmaddadp" },
13179      { 0x18c, "xvcmpeqdp" },
13180      { 0x190, "xvcvdpuxws" },
13181      { 0x192, "xvrdpi" },
13182      { 0x194, "xvrsqrtedp" },
13183      { 0x196, "xvsqrtdp" },
13184      { 0x1a0, "xvsubdp" },
13185      { 0x1a4, "xvmaddmdp" },
13186      { 0x1ac, "xvcmpgtdp" },
13187      { 0x1b0, "xvcvdpsxws" },
13188      { 0x1b2, "xvrdpiz" },
13189      { 0x1b4, "xvredp" },
13190      { 0x1c0, "xvmuldp" },
13191      { 0x1c4, "xvmsubadp" },
13192      { 0x1cc, "xvcmpgedp" },
13193      { 0x1d0, "xvcvuxwdp" },
13194      { 0x1d2, "xvrdpip" },
13195      { 0x1d4, "xvtsqrtdp" },
13196      { 0x1d6, "xvrdpic" },
13197      { 0x1e0, "xvdivdp" },
13198      { 0x1e4, "xvmsubmdp" },
13199      { 0x1f0, "xvcvsxwdp" },
13200      { 0x1f2, "xvrdpim" },
13201      { 0x1f4, "xvtdivdp" },
13202      { 0x208, "xxland" },
13203      { 0x212, "xscvdpsp" },
13204      { 0x228, "xxlandc" },
13205      { 0x248 , "xxlor" },
13206      { 0x268, "xxlxor" },
13207      { 0x280, "xsmaxdp" },
13208      { 0x284, "xsnmaddadp" },
13209      { 0x288, "xxlnor" },
13210      { 0x290, "xscvdpuxds" },
13211      { 0x292, "xscvspdp" },
13212      { 0x2a0, "xsmindp" },
13213      { 0x2a4, "xsnmaddmdp" },
13214      { 0x2b0, "xscvdpsxds" },
13215      { 0x2b2, "xsabsdp" },
13216      { 0x2c0, "xscpsgndp" },
13217      { 0x2c4, "xsnmsubadp" },
13218      { 0x2d0, "xscvuxddp" },
13219      { 0x2d2, "xsnabsdp" },
13220      { 0x2e4, "xsnmsubmdp" },
13221      { 0x2f0, "xscvsxddp" },
13222      { 0x2f2, "xsnegdp" },
13223      { 0x300, "xvmaxsp" },
13224      { 0x304, "xvnmaddasp" },
13225      { 0x30c, "xvcmpeqsp." },
13226      { 0x310, "xvcvspuxds" },
13227      { 0x312, "xvcvdpsp" },
13228      { 0x320, "xvminsp" },
13229      { 0x324, "xvnmaddmsp" },
13230      { 0x32c, "xvcmpgtsp." },
13231      { 0x330, "xvcvspsxds" },
13232      { 0x332, "xvabssp" },
13233      { 0x340, "xvcpsgnsp" },
13234      { 0x344, "xvnmsubasp" },
13235      { 0x34c, "xvcmpgesp." },
13236      { 0x350, "xvcvuxdsp" },
13237      { 0x352, "xvnabssp" },
13238      { 0x364, "xvnmsubmsp" },
13239      { 0x370, "xvcvsxdsp" },
13240      { 0x372, "xvnegsp" },
13241      { 0x380, "xvmaxdp" },
13242      { 0x384, "xvnmaddadp" },
13243      { 0x38c, "xvcmpeqdp." },
13244      { 0x390, "xvcvdpuxds" },
13245      { 0x392, "xvcvspdp" },
13246      { 0x3a0, "xvmindp" },
13247      { 0x3a4, "xvnmaddmdp" },
13248      { 0x3ac, "xvcmpgtdp." },
13249      { 0x3b0, "xvcvdpsxds" },
13250      { 0x3b2, "xvabsdp" },
13251      { 0x3c0, "xvcpsgndp" },
13252      { 0x3c4, "xvnmsubadp" },
13253      { 0x3cc, "xvcmpgedp." },
13254      { 0x3d0, "xvcvuxddp" },
13255      { 0x3d2, "xvnabsdp" },
13256      { 0x3e4, "xvnmsubmdp" },
13257      { 0x3f0, "xvcvsxddp" },
13258      { 0x3f2, "xvnegdp" }
13259};
13260#define VSX_ALL_LEN 135
13261
13262// ATTENTION: This search function assumes vsx_all array is sorted.
13263static Int findVSXextOpCode(UInt opcode)
13264{
13265   Int low, mid, high;
13266   low = 0;
13267   high = VSX_ALL_LEN - 1;
13268   while (low <= high) {
13269      mid = (low + high)/2;
13270      if (opcode < vsx_all[mid].opcode)
13271         high = mid - 1;
13272      else if (opcode > vsx_all[mid].opcode)
13273         low = mid + 1;
13274      else
13275         return mid;
13276   }
13277   return -1;
13278}
13279
13280
13281/* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
13282 * passed, and we then try to match it up with one of the VSX forms
13283 * below.
13284 */
13285static UInt get_VSX60_opc2(UInt opc2_full)
13286{
13287#define XX2_MASK 0x000003FE
13288#define XX3_1_MASK 0x000003FC
13289#define XX3_2_MASK 0x000001FC
13290#define XX3_3_MASK 0x0000007C
13291#define XX4_MASK 0x00000018
13292   Int ret;
13293   UInt vsxExtOpcode = 0;
13294
13295   if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
13296      vsxExtOpcode = vsx_all[ret].opcode;
13297   else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
13298      vsxExtOpcode = vsx_all[ret].opcode;
13299   else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
13300      vsxExtOpcode = vsx_all[ret].opcode;
13301   else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
13302      vsxExtOpcode = vsx_all[ret].opcode;
13303   else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
13304      vsxExtOpcode = vsx_all[ret].opcode;
13305
13306   return vsxExtOpcode;
13307}
13308
13309/*------------------------------------------------------------*/
13310/*--- Disassemble a single instruction                     ---*/
13311/*------------------------------------------------------------*/
13312
13313/* Disassemble a single instruction into IR.  The instruction
13314   is located in host memory at &guest_code[delta]. */
13315
13316static
13317DisResult disInstr_PPC_WRK (
13318             Bool         put_IP,
13319             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
13320             Bool         resteerCisOk,
13321             void*        callback_opaque,
13322             Long         delta64,
13323             VexArchInfo* archinfo,
13324             VexAbiInfo*  abiinfo
13325          )
13326{
13327   UChar     opc1;
13328   UInt      opc2;
13329   DisResult dres;
13330   UInt      theInstr;
13331   IRType    ty = mode64 ? Ity_I64 : Ity_I32;
13332   Bool      allow_F  = False;
13333   Bool      allow_V  = False;
13334   Bool      allow_FX = False;
13335   Bool      allow_GX = False;
13336   Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
13337   UInt      hwcaps = archinfo->hwcaps;
13338   Long      delta;
13339
13340   /* What insn variants are we supporting today? */
13341   if (mode64) {
13342      allow_F  = True;
13343      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
13344      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
13345      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
13346      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
13347   } else {
13348      allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
13349      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
13350      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
13351      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
13352      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
13353   }
13354
13355   /* The running delta */
13356   delta = (Long)mkSzAddr(ty, (ULong)delta64);
13357
13358   /* Set result defaults. */
13359   dres.whatNext   = Dis_Continue;
13360   dres.len        = 0;
13361   dres.continueAt = 0;
13362
13363   /* At least this is simple on PPC32: insns are all 4 bytes long, and
13364      4-aligned.  So just fish the whole thing out of memory right now
13365      and have done. */
13366   theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) );
13367
13368   if (0) vex_printf("insn: 0x%x\n", theInstr);
13369
13370   DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
13371
13372   /* We may be asked to update the guest CIA before going further. */
13373   if (put_IP)
13374      putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
13375
13376   /* Spot "Special" instructions (see comment at top of file). */
13377   {
13378      UChar* code = (UChar*)(guest_code + delta);
13379      /* Spot the 16-byte preamble:
13380         32-bit mode:
13381            54001800  rlwinm 0,0,3,0,0
13382            54006800  rlwinm 0,0,13,0,0
13383            5400E800  rlwinm 0,0,29,0,0
13384            54009800  rlwinm 0,0,19,0,0
13385         64-bit mode:
13386            78001800  rotldi 0,0,3
13387            78006800  rotldi 0,0,13
13388            7800E802  rotldi 0,0,61
13389            78009802  rotldi 0,0,51
13390      */
13391      UInt word1 = mode64 ? 0x78001800 : 0x54001800;
13392      UInt word2 = mode64 ? 0x78006800 : 0x54006800;
13393      UInt word3 = mode64 ? 0x7800E802 : 0x5400E800;
13394      UInt word4 = mode64 ? 0x78009802 : 0x54009800;
13395      if (getUIntBigendianly(code+ 0) == word1 &&
13396          getUIntBigendianly(code+ 4) == word2 &&
13397          getUIntBigendianly(code+ 8) == word3 &&
13398          getUIntBigendianly(code+12) == word4) {
13399         /* Got a "Special" instruction preamble.  Which one is it? */
13400         if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
13401            /* %R3 = client_request ( %R4 ) */
13402            DIP("r3 = client_request ( %%r4 )\n");
13403            delta += 20;
13404            irsb->next     = mkSzImm( ty, guest_CIA_bbstart + delta );
13405            irsb->jumpkind = Ijk_ClientReq;
13406            dres.whatNext  = Dis_StopHere;
13407            goto decode_success;
13408         }
13409         else
13410         if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
13411            /* %R3 = guest_NRADDR */
13412            DIP("r3 = guest_NRADDR\n");
13413            delta += 20;
13414            dres.len = 20;
13415            putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
13416            goto decode_success;
13417         }
13418         else
13419         if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
13420            /*  branch-and-link-to-noredir %R11 */
13421            DIP("branch-and-link-to-noredir r11\n");
13422            delta += 20;
13423            putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
13424            irsb->next     = getIReg(11);
13425            irsb->jumpkind = Ijk_NoRedir;
13426            dres.whatNext  = Dis_StopHere;
13427            goto decode_success;
13428         }
13429         else
13430         if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
13431            /* %R3 = guest_NRADDR_GPR2 */
13432            DIP("r3 = guest_NRADDR_GPR2\n");
13433            delta += 20;
13434            dres.len = 20;
13435            putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
13436            goto decode_success;
13437         }
13438         /* We don't know what it is.  Set opc1/opc2 so decode_failure
13439            can print the insn following the Special-insn preamble. */
13440         theInstr = getUIntBigendianly(code+16);
13441         opc1     = ifieldOPC(theInstr);
13442         opc2     = ifieldOPClo10(theInstr);
13443         goto decode_failure;
13444         /*NOTREACHED*/
13445      }
13446   }
13447
13448   opc1 = ifieldOPC(theInstr);
13449   opc2 = ifieldOPClo10(theInstr);
13450
13451   // Note: all 'reserved' bits must be cleared, else invalid
13452   switch (opc1) {
13453
13454   /* Integer Arithmetic Instructions */
13455   case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
13456   case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
13457      if (dis_int_arith( theInstr )) goto decode_success;
13458      goto decode_failure;
13459
13460   /* Integer Compare Instructions */
13461   case 0x0B: case 0x0A: // cmpi, cmpli
13462      if (dis_int_cmp( theInstr )) goto decode_success;
13463      goto decode_failure;
13464
13465   /* Integer Logical Instructions */
13466   case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
13467   case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
13468      if (dis_int_logic( theInstr )) goto decode_success;
13469      goto decode_failure;
13470
13471   /* Integer Rotate Instructions */
13472   case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
13473      if (dis_int_rot( theInstr )) goto decode_success;
13474      goto decode_failure;
13475
13476   /* 64bit Integer Rotate Instructions */
13477   case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
13478      if (dis_int_rot( theInstr )) goto decode_success;
13479      goto decode_failure;
13480
13481   /* Integer Load Instructions */
13482   case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
13483   case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
13484   case 0x20: case 0x21:            // lwz,  lwzu
13485      if (dis_int_load( theInstr )) goto decode_success;
13486      goto decode_failure;
13487
13488   /* Integer Store Instructions */
13489   case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
13490   case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
13491      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
13492      goto decode_failure;
13493
13494   /* Integer Load and Store Multiple Instructions */
13495   case 0x2E: case 0x2F: // lmw, stmw
13496      if (dis_int_ldst_mult( theInstr )) goto decode_success;
13497      goto decode_failure;
13498
13499   /* Branch Instructions */
13500   case 0x12: case 0x10: // b, bc
13501      if (dis_branch(theInstr, abiinfo, &dres,
13502                               resteerOkFn, callback_opaque))
13503         goto decode_success;
13504      goto decode_failure;
13505
13506   /* System Linkage Instructions */
13507   case 0x11: // sc
13508      if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
13509      goto decode_failure;
13510
13511   /* Trap Instructions */
13512   case 0x02: case 0x03: // tdi, twi
13513      if (dis_trapi(theInstr, &dres)) goto decode_success;
13514      goto decode_failure;
13515
13516   /* Floating Point Load Instructions */
13517   case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
13518   case 0x33:                       // lfdu
13519      if (!allow_F) goto decode_noF;
13520      if (dis_fp_load( theInstr )) goto decode_success;
13521      goto decode_failure;
13522
13523   /* Floating Point Store Instructions */
13524   case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
13525   case 0x37:                       // stfdux
13526      if (!allow_F) goto decode_noF;
13527      if (dis_fp_store( theInstr )) goto decode_success;
13528      goto decode_failure;
13529
13530      /* Floating Point Load Double Pair Instructions */
13531   case 0x39: case 0x3D:
13532      if (!allow_F) goto decode_noF;
13533      if (dis_fp_pair( theInstr )) goto decode_success;
13534      goto decode_failure;
13535
13536   /* 64bit Integer Loads */
13537   case 0x3A:  // ld, ldu, lwa
13538      if (!mode64) goto decode_failure;
13539      if (dis_int_load( theInstr )) goto decode_success;
13540      goto decode_failure;
13541
13542   case 0x3B:
13543      if (!allow_F) goto decode_noF;
13544      opc2 = ifieldOPClo10(theInstr);
13545      switch (opc2) {
13546         case 0x3CE: // fcfidus (implemented as native insn)
13547            if (!allow_VX)
13548               goto decode_noVX;
13549            if (dis_fp_round( theInstr ))
13550               goto decode_success;
13551            goto decode_failure;
13552         case 0x34E: // fcfids
13553            if (dis_fp_round( theInstr ))
13554               goto decode_success;
13555            goto decode_failure;
13556      }
13557
13558      opc2 = IFIELD(theInstr, 1, 5);
13559      switch (opc2) {
13560      /* Floating Point Arith Instructions */
13561      case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
13562      case 0x19:                       // fmuls
13563         if (dis_fp_arith(theInstr)) goto decode_success;
13564         goto decode_failure;
13565      case 0x16:                       // fsqrts
13566         if (!allow_FX) goto decode_noFX;
13567         if (dis_fp_arith(theInstr)) goto decode_success;
13568         goto decode_failure;
13569      case 0x18:                       // fres
13570         if (!allow_GX) goto decode_noGX;
13571         if (dis_fp_arith(theInstr)) goto decode_success;
13572         goto decode_failure;
13573
13574      /* Floating Point Mult-Add Instructions */
13575      case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
13576      case 0x1F:                       // fnmadds
13577         if (dis_fp_multadd(theInstr)) goto decode_success;
13578         goto decode_failure;
13579
13580      case 0x1A:                       // frsqrtes
13581         if (!allow_GX) goto decode_noGX;
13582         if (dis_fp_arith(theInstr)) goto decode_success;
13583         goto decode_failure;
13584
13585      default:
13586         goto decode_failure;
13587      }
13588      break;
13589
13590   case 0x3C: // VSX instructions (except load/store)
13591   {
13592      UInt vsxOpc2 = get_VSX60_opc2(opc2);
13593      /* The vsxOpc2 returned is the "normalized" value, representing the
13594       * instructions secondary opcode as taken from the standard secondary
13595       * opcode field [21:30] (IBM notatition), even if the actual field
13596       * is non-standard.  These normalized values are given in the opcode
13597       * appendices of the ISA 2.06 document.
13598       */
13599      if (vsxOpc2 == 0)
13600         goto decode_failure;
13601
13602      switch (vsxOpc2) {
13603         case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
13604         case 0x018: case 0x148: // xxsel, xxspltw
13605            if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
13606            goto decode_failure;
13607         case 0x268: case 0x248: case 0x288: case 0x208: case 0x228: // xxlxor, xxlor, xxlnor, xxland, xxlandc
13608            if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
13609            goto decode_failure;
13610         case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
13611         case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
13612         case 0x280: case 0x2A0: // xsmaxdp, xsmindp
13613         case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
13614         case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
13615         case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
13616         case 0x092: // xsrdpi
13617            if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
13618            goto decode_failure;
13619         case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
13620            if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
13621            goto decode_failure;
13622         case 0x080: case 0x0E0: // xsadddp, xsdivdp
13623         case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
13624         case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
13625         case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
13626         case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
13627         case 0x0C0: case 0x0A0: // xsmuldp, xssubdp
13628         case 0x096: case 0x0F4: // xssqrtdp, xstdivdp
13629         case 0x0D4: // xstsqrtdp
13630            if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
13631            goto decode_failure;
13632         case 0x180: // xvadddp
13633         case 0x1E0: // xvdivdp
13634         case 0x1C0: // xvmuldp
13635         case 0x1A0: // xvsubdp
13636         case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
13637         case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
13638         case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
13639         case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
13640         case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
13641         case 0x196: // xvsqrtdp
13642            if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
13643            goto decode_failure;
13644         case 0x100: // xvaddsp
13645         case 0x160: // xvdivsp
13646         case 0x140: // xvmulsp
13647         case 0x120: // xvsubsp
13648         case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
13649         case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
13650         case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
13651         case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
13652         case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
13653         case 0x116: // xvsqrtsp
13654            if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
13655            goto decode_failure;
13656
13657         case 0x2B0: case 0x2F0: case 0x2D0: // xscvdpsxds, xscvsxddp, xscvuxddp
13658         case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
13659         case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
13660         case 0x212: case 0x090: // xscvdpsp, xscvdpuxws
13661         case 0x292: case 0x312: // xscvspdp, xvcvdpsp
13662         case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
13663         case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
13664         case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
13665         case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
13666         case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
13667         case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
13668         case 0x3d0: case 0x350: // xvcvuxddp, xvcvuxdsp
13669         case 0x1d0: // xvcvuxwdp
13670            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
13671            goto decode_failure;
13672
13673         case 0x18C: case 0x38C: // xvcmpeqdp[.]
13674         case 0x10C: case 0x30C: // xvcmpeqsp[.]
13675         case 0x14C: case 0x34C: // xvcmpgesp[.]
13676         case 0x12C: case 0x32C: // xvcmpgtsp[.]
13677         case 0x1CC: case 0x3CC: // xvcmpgedp[.]
13678         case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
13679             if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
13680             goto decode_failure;
13681
13682         case 0x134:  // xvresp
13683         case 0x1B4:  // xvredp
13684         case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
13685         case 0x380: case 0x3A0: // xvmaxdp, xvmindp
13686         case 0x300: case 0x320: // xvmaxsp, xvminsp
13687         case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
13688         case 0x3B2: case 0x332: // xvabsdp, xvabssp
13689         case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
13690         case 0x192: case 0x1D6: // xvrdpi, xvrdpic
13691         case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
13692         case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
13693         case 0x112: case 0x156: // xvrspi, xvrspic
13694         case 0x172: case 0x152: // xvrspim, xvrspip
13695         case 0x132: // xvrspiz
13696            if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
13697            goto decode_failure;
13698
13699         default:
13700            goto decode_failure;
13701      }
13702      break;
13703   }
13704
13705   /* 64bit Integer Stores */
13706   case 0x3E:  // std, stdu
13707      if (!mode64) goto decode_failure;
13708      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
13709      goto decode_failure;
13710
13711   case 0x3F:
13712      if (!allow_F) goto decode_noF;
13713      /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
13714         so we can simply fall through the first switch statement */
13715
13716      opc2 = IFIELD(theInstr, 1, 5);
13717      switch (opc2) {
13718      /* Floating Point Arith Instructions */
13719      case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
13720      case 0x19:                       // fmul
13721         if (dis_fp_arith(theInstr)) goto decode_success;
13722         goto decode_failure;
13723      case 0x16:                       // fsqrt
13724         if (!allow_FX) goto decode_noFX;
13725         if (dis_fp_arith(theInstr)) goto decode_success;
13726         goto decode_failure;
13727      case 0x17: case 0x1A:            // fsel, frsqrte
13728         if (!allow_GX) goto decode_noGX;
13729         if (dis_fp_arith(theInstr)) goto decode_success;
13730         goto decode_failure;
13731
13732      /* Floating Point Mult-Add Instructions */
13733      case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
13734      case 0x1F:                       // fnmadd
13735         if (dis_fp_multadd(theInstr)) goto decode_success;
13736         goto decode_failure;
13737
13738      case 0x18:                       // fre
13739         if (!allow_GX) goto decode_noGX;
13740         if (dis_fp_arith(theInstr)) goto decode_success;
13741         goto decode_failure;
13742
13743      default:
13744         break; // Fall through
13745      }
13746
13747      opc2 = IFIELD(theInstr, 1, 10);
13748      switch (opc2) {
13749      /* Floating Point Compare Instructions */
13750      case 0x000: // fcmpu
13751      case 0x020: // fcmpo
13752         if (dis_fp_cmp(theInstr)) goto decode_success;
13753         goto decode_failure;
13754
13755      case 0x080: // ftdiv
13756      case 0x0A0: // ftsqrt
13757         if (dis_fp_tests(theInstr)) goto decode_success;
13758         goto decode_failure;
13759
13760      /* Floating Point Rounding/Conversion Instructions */
13761      case 0x00C: // frsp
13762      case 0x00E: // fctiw
13763      case 0x00F: // fctiwz
13764      case 0x32E: // fctid
13765      case 0x32F: // fctidz
13766      case 0x34E: // fcfid
13767         if (dis_fp_round(theInstr)) goto decode_success;
13768         goto decode_failure;
13769      case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
13770      case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
13771         if (!allow_VX) goto decode_noVX;
13772         if (dis_fp_round(theInstr)) goto decode_success;
13773         goto decode_failure;
13774
13775      /* Power6 rounding stuff */
13776      case 0x1E8: // frim
13777      case 0x1C8: // frip
13778      case 0x188: // frin
13779      case 0x1A8: // friz
13780         /* A hack to check for P6 capability . . . */
13781         if ((allow_F && allow_V && allow_FX && allow_GX) &&
13782             (dis_fp_round(theInstr)))
13783            goto decode_success;
13784         goto decode_failure;
13785
13786      /* Floating Point Move Instructions */
13787      case 0x008: // fcpsgn
13788      case 0x028: // fneg
13789      case 0x048: // fmr
13790      case 0x088: // fnabs
13791      case 0x108: // fabs
13792         if (dis_fp_move( theInstr )) goto decode_success;
13793         goto decode_failure;
13794
13795      /* Floating Point Status/Control Register Instructions */
13796      case 0x026: // mtfsb1
13797      case 0x040: // mcrfs
13798      case 0x046: // mtfsb0
13799      case 0x086: // mtfsfi
13800      case 0x247: // mffs
13801      case 0x2C7: // mtfsf
13802         if (dis_fp_scr( theInstr )) goto decode_success;
13803         goto decode_failure;
13804
13805      default:
13806         goto decode_failure;
13807      }
13808      break;
13809
13810   case 0x13:
13811      switch (opc2) {
13812
13813      /* Condition Register Logical Instructions */
13814      case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
13815      case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
13816      case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
13817         if (dis_cond_logic( theInstr )) goto decode_success;
13818         goto decode_failure;
13819
13820      /* Branch Instructions */
13821      case 0x210: case 0x010: // bcctr, bclr
13822         if (dis_branch(theInstr, abiinfo, &dres,
13823                                  resteerOkFn, callback_opaque))
13824            goto decode_success;
13825         goto decode_failure;
13826
13827      /* Memory Synchronization Instructions */
13828      case 0x096: // isync
13829         if (dis_memsync( theInstr )) goto decode_success;
13830         goto decode_failure;
13831
13832      default:
13833         goto decode_failure;
13834      }
13835      break;
13836
13837
13838   case 0x1F:
13839
13840      /* For arith instns, bit10 is the OE flag (overflow enable) */
13841
13842      opc2 = IFIELD(theInstr, 1, 9);
13843      switch (opc2) {
13844      /* Integer Arithmetic Instructions */
13845      case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
13846      case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
13847      case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
13848      case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
13849      case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
13850      case 0x0C8: // subfze
13851         if (dis_int_arith( theInstr )) goto decode_success;
13852         goto decode_failure;
13853
13854      case 0x18B: // divweu (implemented as native insn)
13855      case 0x1AB: // divwe (implemented as native insn)
13856         if (!allow_VX) goto decode_noVX;
13857         if (dis_int_arith( theInstr )) goto decode_success;
13858         goto decode_failure;
13859
13860      /* 64bit Integer Arithmetic */
13861      case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
13862      case 0x1C9: case 0x1E9: // divdu, divd
13863         if (!mode64) goto decode_failure;
13864         if (dis_int_arith( theInstr )) goto decode_success;
13865         goto decode_failure;
13866
13867      case 0x1A9: //  divde (implemented as native insn)
13868      case 0x189: //  divdeuo (implemented as native insn)
13869         if (!allow_VX) goto decode_noVX;
13870         if (!mode64) goto decode_failure;
13871         if (dis_int_arith( theInstr )) goto decode_success;
13872         goto decode_failure;
13873
13874      case 0x1FC:                         // cmpb
13875         if (dis_int_logic( theInstr )) goto decode_success;
13876         goto decode_failure;
13877
13878      default:
13879         break;  // Fall through...
13880      }
13881
13882      /* All remaining opcodes use full 10 bits. */
13883
13884      opc2 = IFIELD(theInstr, 1, 10);
13885      switch (opc2) {
13886      /* Integer Compare Instructions  */
13887      case 0x000: case 0x020: // cmp, cmpl
13888         if (dis_int_cmp( theInstr )) goto decode_success;
13889         goto decode_failure;
13890
13891      /* Integer Logical Instructions */
13892      case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
13893      case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
13894      case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
13895      case 0x19C: case 0x13C:             // orc,  xor
13896      case 0x2DF: case 0x25F:            // mftgpr, mffgpr
13897         if (dis_int_logic( theInstr )) goto decode_success;
13898         goto decode_failure;
13899
13900      /* 64bit Integer Logical Instructions */
13901      case 0x3DA: case 0x03A: // extsw, cntlzd
13902         if (!mode64) goto decode_failure;
13903         if (dis_int_logic( theInstr )) goto decode_success;
13904         goto decode_failure;
13905
13906         /* 64bit Integer Parity Instructions */
13907      case 0xba: case 0x9a: // prtyd, prtyw
13908         if (dis_int_parity( theInstr )) goto decode_success;
13909         goto decode_failure;
13910
13911      /* Integer Shift Instructions */
13912      case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
13913      case 0x218:                         // srw
13914         if (dis_int_shift( theInstr )) goto decode_success;
13915         goto decode_failure;
13916
13917      /* 64bit Integer Shift Instructions */
13918      case 0x01B: case 0x31A: // sld, srad
13919      case 0x33A: case 0x33B: // sradi
13920      case 0x21B:             // srd
13921         if (!mode64) goto decode_failure;
13922         if (dis_int_shift( theInstr )) goto decode_success;
13923         goto decode_failure;
13924
13925      /* Integer Load Instructions */
13926      case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
13927      case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
13928      case 0x017: case 0x037:             // lwzx,  lwzux
13929         if (dis_int_load( theInstr )) goto decode_success;
13930         goto decode_failure;
13931
13932      /* 64bit Integer Load Instructions */
13933      case 0x035: case 0x015:             // ldux,  ldx
13934      case 0x175: case 0x155:             // lwaux, lwax
13935         if (!mode64) goto decode_failure;
13936         if (dis_int_load( theInstr )) goto decode_success;
13937         goto decode_failure;
13938
13939      /* Integer Store Instructions */
13940      case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
13941      case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
13942         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
13943         goto decode_failure;
13944
13945      /* 64bit Integer Store Instructions */
13946      case 0x0B5: case 0x095: // stdux, stdx
13947         if (!mode64) goto decode_failure;
13948         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
13949         goto decode_failure;
13950
13951      /* Integer Load and Store with Byte Reverse Instructions */
13952      case 0x316: case 0x216: case 0x396: // lhbrx, lwbrx, sthbrx
13953      case 0x296: case 0x214:             // stwbrx, ldbrx
13954      case 0x294:                         // stdbrx
13955         if (dis_int_ldst_rev( theInstr )) goto decode_success;
13956         goto decode_failure;
13957
13958      /* Integer Load and Store String Instructions */
13959      case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
13960      case 0x295: {                       // stswx
13961         Bool stopHere = False;
13962         Bool ok = dis_int_ldst_str( theInstr, &stopHere );
13963         if (!ok) goto decode_failure;
13964         if (stopHere) {
13965            irsb->next     = mkSzImm(ty, nextInsnAddr());
13966            irsb->jumpkind = Ijk_Boring;
13967            dres.whatNext  = Dis_StopHere;
13968         }
13969         goto decode_success;
13970      }
13971
13972      /* Memory Synchronization Instructions */
13973      case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
13974      case 0x256:                         // sync
13975         if (dis_memsync( theInstr )) goto decode_success;
13976         goto decode_failure;
13977
13978      /* 64bit Memory Synchronization Instructions */
13979      case 0x054: case 0x0D6: // ldarx, stdcx.
13980         if (!mode64) goto decode_failure;
13981         if (dis_memsync( theInstr )) goto decode_success;
13982         goto decode_failure;
13983
13984      /* Processor Control Instructions */
13985      case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
13986      case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
13987         if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
13988         goto decode_failure;
13989
13990      /* Cache Management Instructions */
13991      case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
13992      case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
13993      case 0x3D6:                         // icbi
13994         if (dis_cache_manage( theInstr, &dres, archinfo ))
13995            goto decode_success;
13996         goto decode_failure;
13997
13998//zz       /* External Control Instructions */
13999//zz       case 0x136: case 0x1B6: // eciwx, ecowx
14000//zz          DIP("external control op => not implemented\n");
14001//zz          goto decode_failure;
14002
14003      /* Trap Instructions */
14004      case 0x004: case 0x044:             // tw,   td
14005         if (dis_trap(theInstr, &dres)) goto decode_success;
14006         goto decode_failure;
14007
14008      /* Floating Point Load Instructions */
14009      case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
14010      case 0x277:                         // lfdux
14011         if (!allow_F) goto decode_noF;
14012         if (dis_fp_load( theInstr )) goto decode_success;
14013         goto decode_failure;
14014
14015      /* Floating Point Store Instructions */
14016      case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
14017      case 0x2F7:                         // stfdu, stfiwx
14018         if (!allow_F) goto decode_noF;
14019         if (dis_fp_store( theInstr )) goto decode_success;
14020         goto decode_failure;
14021      case 0x3D7:                         // stfiwx
14022         if (!allow_F) goto decode_noF;
14023         if (!allow_GX) goto decode_noGX;
14024         if (dis_fp_store( theInstr )) goto decode_success;
14025         goto decode_failure;
14026
14027         /* Floating Point Double Pair Indexed Instructions */
14028      case 0x317: // lfdpx (Power6)
14029      case 0x397: // stfdpx (Power6)
14030         if (!allow_F) goto decode_noF;
14031         if (dis_fp_pair(theInstr)) goto decode_success;
14032         goto decode_failure;
14033
14034      case 0x357:                         // lfiwax
14035         if (!allow_F) goto decode_noF;
14036         if (dis_fp_load( theInstr )) goto decode_success;
14037         goto decode_failure;
14038
14039      case 0x377:                         // lfiwzx
14040         if (!allow_F) goto decode_noF;
14041         if (dis_fp_load( theInstr )) goto decode_success;
14042         goto decode_failure;
14043
14044      /* AltiVec instructions */
14045
14046      /* AV Cache Control - Data streams */
14047      case 0x156: case 0x176: case 0x336: // dst, dstst, dss
14048         if (!allow_V) goto decode_noV;
14049         if (dis_av_datastream( theInstr )) goto decode_success;
14050         goto decode_failure;
14051
14052      /* AV Load */
14053      case 0x006: case 0x026:             // lvsl, lvsr
14054      case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
14055      case 0x067: case 0x167:             // lvx, lvxl
14056         if (!allow_V) goto decode_noV;
14057         if (dis_av_load( abiinfo, theInstr )) goto decode_success;
14058         goto decode_failure;
14059
14060      /* AV Store */
14061      case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
14062      case 0x0E7: case 0x1E7:             // stvx, stvxl
14063         if (!allow_V) goto decode_noV;
14064         if (dis_av_store( theInstr )) goto decode_success;
14065         goto decode_failure;
14066
14067      /* VSX Load */
14068      case 0x24C: // lxsdx
14069      case 0x34C: // lxvd2x
14070      case 0x14C: // lxvdsx
14071      case 0x30C: // lxvw4x
14072    	  if (dis_vx_load( theInstr )) goto decode_success;
14073          goto decode_failure;
14074
14075      /* VSX Store */
14076      case 0x2CC: // stxsdx
14077      case 0x3CC: // stxvd2x
14078      case 0x38C: // stxvw4x
14079    	  if (dis_vx_store( theInstr )) goto decode_success;
14080    	  goto decode_failure;
14081
14082      /* Miscellaneous ISA 2.06 instructions */
14083      case 0x1FA: // popcntd
14084      case 0x17A: // popcntw
14085    	  if (dis_int_logic( theInstr )) goto decode_success;
14086    	  goto decode_failure;
14087
14088      case 0x0FC: // bpermd
14089         if (dis_int_logic( theInstr )) goto decode_success;
14090         goto decode_failure;
14091
14092      default:
14093         /* Deal with some other cases that we would otherwise have
14094            punted on. */
14095         /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
14096         /* only decode this insn when reserved bit 0 (31 in IBM's
14097            notation) is zero */
14098         if (IFIELD(theInstr, 0, 6) == (15<<1)) {
14099            UInt rT = ifieldRegDS( theInstr );
14100            UInt rA = ifieldRegA( theInstr );
14101            UInt rB = ifieldRegB( theInstr );
14102            UInt bi = ifieldRegC( theInstr );
14103            putIReg(
14104               rT,
14105               IRExpr_Mux0X( unop(Iop_32to8,getCRbit( bi )),
14106                             getIReg(rB),
14107                             rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
14108                                     : getIReg(rA) )
14109            );
14110            DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
14111            goto decode_success;
14112         }
14113         goto decode_failure;
14114      }
14115      break;
14116
14117
14118   case 0x04:
14119      /* AltiVec instructions */
14120
14121      opc2 = IFIELD(theInstr, 0, 6);
14122      switch (opc2) {
14123      /* AV Mult-Add, Mult-Sum */
14124      case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
14125      case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
14126      case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
14127         if (!allow_V) goto decode_noV;
14128         if (dis_av_multarith( theInstr )) goto decode_success;
14129         goto decode_failure;
14130
14131      /* AV Permutations */
14132      case 0x2A:                       // vsel
14133      case 0x2B:                       // vperm
14134      case 0x2C:                       // vsldoi
14135         if (!allow_V) goto decode_noV;
14136         if (dis_av_permute( theInstr )) goto decode_success;
14137         goto decode_failure;
14138
14139      /* AV Floating Point Mult-Add/Sub */
14140      case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
14141         if (!allow_V) goto decode_noV;
14142         if (dis_av_fp_arith( theInstr )) goto decode_success;
14143         goto decode_failure;
14144
14145      default:
14146         break;  // Fall through...
14147      }
14148
14149      opc2 = IFIELD(theInstr, 0, 11);
14150      switch (opc2) {
14151      /* AV Arithmetic */
14152      case 0x180:                         // vaddcuw
14153      case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
14154      case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
14155      case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
14156      case 0x580:                         // vsubcuw
14157      case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
14158      case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
14159      case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
14160      case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
14161      case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
14162      case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
14163      case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
14164      case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
14165      case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
14166      case 0x008: case 0x048:             // vmuloub, vmulouh
14167      case 0x108: case 0x148:             // vmulosb, vmulosh
14168      case 0x208: case 0x248:             // vmuleub, vmuleuh
14169      case 0x308: case 0x348:             // vmulesb, vmulesh
14170      case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
14171      case 0x688: case 0x788:             // vsum2sws, vsumsws
14172         if (!allow_V) goto decode_noV;
14173         if (dis_av_arith( theInstr )) goto decode_success;
14174         goto decode_failure;
14175
14176      /* AV Rotate, Shift */
14177      case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
14178      case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
14179      case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
14180      case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
14181      case 0x1C4: case 0x2C4:             // vsl, vsr
14182      case 0x40C: case 0x44C:             // vslo, vsro
14183         if (!allow_V) goto decode_noV;
14184         if (dis_av_shift( theInstr )) goto decode_success;
14185         goto decode_failure;
14186
14187      /* AV Logic */
14188      case 0x404: case 0x444: case 0x484: // vand, vandc, vor
14189      case 0x4C4: case 0x504:             // vxor, vnor
14190         if (!allow_V) goto decode_noV;
14191         if (dis_av_logic( theInstr )) goto decode_success;
14192         goto decode_failure;
14193
14194      /* AV Processor Control */
14195      case 0x604: case 0x644:             // mfvscr, mtvscr
14196         if (!allow_V) goto decode_noV;
14197         if (dis_av_procctl( theInstr )) goto decode_success;
14198         goto decode_failure;
14199
14200      /* AV Floating Point Arithmetic */
14201      case 0x00A: case 0x04A:             // vaddfp, vsubfp
14202      case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
14203      case 0x1CA:                         // vlogefp
14204      case 0x40A: case 0x44A:             // vmaxfp, vminfp
14205         if (!allow_V) goto decode_noV;
14206         if (dis_av_fp_arith( theInstr )) goto decode_success;
14207         goto decode_failure;
14208
14209      /* AV Floating Point Round/Convert */
14210      case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
14211      case 0x2CA:                         // vrfim
14212      case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
14213      case 0x3CA:                         // vctsxs
14214         if (!allow_V) goto decode_noV;
14215         if (dis_av_fp_convert( theInstr )) goto decode_success;
14216         goto decode_failure;
14217
14218      /* AV Merge, Splat */
14219      case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
14220      case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
14221      case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
14222      case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
14223         if (!allow_V) goto decode_noV;
14224         if (dis_av_permute( theInstr )) goto decode_success;
14225         goto decode_failure;
14226
14227      /* AV Pack, Unpack */
14228      case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
14229      case 0x0CE:                         // vpkuwus
14230      case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
14231      case 0x1CE:                         // vpkswss
14232      case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
14233      case 0x2CE:                         // vupklsh
14234      case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
14235         if (!allow_V) goto decode_noV;
14236         if (dis_av_pack( theInstr )) goto decode_success;
14237         goto decode_failure;
14238
14239      default:
14240         break;  // Fall through...
14241      }
14242
14243      opc2 = IFIELD(theInstr, 0, 10);
14244      switch (opc2) {
14245
14246      /* AV Compare */
14247      case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
14248      case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
14249      case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
14250         if (!allow_V) goto decode_noV;
14251         if (dis_av_cmp( theInstr )) goto decode_success;
14252         goto decode_failure;
14253
14254      /* AV Floating Point Compare */
14255      case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
14256      case 0x3C6:                         // vcmpbfp
14257         if (!allow_V) goto decode_noV;
14258         if (dis_av_fp_cmp( theInstr )) goto decode_success;
14259         goto decode_failure;
14260
14261      default:
14262         goto decode_failure;
14263      }
14264      break;
14265
14266   default:
14267      goto decode_failure;
14268
14269   decode_noF:
14270      vassert(!allow_F);
14271      vex_printf("disInstr(ppc): declined to decode an FP insn.\n");
14272      goto decode_failure;
14273   decode_noV:
14274      vassert(!allow_V);
14275      vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n");
14276      goto decode_failure;
14277   decode_noVX:
14278      vassert(!allow_VX);
14279      vex_printf("disInstr(ppc): declined to decode a Power ISA 2.06 insn.\n");
14280      goto decode_failure;
14281   decode_noFX:
14282      vassert(!allow_FX);
14283      vex_printf("disInstr(ppc): "
14284                 "declined to decode a GeneralPurpose-Optional insn.\n");
14285      goto decode_failure;
14286   decode_noGX:
14287      vassert(!allow_GX);
14288      vex_printf("disInstr(ppc): "
14289                 "declined to decode a Graphics-Optional insn.\n");
14290      goto decode_failure;
14291
14292   decode_failure:
14293   /* All decode failures end up here. */
14294   opc2 = (theInstr) & 0x7FF;
14295   vex_printf("disInstr(ppc): unhandled instruction: "
14296              "0x%x\n", theInstr);
14297   vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
14298              opc1, opc1, opc2, opc2);
14299
14300   /* Tell the dispatcher that this insn cannot be decoded, and so has
14301      not been executed, and (is currently) the next to be executed.
14302      CIA should be up-to-date since it made so at the start of each
14303      insn, but nevertheless be paranoid and update it again right
14304      now. */
14305   putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
14306   irsb->next     = mkSzImm(ty, guest_CIA_curr_instr);
14307   irsb->jumpkind = Ijk_NoDecode;
14308   dres.whatNext  = Dis_StopHere;
14309   dres.len       = 0;
14310   return dres;
14311
14312   } /* switch (opc) for the main (primary) opcode switch. */
14313
14314  decode_success:
14315   /* All decode successes end up here. */
14316   DIP("\n");
14317
14318   if (dres.len == 0) {
14319      dres.len = 4;
14320   } else {
14321      vassert(dres.len == 20);
14322   }
14323   return dres;
14324}
14325
14326#undef DIP
14327#undef DIS
14328
14329
14330/*------------------------------------------------------------*/
14331/*--- Top-level fn                                         ---*/
14332/*------------------------------------------------------------*/
14333
14334/* Disassemble a single instruction into IR.  The instruction
14335   is located in host memory at &guest_code[delta]. */
14336
14337DisResult disInstr_PPC ( IRSB*        irsb_IN,
14338                         Bool         put_IP,
14339                         Bool         (*resteerOkFn) ( void*, Addr64 ),
14340                         Bool         resteerCisOk,
14341                         void*        callback_opaque,
14342                         UChar*       guest_code_IN,
14343                         Long         delta,
14344                         Addr64       guest_IP,
14345                         VexArch      guest_arch,
14346                         VexArchInfo* archinfo,
14347                         VexAbiInfo*  abiinfo,
14348                         Bool         host_bigendian_IN )
14349{
14350   IRType     ty;
14351   DisResult  dres;
14352   UInt       mask32, mask64;
14353   UInt hwcaps_guest = archinfo->hwcaps;
14354
14355   vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
14356
14357   /* global -- ick */
14358   mode64 = guest_arch == VexArchPPC64;
14359   ty = mode64 ? Ity_I64 : Ity_I32;
14360
14361   /* do some sanity checks */
14362   mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
14363            | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX;
14364
14365   mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
14366		   | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX;
14367
14368   if (mode64) {
14369      vassert((hwcaps_guest & mask32) == 0);
14370   } else {
14371      vassert((hwcaps_guest & mask64) == 0);
14372   }
14373
14374   /* Set globals (see top of this file) */
14375   guest_code           = guest_code_IN;
14376   irsb                 = irsb_IN;
14377   host_is_bigendian    = host_bigendian_IN;
14378
14379   guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
14380   guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
14381
14382   dres = disInstr_PPC_WRK ( put_IP,
14383                             resteerOkFn, resteerCisOk, callback_opaque,
14384                             delta, archinfo, abiinfo );
14385
14386   return dres;
14387}
14388
14389
14390/*------------------------------------------------------------*/
14391/*--- Unused stuff                                         ---*/
14392/*------------------------------------------------------------*/
14393
14394///* A potentially more memcheck-friendly implementation of Clz32, with
14395//   the boundary case Clz32(0) = 32, which is what ppc requires. */
14396//
14397//static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
14398//{
14399//   /* Welcome ... to SSA R Us. */
14400//   IRTemp n1  = newTemp(Ity_I32);
14401//   IRTemp n2  = newTemp(Ity_I32);
14402//   IRTemp n3  = newTemp(Ity_I32);
14403//   IRTemp n4  = newTemp(Ity_I32);
14404//   IRTemp n5  = newTemp(Ity_I32);
14405//   IRTemp n6  = newTemp(Ity_I32);
14406//   IRTemp n7  = newTemp(Ity_I32);
14407//   IRTemp n8  = newTemp(Ity_I32);
14408//   IRTemp n9  = newTemp(Ity_I32);
14409//   IRTemp n10 = newTemp(Ity_I32);
14410//   IRTemp n11 = newTemp(Ity_I32);
14411//   IRTemp n12 = newTemp(Ity_I32);
14412//
14413//   /* First, propagate the most significant 1-bit into all lower
14414//      positions in the word. */
14415//   /* unsigned int clz ( unsigned int n )
14416//      {
14417//         n |= (n >> 1);
14418//         n |= (n >> 2);
14419//         n |= (n >> 4);
14420//         n |= (n >> 8);
14421//         n |= (n >> 16);
14422//         return bitcount(~n);
14423//      }
14424//   */
14425//   assign(n1, mkexpr(arg));
14426//   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
14427//   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
14428//   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
14429//   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
14430//   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
14431//   /* This gives a word of the form 0---01---1.  Now invert it, giving
14432//      a word of the form 1---10---0, then do a population-count idiom
14433//      (to count the 1s, which is the number of leading zeroes, or 32
14434//      if the original word was 0. */
14435//   assign(n7, unop(Iop_Not32, mkexpr(n6)));
14436//
14437//   /* unsigned int bitcount ( unsigned int n )
14438//      {
14439//         n = n - ((n >> 1) & 0x55555555);
14440//         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
14441//         n = (n + (n >> 4)) & 0x0F0F0F0F;
14442//         n = n + (n >> 8);
14443//         n = (n + (n >> 16)) & 0x3F;
14444//         return n;
14445//      }
14446//   */
14447//   assign(n8,
14448//          binop(Iop_Sub32,
14449//                mkexpr(n7),
14450//                binop(Iop_And32,
14451//                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
14452//                      mkU32(0x55555555))));
14453//   assign(n9,
14454//          binop(Iop_Add32,
14455//                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
14456//                binop(Iop_And32,
14457//                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
14458//                      mkU32(0x33333333))));
14459//   assign(n10,
14460//          binop(Iop_And32,
14461//                binop(Iop_Add32,
14462//                      mkexpr(n9),
14463//                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
14464//                mkU32(0x0F0F0F0F)));
14465//   assign(n11,
14466//          binop(Iop_Add32,
14467//                mkexpr(n10),
14468//                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
14469//   assign(n12,
14470//          binop(Iop_Add32,
14471//                mkexpr(n11),
14472//                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
14473//   return
14474//      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
14475//}
14476
14477/*--------------------------------------------------------------------*/
14478/*--- end                                         guest_ppc_toIR.c ---*/
14479/*--------------------------------------------------------------------*/
14480