1
2/*--------------------------------------------------------------------*/
3/*--- begin                                       guest_ppc_toIR.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
9
10   Copyright (C) 2004-2015 OpenWorks LLP
11      info@open-works.net
12
13   This program is free software; you can redistribute it and/or
14   modify it under the terms of the GNU General Public License as
15   published by the Free Software Foundation; either version 2 of the
16   License, or (at your option) any later version.
17
18   This program is distributed in the hope that it will be useful, but
19   WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21   General Public License for more details.
22
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26   02110-1301, USA.
27
28   The GNU General Public License is contained in the file COPYING.
29
30   Neither the names of the U.S. Department of Energy nor the
31   University of California nor the names of its contributors may be
32   used to endorse or promote products derived from this software
33   without prior written permission.
34*/
35
36/* TODO 18/Nov/05:
37
38   Spot rld... cases which are simply left/right shifts and emit
39   Shl64/Shr64 accordingly.
40
41   Altivec
42   - datastream insns
43   - lvxl,stvxl: load/store with 'least recently used' hint
44   - vexptefp, vlogefp
45
46   LIMITATIONS:
47
48   Various, including:
49
50   - Some invalid forms of lswi and lswx are accepted when they should
51     not be.
52
53   - Floating Point:
54     - All exceptions disabled in FPSCR
55     - condition codes not set in FPSCR
56
57   - Altivec floating point:
58     - vmaddfp, vnmsubfp
59       Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
60       system default of Non-Java mode, we get some small errors
61       (lowest bit only).
62       This is because Non-Java mode brutally hacks denormalised results
63       to zero, whereas we keep maximum accuracy.  However, using
64       Non-Java mode would give us more inaccuracy, as our intermediate
65       results would then be zeroed, too.
66
67   - AbiHints for the stack red zone are only emitted for
68       unconditional calls and returns (bl, blr).  They should also be
69       emitted for conditional calls and returns, but we don't have a
70       way to express that right now.  Ah well.
71
72   - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c)
73       ignores the rounding mode, and generates code that assumes
74       round-to-nearest.  This means V will compute incorrect results
75       for uses of these IROps when the rounding mode (first) arg is
76       not mkU32(Irrm_NEAREST).
77*/
78
79/* "Special" instructions.
80
81   This instruction decoder can decode four special instructions
82   which mean nothing natively (are no-ops as far as regs/mem are
83   concerned) but have meaning for supporting Valgrind.  A special
84   instruction is flagged by a 16-byte preamble:
85
86      32-bit mode: 5400183E 5400683E 5400E83E 5400983E
87                   (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31;
88                    rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31)
89
90      64-bit mode: 78001800 78006800 7800E802 78009802
91                   (rotldi 0,0,3; rotldi 0,0,13;
92                    rotldi 0,0,61; rotldi 0,0,51)
93
94   Following that, one of the following 3 are allowed
95   (standard interpretation in parentheses):
96
97      7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
98      7C421378 (or 2,2,2)   %R3 = guest_NRADDR
99      7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11  Big endian
100      7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R12  Little endian
101      7C842378 (or 4,4,4)   %R3 = guest_NRADDR_GPR2
102      7CA52B78 (or 5,5,5)   IR injection
103
104   Any other bytes following the 16-byte preamble are illegal and
105   constitute a failure in instruction decoding.  This all assumes
106   that the preamble will never occur except in specific code
107   fragments designed for Valgrind to catch.
108*/
109
110/*  Little Endian notes  */
111/*
112 * Vector operations in little Endian mode behave in non-obvious ways at times.
113 * Below is an attempt at explaining this.
114 *
115 * LE/BE vector example
116 *   With a vector of unsigned ints declared as follows:
117 *     vector unsigned int vec_inA =
118                            { 0x11111111, 0x22222222, 0x33333333, 0x44444444 };
119 *   The '0x11111111' word is word zero in both LE and BE format.  But the
120 *   loaded vector register will have word zero on the far left in BE mode and
121 *   on the far right in LE mode. The lvx and stvx instructions work naturally
122 *   for whatever endianness is in effect.  For example, in LE mode, the stvx
123 *   stores word zero (far right word) of the vector at the lowest memory
124 *   address of the EA; in BE mode, stvx still stores word zero at the lowest
125 *   memory address, but with word zero interpreted as the one at the far left
126 *   of the register.
127 *
128 *   The lxvd2x and stxvd2x instructions are not so well suited for LE mode.
129 *   When the compiler generates an lxvd2x instruction to load the
130 *   above-declared vector of unsigned integers, it loads the vector as two
131 *   double words, but they are in BE word-wise format.  To put the vector in
132 *   the right order for LE, the compiler also generates an xxswapd after the
133 *   load, which puts it in proper LE format.  Similarly, the stxvd2x
134 *   instruction has a BE bias, storing the vector in BE word-wise format. But
135 *   the compiler also generates an xxswapd prior to the store, thus ensuring
136 *   the vector is stored in memory in the correct LE order.
137 *
138 *   Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts
139 *   of a double words and words within a vector.  Because of the reverse order
140 *   of numbering for LE as described above, the high part refers to word 1 in
141 *   LE format. When input data is saved to a guest state vector register
142 *   (e.g., via Iop_64HLtoV128), it is first saved to memory and then the
143 *   register is loaded via PPCInstr_AvLdSt, which does an lvx instruction.
144 *   The saving of the data to memory must be done in proper LE order.  For the
145 *   inverse operation of extracting data from a vector register (e.g.,
146 *   Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting
147 *   in stvx), and then integer registers are loaded from the memory location
148 *   from where the vector register was saved.  Again, this must be done in
149 *   proper LE order.  So for these various vector Iops, we have LE-specific
150 *   code in host_ppc_isel.c
151 *
152 *   Another unique behavior of vectors in LE mode is with the vector scalar
153 *   (VSX) operations that operate on "double word 0" of the source register,
154 *   storing the result in "double word 0" of the output vector register.  For
155 *   these operations, "double word 0" is interpreted as "high half of the
156 *   register" (i.e, the part on the left side).
157 *
158 */
159/* Translates PPC32/64 code to IR. */
160
161/* References
162
163#define PPC32
164   "PowerPC Microprocessor Family:
165    The Programming Environments Manual for 32-Bit Microprocessors"
166    02/21/2000
167    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
168
169#define PPC64
170   "PowerPC Microprocessor Family:
171    Programming Environments Manual for 64-Bit Microprocessors"
172    06/10/2003
173   http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
174
175#define AV
176   "PowerPC Microprocessor Family:
177    AltiVec(TM) Technology Programming Environments Manual"
178    07/10/2003
179   http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
180*/
181
182#include "libvex_basictypes.h"
183#include "libvex_ir.h"
184#include "libvex.h"
185#include "libvex_emnote.h"
186#include "libvex_guest_ppc32.h"
187#include "libvex_guest_ppc64.h"
188
189#include "main_util.h"
190#include "main_globals.h"
191#include "guest_generic_bb_to_IR.h"
192#include "guest_ppc_defs.h"
193
194/*------------------------------------------------------------*/
195/*--- Globals                                              ---*/
196/*------------------------------------------------------------*/
197
198/* These are set at the start of the translation of an insn, right
199   down in disInstr_PPC, so that we don't have to pass them around
200   endlessly.  They are all constant during the translation of any
201   given insn. */
202
203/* We need to know this to do sub-register accesses correctly. */
204static VexEndness host_endness;
205
206/* Pointer to the guest code area. */
207static const UChar* guest_code;
208
209/* The guest address corresponding to guest_code[0]. */
210static Addr64 guest_CIA_bbstart;
211
212/* The guest address for the instruction currently being
213   translated. */
214static Addr64 guest_CIA_curr_instr;
215
216/* The IRSB* into which we're generating code. */
217static IRSB* irsb;
218
219/* Is our guest binary 32 or 64bit?  Set at each call to
220   disInstr_PPC below. */
221static Bool mode64 = False;
222
223// Given a pointer to a function as obtained by "& functionname" in C,
224// produce a pointer to the actual entry point for the function.  For
225// most platforms it's the identity function.  Unfortunately, on
226// ppc64-linux it isn't (sigh)
227static void* fnptr_to_fnentry( const VexAbiInfo* vbi, void* f )
228{
229   if (vbi->host_ppc_calls_use_fndescrs) {
230      /* f is a pointer to a 3-word function descriptor, of which the
231         first word is the entry address. */
232      /* note, this is correct even with cross-jitting, since this is
233         purely a host issue, not a guest one. */
234      HWord* fdescr = (HWord*)f;
235      return (void*)(fdescr[0]);
236   } else {
237      /* Simple; "& f" points directly at the code for f. */
238      return f;
239   }
240}
241
242#define SIGN_BIT  0x8000000000000000ULL
243#define SIGN_MASK 0x7fffffffffffffffULL
244#define SIGN_BIT32  0x80000000
245#define SIGN_MASK32 0x7fffffff
246
247
248/*------------------------------------------------------------*/
249/*--- Debugging output                                     ---*/
250/*------------------------------------------------------------*/
251
252#define DIP(format, args...)           \
253   if (vex_traceflags & VEX_TRACE_FE)  \
254      vex_printf(format, ## args)
255
256#define DIS(buf, format, args...)      \
257   if (vex_traceflags & VEX_TRACE_FE)  \
258      vex_sprintf(buf, format, ## args)
259
260
261/*------------------------------------------------------------*/
262/*--- Offsets of various parts of the ppc32/64 guest state ---*/
263/*------------------------------------------------------------*/
264
265#define offsetofPPCGuestState(_x) \
266   (mode64 ? offsetof(VexGuestPPC64State, _x) : \
267             offsetof(VexGuestPPC32State, _x))
268
269#define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
270#define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
271#define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
272#define OFFB_LR          offsetofPPCGuestState(guest_LR)
273#define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
274#define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
275#define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
276#define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
277#define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
278#define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
279#define OFFB_DFPROUND    offsetofPPCGuestState(guest_DFPROUND)
280#define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
281#define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
282#define OFFB_EMNOTE      offsetofPPCGuestState(guest_EMNOTE)
283#define OFFB_CMSTART     offsetofPPCGuestState(guest_CMSTART)
284#define OFFB_CMLEN       offsetofPPCGuestState(guest_CMLEN)
285#define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
286#define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
287#define OFFB_TFHAR       offsetofPPCGuestState(guest_TFHAR)
288#define OFFB_TEXASR      offsetofPPCGuestState(guest_TEXASR)
289#define OFFB_TEXASRU     offsetofPPCGuestState(guest_TEXASRU)
290#define OFFB_TFIAR       offsetofPPCGuestState(guest_TFIAR)
291#define OFFB_PPR         offsetofPPCGuestState(guest_PPR)
292#define OFFB_PSPB        offsetofPPCGuestState(guest_PSPB)
293
294
295/*------------------------------------------------------------*/
296/*--- Extract instruction fields                          --- */
297/*------------------------------------------------------------*/
298
299/* Extract field from insn, given idx (zero = lsb) and field length */
300#define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
301
302/* Extract primary opcode, instr[31:26] */
303static UChar ifieldOPC( UInt instr ) {
304   return toUChar( IFIELD( instr, 26, 6 ) );
305}
306
307/* Extract 10-bit secondary opcode, instr[10:1] */
308static UInt ifieldOPClo10 ( UInt instr) {
309   return IFIELD( instr, 1, 10 );
310}
311
312/* Extract 9-bit secondary opcode, instr[9:1] */
313static UInt ifieldOPClo9 ( UInt instr) {
314   return IFIELD( instr, 1, 9 );
315}
316
317/* Extract 8-bit secondary opcode, instr[8:1] */
318static UInt ifieldOPClo8 ( UInt instr) {
319   return IFIELD( instr, 1, 8 );
320}
321
322/* Extract 5-bit secondary opcode, instr[5:1] */
323static UInt ifieldOPClo5 ( UInt instr) {
324   return IFIELD( instr, 1, 5 );
325}
326
327/* Extract RD (destination register) field, instr[25:21] */
328static UChar ifieldRegDS( UInt instr ) {
329   return toUChar( IFIELD( instr, 21, 5 ) );
330}
331
332/* Extract XT (destination register) field, instr[0,25:21] */
333static UChar ifieldRegXT ( UInt instr )
334{
335  UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
336  UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
337  return (upper_bit << 5) | lower_bits;
338}
339
340/* Extract XS (store source register) field, instr[0,25:21] */
341static inline UChar ifieldRegXS ( UInt instr )
342{
343  return ifieldRegXT ( instr );
344}
345
346/* Extract RA (1st source register) field, instr[20:16] */
347static UChar ifieldRegA ( UInt instr ) {
348   return toUChar( IFIELD( instr, 16, 5 ) );
349}
350
351/* Extract XA (1st source register) field, instr[2,20:16] */
352static UChar ifieldRegXA ( UInt instr )
353{
354  UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
355  UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
356  return (upper_bit << 5) | lower_bits;
357}
358
359/* Extract RB (2nd source register) field, instr[15:11] */
360static UChar ifieldRegB ( UInt instr ) {
361   return toUChar( IFIELD( instr, 11, 5 ) );
362}
363
364/* Extract XB (2nd source register) field, instr[1,15:11] */
365static UChar ifieldRegXB ( UInt instr )
366{
367  UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
368  UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
369  return (upper_bit << 5) | lower_bits;
370}
371
372/* Extract RC (3rd source register) field, instr[10:6] */
373static UChar ifieldRegC ( UInt instr ) {
374   return toUChar( IFIELD( instr, 6, 5 ) );
375}
376
377/* Extract XC (3rd source register) field, instr[3,10:6] */
378static UChar ifieldRegXC ( UInt instr )
379{
380  UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
381  UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
382  return (upper_bit << 5) | lower_bits;
383}
384
385/* Extract bit 10, instr[10] */
386static UChar ifieldBIT10 ( UInt instr ) {
387   return toUChar( IFIELD( instr, 10, 1 ) );
388}
389
390/* Extract 2nd lowest bit, instr[1] */
391static UChar ifieldBIT1 ( UInt instr ) {
392   return toUChar( IFIELD( instr, 1, 1 ) );
393}
394
395/* Extract lowest bit, instr[0] */
396static UChar ifieldBIT0 ( UInt instr ) {
397   return toUChar( instr & 0x1 );
398}
399
400/* Extract unsigned bottom half, instr[15:0] */
401static UInt ifieldUIMM16 ( UInt instr ) {
402   return instr & 0xFFFF;
403}
404
405/* Extract unsigned bottom 26 bits, instr[25:0] */
406static UInt ifieldUIMM26 ( UInt instr ) {
407   return instr & 0x3FFFFFF;
408}
409
410/* Extract DM field, instr[9:8] */
411static UChar ifieldDM ( UInt instr ) {
412   return toUChar( IFIELD( instr, 8, 2 ) );
413}
414
415/* Extract SHW field, instr[9:8] */
416static inline UChar ifieldSHW ( UInt instr )
417{
418  return ifieldDM ( instr );
419}
420
421/*------------------------------------------------------------*/
422/*--- Guest-state identifiers                              ---*/
423/*------------------------------------------------------------*/
424
425typedef enum {
426    PPC_GST_CIA,    // Current Instruction Address
427    PPC_GST_LR,     // Link Register
428    PPC_GST_CTR,    // Count Register
429    PPC_GST_XER,    // Overflow, carry flags, byte count
430    PPC_GST_CR,     // Condition Register
431    PPC_GST_FPSCR,  // Floating Point Status/Control Register
432    PPC_GST_VRSAVE, // Vector Save/Restore Register
433    PPC_GST_VSCR,   // Vector Status and Control Register
434    PPC_GST_EMWARN, // Emulation warnings
435    PPC_GST_CMSTART,// For icbi: start of area to invalidate
436    PPC_GST_CMLEN,  // For icbi: length of area to invalidate
437    PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
438    PPC_GST_SPRG3_RO, // SPRG3
439    PPC_GST_TFHAR,  // Transactional Failure Handler Address Register
440    PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
441    PPC_GST_TEXASR, // Transactional EXception And Summary Register
442    PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper
443    PPC_GST_PPR,     // Program Priority register
444    PPC_GST_PPR32,   // Upper 32-bits of Program Priority register
445    PPC_GST_PSPB,    /* Problem State Priority Boost register, Note, the
446                      * register is initialized to a non-zero value.  Currently
447                      * Valgrind is not supporting the register value to
448                      * automatically decrement. Could be added later if
449                      * needed.
450                      */
451    PPC_GST_MAX
452} PPC_GST;
453
454#define MASK_FPSCR_RN   0x3ULL  // Binary floating point rounding mode
455#define MASK_FPSCR_DRN  0x700000000ULL // Decimal floating point rounding mode
456#define MASK_VSCR_VALID 0x00010001
457
458
459/*------------------------------------------------------------*/
460/*---  FP Helpers                                          ---*/
461/*------------------------------------------------------------*/
462
463/* Produce the 32-bit pattern corresponding to the supplied
464   float. */
465static UInt float_to_bits ( Float f )
466{
467   union { UInt i; Float f; } u;
468   vassert(4 == sizeof(UInt));
469   vassert(4 == sizeof(Float));
470   vassert(4 == sizeof(u));
471   u.f = f;
472   return u.i;
473}
474
475
476/*------------------------------------------------------------*/
477/*--- Misc Helpers                                         ---*/
478/*------------------------------------------------------------*/
479
480/* Generate mask with 1's from 'begin' through 'end',
481   wrapping if begin > end.
482   begin->end works from right to left, 0=lsb
483*/
484static UInt MASK32( UInt begin, UInt end )
485{
486   UInt m1, m2, mask;
487   vassert(begin < 32);
488   vassert(end < 32);
489   m1   = ((UInt)(-1)) << begin;
490   m2   = ((UInt)(-1)) << end << 1;
491   mask = m1 ^ m2;
492   if (begin > end) mask = ~mask;  // wrap mask
493   return mask;
494}
495
496static ULong MASK64( UInt begin, UInt end )
497{
498   ULong m1, m2, mask;
499   vassert(begin < 64);
500   vassert(end < 64);
501   m1   = ((ULong)(-1)) << begin;
502   m2   = ((ULong)(-1)) << end << 1;
503   mask = m1 ^ m2;
504   if (begin > end) mask = ~mask;  // wrap mask
505   return mask;
506}
507
508static Addr64 nextInsnAddr( void )
509{
510   return guest_CIA_curr_instr + 4;
511}
512
513
514/*------------------------------------------------------------*/
515/*--- Helper bits and pieces for deconstructing the        ---*/
516/*--- ppc32/64 insn stream.                                ---*/
517/*------------------------------------------------------------*/
518
519/* Add a statement to the list held by "irsb". */
520static void stmt ( IRStmt* st )
521{
522   addStmtToIRSB( irsb, st );
523}
524
525/* Generate a new temporary of the given type. */
526static IRTemp newTemp ( IRType ty )
527{
528   vassert(isPlausibleIRType(ty));
529   return newIRTemp( irsb->tyenv, ty );
530}
531
532/* Various simple conversions */
533
534static UChar extend_s_5to8 ( UChar x )
535{
536   return toUChar((((Int)x) << 27) >> 27);
537}
538
539static UInt extend_s_8to32( UChar x )
540{
541   return (UInt)((((Int)x) << 24) >> 24);
542}
543
544static UInt extend_s_16to32 ( UInt x )
545{
546   return (UInt)((((Int)x) << 16) >> 16);
547}
548
549static ULong extend_s_16to64 ( UInt x )
550{
551   return (ULong)((((Long)x) << 48) >> 48);
552}
553
554static ULong extend_s_26to64 ( UInt x )
555{
556   return (ULong)((((Long)x) << 38) >> 38);
557}
558
559static ULong extend_s_32to64 ( UInt x )
560{
561   return (ULong)((((Long)x) << 32) >> 32);
562}
563
564/* Do a proper-endian load of a 32-bit word, regardless of the endianness
565   of the underlying host. */
566static UInt getUIntPPCendianly ( const UChar* p )
567{
568   UInt w = 0;
569   if (host_endness == VexEndnessBE) {
570       w = (w << 8) | p[0];
571       w = (w << 8) | p[1];
572       w = (w << 8) | p[2];
573       w = (w << 8) | p[3];
574   } else {
575       w = (w << 8) | p[3];
576       w = (w << 8) | p[2];
577       w = (w << 8) | p[1];
578       w = (w << 8) | p[0];
579   }
580   return w;
581}
582
583
584/*------------------------------------------------------------*/
585/*--- Helpers for constructing IR.                         ---*/
586/*------------------------------------------------------------*/
587
588static void assign ( IRTemp dst, IRExpr* e )
589{
590   stmt( IRStmt_WrTmp(dst, e) );
591}
592
593/* This generates a normal (non store-conditional) store. */
594static void store ( IRExpr* addr, IRExpr* data )
595{
596   IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
597   vassert(tyA == Ity_I32 || tyA == Ity_I64);
598
599   if (host_endness == VexEndnessBE)
600      stmt( IRStmt_Store(Iend_BE, addr, data) );
601   else
602      stmt( IRStmt_Store(Iend_LE, addr, data) );
603}
604
605static IRExpr* unop ( IROp op, IRExpr* a )
606{
607   return IRExpr_Unop(op, a);
608}
609
610static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
611{
612   return IRExpr_Binop(op, a1, a2);
613}
614
615static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
616{
617   return IRExpr_Triop(op, a1, a2, a3);
618}
619
620static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
621                              IRExpr* a3, IRExpr* a4 )
622{
623   return IRExpr_Qop(op, a1, a2, a3, a4);
624}
625
626static IRExpr* mkexpr ( IRTemp tmp )
627{
628   return IRExpr_RdTmp(tmp);
629}
630
631static IRExpr* mkU8 ( UChar i )
632{
633   return IRExpr_Const(IRConst_U8(i));
634}
635
636static IRExpr* mkU16 ( UInt i )
637{
638   return IRExpr_Const(IRConst_U16(i));
639}
640
641static IRExpr* mkU32 ( UInt i )
642{
643   return IRExpr_Const(IRConst_U32(i));
644}
645
646static IRExpr* mkU64 ( ULong i )
647{
648   return IRExpr_Const(IRConst_U64(i));
649}
650
651static IRExpr* mkV128 ( UShort i )
652{
653   vassert(i == 0 || i == 0xffff);
654   return IRExpr_Const(IRConst_V128(i));
655}
656
657/* This generates a normal (non load-linked) load. */
658static IRExpr* load ( IRType ty, IRExpr* addr )
659{
660   if (host_endness == VexEndnessBE)
661      return IRExpr_Load(Iend_BE, ty, addr);
662   else
663      return IRExpr_Load(Iend_LE, ty, addr);
664}
665
666static IRStmt* stmt_load ( IRTemp result,
667                           IRExpr* addr, IRExpr* storedata )
668{
669   if (host_endness == VexEndnessBE)
670      return IRStmt_LLSC(Iend_BE, result, addr, storedata);
671   else
672      return IRStmt_LLSC(Iend_LE, result, addr, storedata);
673}
674
675static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
676{
677   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
678   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
679   return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
680                                          unop(Iop_1Uto32, arg2)));
681}
682
683static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
684{
685   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
686   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
687   return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
688                                           unop(Iop_1Uto32, arg2)));
689}
690
691/* expand V128_8Ux16 to 2x V128_16Ux8's */
692static void expand8Ux16( IRExpr* vIn,
693                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
694{
695   IRTemp ones8x16 = newTemp(Ity_V128);
696
697   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
698   vassert(vEvn && *vEvn == IRTemp_INVALID);
699   vassert(vOdd && *vOdd == IRTemp_INVALID);
700   *vEvn = newTemp(Ity_V128);
701   *vOdd = newTemp(Ity_V128);
702
703   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
704   assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
705   assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
706                        binop(Iop_ShrV128, vIn, mkU8(8))) );
707}
708
709/* expand V128_8Sx16 to 2x V128_16Sx8's */
710static void expand8Sx16( IRExpr* vIn,
711                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
712{
713   IRTemp ones8x16 = newTemp(Ity_V128);
714
715   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
716   vassert(vEvn && *vEvn == IRTemp_INVALID);
717   vassert(vOdd && *vOdd == IRTemp_INVALID);
718   *vEvn = newTemp(Ity_V128);
719   *vOdd = newTemp(Ity_V128);
720
721   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
722   assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
723   assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
724                        binop(Iop_ShrV128, vIn, mkU8(8))) );
725}
726
727/* expand V128_16Uto8 to 2x V128_32Ux4's */
728static void expand16Ux8( IRExpr* vIn,
729                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
730{
731   IRTemp ones16x8 = newTemp(Ity_V128);
732
733   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
734   vassert(vEvn && *vEvn == IRTemp_INVALID);
735   vassert(vOdd && *vOdd == IRTemp_INVALID);
736   *vEvn = newTemp(Ity_V128);
737   *vOdd = newTemp(Ity_V128);
738
739   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
740   assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
741   assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
742                        binop(Iop_ShrV128, vIn, mkU8(16))) );
743}
744
745/* expand V128_16Sto8 to 2x V128_32Sx4's */
746static void expand16Sx8( IRExpr* vIn,
747                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
748{
749   IRTemp ones16x8 = newTemp(Ity_V128);
750
751   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
752   vassert(vEvn && *vEvn == IRTemp_INVALID);
753   vassert(vOdd && *vOdd == IRTemp_INVALID);
754   *vEvn = newTemp(Ity_V128);
755   *vOdd = newTemp(Ity_V128);
756
757   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
758   assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
759   assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
760                       binop(Iop_ShrV128, vIn, mkU8(16))) );
761}
762
763/* break V128 to 4xF64's*/
764static void breakV128to4xF64( IRExpr* t128,
765                              /*OUTs*/
766                              IRTemp* t3, IRTemp* t2,
767                              IRTemp* t1, IRTemp* t0 )
768{
769   IRTemp hi64 = newTemp(Ity_I64);
770   IRTemp lo64 = newTemp(Ity_I64);
771
772   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
773   vassert(t0 && *t0 == IRTemp_INVALID);
774   vassert(t1 && *t1 == IRTemp_INVALID);
775   vassert(t2 && *t2 == IRTemp_INVALID);
776   vassert(t3 && *t3 == IRTemp_INVALID);
777   *t0 = newTemp(Ity_F64);
778   *t1 = newTemp(Ity_F64);
779   *t2 = newTemp(Ity_F64);
780   *t3 = newTemp(Ity_F64);
781
782   assign( hi64, unop(Iop_V128HIto64, t128) );
783   assign( lo64, unop(Iop_V128to64,   t128) );
784   assign( *t3,
785           unop( Iop_F32toF64,
786                 unop( Iop_ReinterpI32asF32,
787                       unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
788   assign( *t2,
789           unop( Iop_F32toF64,
790                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
791   assign( *t1,
792           unop( Iop_F32toF64,
793                 unop( Iop_ReinterpI32asF32,
794                       unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
795   assign( *t0,
796           unop( Iop_F32toF64,
797                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
798}
799
800
801/* break V128 to 4xI32's, then sign-extend to I64's */
802static void breakV128to4x64S( IRExpr* t128,
803                              /*OUTs*/
804                              IRTemp* t3, IRTemp* t2,
805                              IRTemp* t1, IRTemp* t0 )
806{
807   IRTemp hi64 = newTemp(Ity_I64);
808   IRTemp lo64 = newTemp(Ity_I64);
809
810   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
811   vassert(t0 && *t0 == IRTemp_INVALID);
812   vassert(t1 && *t1 == IRTemp_INVALID);
813   vassert(t2 && *t2 == IRTemp_INVALID);
814   vassert(t3 && *t3 == IRTemp_INVALID);
815   *t0 = newTemp(Ity_I64);
816   *t1 = newTemp(Ity_I64);
817   *t2 = newTemp(Ity_I64);
818   *t3 = newTemp(Ity_I64);
819
820   assign( hi64, unop(Iop_V128HIto64, t128) );
821   assign( lo64, unop(Iop_V128to64,   t128) );
822   assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
823   assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
824   assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
825   assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
826}
827
828/* break V128 to 4xI32's, then zero-extend to I64's */
829static void breakV128to4x64U ( IRExpr* t128,
830                               /*OUTs*/
831                               IRTemp* t3, IRTemp* t2,
832                               IRTemp* t1, IRTemp* t0 )
833{
834   IRTemp hi64 = newTemp(Ity_I64);
835   IRTemp lo64 = newTemp(Ity_I64);
836
837   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
838   vassert(t0 && *t0 == IRTemp_INVALID);
839   vassert(t1 && *t1 == IRTemp_INVALID);
840   vassert(t2 && *t2 == IRTemp_INVALID);
841   vassert(t3 && *t3 == IRTemp_INVALID);
842   *t0 = newTemp(Ity_I64);
843   *t1 = newTemp(Ity_I64);
844   *t2 = newTemp(Ity_I64);
845   *t3 = newTemp(Ity_I64);
846
847   assign( hi64, unop(Iop_V128HIto64, t128) );
848   assign( lo64, unop(Iop_V128to64,   t128) );
849   assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
850   assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
851   assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
852   assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
853}
854
855static void breakV128to4x32( IRExpr* t128,
856                              /*OUTs*/
857                              IRTemp* t3, IRTemp* t2,
858                              IRTemp* t1, IRTemp* t0 )
859{
860   IRTemp hi64 = newTemp(Ity_I64);
861   IRTemp lo64 = newTemp(Ity_I64);
862
863   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
864   vassert(t0 && *t0 == IRTemp_INVALID);
865   vassert(t1 && *t1 == IRTemp_INVALID);
866   vassert(t2 && *t2 == IRTemp_INVALID);
867   vassert(t3 && *t3 == IRTemp_INVALID);
868   *t0 = newTemp(Ity_I32);
869   *t1 = newTemp(Ity_I32);
870   *t2 = newTemp(Ity_I32);
871   *t3 = newTemp(Ity_I32);
872
873   assign( hi64, unop(Iop_V128HIto64, t128) );
874   assign( lo64, unop(Iop_V128to64,   t128) );
875   assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
876   assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
877   assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
878   assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
879}
880
881static IRExpr* mkV128from32( IRTemp t3, IRTemp t2,
882                               IRTemp t1, IRTemp t0 )
883{
884   return
885      binop( Iop_64HLtoV128,
886             binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
887             binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
888   );
889}
890
891
892/* Signed saturating narrow 64S to 32 */
893static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
894{
895   IRTemp hi32 = newTemp(Ity_I32);
896   IRTemp lo32 = newTemp(Ity_I32);
897
898   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
899
900   assign( hi32, unop(Iop_64HIto32, t64));
901   assign( lo32, unop(Iop_64to32,   t64));
902
903   return IRExpr_ITE(
904             /* if (hi32 == (lo32 >>s 31)) */
905             binop(Iop_CmpEQ32, mkexpr(hi32),
906                   binop( Iop_Sar32, mkexpr(lo32), mkU8(31))),
907             /* then: within signed-32 range: lo half good enough */
908             mkexpr(lo32),
909             /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
910             binop(Iop_Add32, mkU32(0x7FFFFFFF),
911                   binop(Iop_Shr32, mkexpr(hi32), mkU8(31))));
912}
913
914/* Unsigned saturating narrow 64S to 32 */
915static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
916{
917   IRTemp hi32 = newTemp(Ity_I32);
918   IRTemp lo32 = newTemp(Ity_I32);
919
920   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
921
922   assign( hi32, unop(Iop_64HIto32, t64));
923   assign( lo32, unop(Iop_64to32,   t64));
924
925   return IRExpr_ITE(
926            /* if (top 32 bits of t64 are 0) */
927            binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)),
928            /* then: within unsigned-32 range: lo half good enough */
929            mkexpr(lo32),
930            /* else: positive saturate -> 0xFFFFFFFF */
931            mkU32(0xFFFFFFFF));
932}
933
934/* Signed saturate narrow 64->32, combining to V128 */
935static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
936                                 IRExpr* t1, IRExpr* t0 )
937{
938   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
939   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
940   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
941   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
942   return binop(Iop_64HLtoV128,
943                binop(Iop_32HLto64,
944                      mkQNarrow64Sto32( t3 ),
945                      mkQNarrow64Sto32( t2 )),
946                binop(Iop_32HLto64,
947                      mkQNarrow64Sto32( t1 ),
948                      mkQNarrow64Sto32( t0 )));
949}
950
951/* Unsigned saturate narrow 64->32, combining to V128 */
952static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
953                                 IRExpr* t1, IRExpr* t0 )
954{
955   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
956   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
957   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
958   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
959   return binop(Iop_64HLtoV128,
960                binop(Iop_32HLto64,
961                      mkQNarrow64Uto32( t3 ),
962                      mkQNarrow64Uto32( t2 )),
963                binop(Iop_32HLto64,
964                      mkQNarrow64Uto32( t1 ),
965                      mkQNarrow64Uto32( t0 )));
966}
967
968/* Simulate irops Iop_MullOdd*, since we don't have them  */
969#define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
970      binop(Iop_MullEven8Ux16, \
971            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
972            binop(Iop_ShrV128, expr_vB, mkU8(8)))
973
974#define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
975      binop(Iop_MullEven8Sx16, \
976            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
977            binop(Iop_ShrV128, expr_vB, mkU8(8)))
978
979#define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
980      binop(Iop_MullEven16Ux8, \
981            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
982            binop(Iop_ShrV128, expr_vB, mkU8(16)))
983
984#define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
985      binop(Iop_MullEven32Ux4, \
986            binop(Iop_ShrV128, expr_vA, mkU8(32)), \
987            binop(Iop_ShrV128, expr_vB, mkU8(32)))
988
989#define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
990      binop(Iop_MullEven16Sx8, \
991            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
992            binop(Iop_ShrV128, expr_vB, mkU8(16)))
993
994#define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
995      binop(Iop_MullEven32Sx4, \
996            binop(Iop_ShrV128, expr_vA, mkU8(32)), \
997            binop(Iop_ShrV128, expr_vB, mkU8(32)))
998
999
1000static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
1001{
1002   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1003   return unop(Iop_32Sto64, unop(Iop_64to32, src));
1004}
1005
1006static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
1007{
1008   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1009   return unop(Iop_32Uto64, unop(Iop_64to32, src));
1010}
1011
1012static IROp mkSzOp ( IRType ty, IROp op8 )
1013{
1014   Int adj;
1015   vassert(ty == Ity_I8  || ty == Ity_I16 ||
1016           ty == Ity_I32 || ty == Ity_I64);
1017   vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
1018           op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
1019           op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
1020           op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
1021           op8 == Iop_Not8 );
1022   adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
1023   return adj + op8;
1024}
1025
1026/* Make sure we get valid 32 and 64bit addresses */
1027static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
1028{
1029   vassert(ty == Ity_I32 || ty == Ity_I64);
1030   return ( ty == Ity_I64 ?
1031            (Addr64)addr :
1032            (Addr64)extend_s_32to64( toUInt(addr) ) );
1033}
1034
1035/* sz, ULong -> IRExpr */
1036static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
1037{
1038   vassert(ty == Ity_I32 || ty == Ity_I64);
1039   return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
1040}
1041
1042/* sz, ULong -> IRConst */
1043static IRConst* mkSzConst ( IRType ty, ULong imm64 )
1044{
1045   vassert(ty == Ity_I32 || ty == Ity_I64);
1046   return ( ty == Ity_I64 ?
1047            IRConst_U64(imm64) :
1048            IRConst_U32((UInt)imm64) );
1049}
1050
1051/* Sign extend imm16 -> IRExpr* */
1052static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
1053{
1054   vassert(ty == Ity_I32 || ty == Ity_I64);
1055   return ( ty == Ity_I64 ?
1056            mkU64(extend_s_16to64(imm16)) :
1057            mkU32(extend_s_16to32(imm16)) );
1058}
1059
1060/* Sign extend imm32 -> IRExpr* */
1061static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
1062{
1063   vassert(ty == Ity_I32 || ty == Ity_I64);
1064   return ( ty == Ity_I64 ?
1065            mkU64(extend_s_32to64(imm32)) :
1066            mkU32(imm32) );
1067}
1068
1069/* IR narrows I32/I64 -> I8/I16/I32 */
1070static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
1071{
1072   vassert(ty == Ity_I32 || ty == Ity_I64);
1073   return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
1074}
1075
1076static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
1077{
1078   vassert(ty == Ity_I32 || ty == Ity_I64);
1079   return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
1080}
1081
1082static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
1083{
1084   vassert(ty == Ity_I32 || ty == Ity_I64);
1085   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
1086}
1087
1088/* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
1089static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
1090{
1091   IROp op;
1092   vassert(ty == Ity_I32 || ty == Ity_I64);
1093   if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
1094   else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
1095   return unop(op, src);
1096}
1097
1098static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
1099{
1100   IROp op;
1101   vassert(ty == Ity_I32 || ty == Ity_I64);
1102   if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
1103   else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
1104   return unop(op, src);
1105}
1106
1107static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
1108{
1109   vassert(ty == Ity_I32 || ty == Ity_I64);
1110   if (ty == Ity_I32)
1111      return src;
1112   return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
1113}
1114
1115
1116static Int integerGuestRegOffset ( UInt archreg )
1117{
1118   vassert(archreg < 32);
1119
1120   // jrs: probably not necessary; only matters if we reference sub-parts
1121   // of the ppc registers, but that isn't the case
1122   // later: this might affect Altivec though?
1123
1124   switch (archreg) {
1125   case  0: return offsetofPPCGuestState(guest_GPR0);
1126   case  1: return offsetofPPCGuestState(guest_GPR1);
1127   case  2: return offsetofPPCGuestState(guest_GPR2);
1128   case  3: return offsetofPPCGuestState(guest_GPR3);
1129   case  4: return offsetofPPCGuestState(guest_GPR4);
1130   case  5: return offsetofPPCGuestState(guest_GPR5);
1131   case  6: return offsetofPPCGuestState(guest_GPR6);
1132   case  7: return offsetofPPCGuestState(guest_GPR7);
1133   case  8: return offsetofPPCGuestState(guest_GPR8);
1134   case  9: return offsetofPPCGuestState(guest_GPR9);
1135   case 10: return offsetofPPCGuestState(guest_GPR10);
1136   case 11: return offsetofPPCGuestState(guest_GPR11);
1137   case 12: return offsetofPPCGuestState(guest_GPR12);
1138   case 13: return offsetofPPCGuestState(guest_GPR13);
1139   case 14: return offsetofPPCGuestState(guest_GPR14);
1140   case 15: return offsetofPPCGuestState(guest_GPR15);
1141   case 16: return offsetofPPCGuestState(guest_GPR16);
1142   case 17: return offsetofPPCGuestState(guest_GPR17);
1143   case 18: return offsetofPPCGuestState(guest_GPR18);
1144   case 19: return offsetofPPCGuestState(guest_GPR19);
1145   case 20: return offsetofPPCGuestState(guest_GPR20);
1146   case 21: return offsetofPPCGuestState(guest_GPR21);
1147   case 22: return offsetofPPCGuestState(guest_GPR22);
1148   case 23: return offsetofPPCGuestState(guest_GPR23);
1149   case 24: return offsetofPPCGuestState(guest_GPR24);
1150   case 25: return offsetofPPCGuestState(guest_GPR25);
1151   case 26: return offsetofPPCGuestState(guest_GPR26);
1152   case 27: return offsetofPPCGuestState(guest_GPR27);
1153   case 28: return offsetofPPCGuestState(guest_GPR28);
1154   case 29: return offsetofPPCGuestState(guest_GPR29);
1155   case 30: return offsetofPPCGuestState(guest_GPR30);
1156   case 31: return offsetofPPCGuestState(guest_GPR31);
1157   default: break;
1158   }
1159   vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1160}
1161
1162static IRExpr* getIReg ( UInt archreg )
1163{
1164   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1165   vassert(archreg < 32);
1166   return IRExpr_Get( integerGuestRegOffset(archreg), ty );
1167}
1168
1169/* Ditto, but write to a reg instead. */
1170static void putIReg ( UInt archreg, IRExpr* e )
1171{
1172   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1173   vassert(archreg < 32);
1174   vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
1175   stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
1176}
1177
1178
1179/* Floating point egisters are mapped to VSX registers[0..31]. */
1180static Int floatGuestRegOffset ( UInt archreg )
1181{
1182   vassert(archreg < 32);
1183
1184   if (host_endness == VexEndnessLE) {
1185      switch (archreg) {
1186         case  0: return offsetofPPCGuestState(guest_VSR0) + 8;
1187         case  1: return offsetofPPCGuestState(guest_VSR1) + 8;
1188         case  2: return offsetofPPCGuestState(guest_VSR2) + 8;
1189         case  3: return offsetofPPCGuestState(guest_VSR3) + 8;
1190         case  4: return offsetofPPCGuestState(guest_VSR4) + 8;
1191         case  5: return offsetofPPCGuestState(guest_VSR5) + 8;
1192         case  6: return offsetofPPCGuestState(guest_VSR6) + 8;
1193         case  7: return offsetofPPCGuestState(guest_VSR7) + 8;
1194         case  8: return offsetofPPCGuestState(guest_VSR8) + 8;
1195         case  9: return offsetofPPCGuestState(guest_VSR9) + 8;
1196         case 10: return offsetofPPCGuestState(guest_VSR10) + 8;
1197         case 11: return offsetofPPCGuestState(guest_VSR11) + 8;
1198         case 12: return offsetofPPCGuestState(guest_VSR12) + 8;
1199         case 13: return offsetofPPCGuestState(guest_VSR13) + 8;
1200         case 14: return offsetofPPCGuestState(guest_VSR14) + 8;
1201         case 15: return offsetofPPCGuestState(guest_VSR15) + 8;
1202         case 16: return offsetofPPCGuestState(guest_VSR16) + 8;
1203         case 17: return offsetofPPCGuestState(guest_VSR17) + 8;
1204         case 18: return offsetofPPCGuestState(guest_VSR18) + 8;
1205         case 19: return offsetofPPCGuestState(guest_VSR19) + 8;
1206         case 20: return offsetofPPCGuestState(guest_VSR20) + 8;
1207         case 21: return offsetofPPCGuestState(guest_VSR21) + 8;
1208         case 22: return offsetofPPCGuestState(guest_VSR22) + 8;
1209         case 23: return offsetofPPCGuestState(guest_VSR23) + 8;
1210         case 24: return offsetofPPCGuestState(guest_VSR24) + 8;
1211         case 25: return offsetofPPCGuestState(guest_VSR25) + 8;
1212         case 26: return offsetofPPCGuestState(guest_VSR26) + 8;
1213         case 27: return offsetofPPCGuestState(guest_VSR27) + 8;
1214         case 28: return offsetofPPCGuestState(guest_VSR28) + 8;
1215         case 29: return offsetofPPCGuestState(guest_VSR29) + 8;
1216         case 30: return offsetofPPCGuestState(guest_VSR30) + 8;
1217         case 31: return offsetofPPCGuestState(guest_VSR31) + 8;
1218         default: break;
1219      }
1220   } else {
1221      switch (archreg) {
1222         case  0: return offsetofPPCGuestState(guest_VSR0);
1223         case  1: return offsetofPPCGuestState(guest_VSR1);
1224         case  2: return offsetofPPCGuestState(guest_VSR2);
1225         case  3: return offsetofPPCGuestState(guest_VSR3);
1226         case  4: return offsetofPPCGuestState(guest_VSR4);
1227         case  5: return offsetofPPCGuestState(guest_VSR5);
1228         case  6: return offsetofPPCGuestState(guest_VSR6);
1229         case  7: return offsetofPPCGuestState(guest_VSR7);
1230         case  8: return offsetofPPCGuestState(guest_VSR8);
1231         case  9: return offsetofPPCGuestState(guest_VSR9);
1232         case 10: return offsetofPPCGuestState(guest_VSR10);
1233         case 11: return offsetofPPCGuestState(guest_VSR11);
1234         case 12: return offsetofPPCGuestState(guest_VSR12);
1235         case 13: return offsetofPPCGuestState(guest_VSR13);
1236         case 14: return offsetofPPCGuestState(guest_VSR14);
1237         case 15: return offsetofPPCGuestState(guest_VSR15);
1238         case 16: return offsetofPPCGuestState(guest_VSR16);
1239         case 17: return offsetofPPCGuestState(guest_VSR17);
1240         case 18: return offsetofPPCGuestState(guest_VSR18);
1241         case 19: return offsetofPPCGuestState(guest_VSR19);
1242         case 20: return offsetofPPCGuestState(guest_VSR20);
1243         case 21: return offsetofPPCGuestState(guest_VSR21);
1244         case 22: return offsetofPPCGuestState(guest_VSR22);
1245         case 23: return offsetofPPCGuestState(guest_VSR23);
1246         case 24: return offsetofPPCGuestState(guest_VSR24);
1247         case 25: return offsetofPPCGuestState(guest_VSR25);
1248         case 26: return offsetofPPCGuestState(guest_VSR26);
1249         case 27: return offsetofPPCGuestState(guest_VSR27);
1250         case 28: return offsetofPPCGuestState(guest_VSR28);
1251         case 29: return offsetofPPCGuestState(guest_VSR29);
1252         case 30: return offsetofPPCGuestState(guest_VSR30);
1253         case 31: return offsetofPPCGuestState(guest_VSR31);
1254         default: break;
1255      }
1256   }
1257   vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1258}
1259
1260static IRExpr* getFReg ( UInt archreg )
1261{
1262   vassert(archreg < 32);
1263   return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1264}
1265
1266/* Ditto, but write to a reg instead. */
1267static void putFReg ( UInt archreg, IRExpr* e )
1268{
1269   vassert(archreg < 32);
1270   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1271   stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1272}
1273
1274/* get Decimal float value.  Note, they share floating point register file. */
1275static IRExpr* getDReg(UInt archreg) {
1276   IRExpr *e;
1277   vassert( archreg < 32 );
1278   e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
1279   return e;
1280}
1281static IRExpr* getDReg32(UInt archreg) {
1282   IRExpr *e;
1283   vassert( archreg < 32 );
1284   e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
1285   return e;
1286}
1287
1288/* Read a floating point register pair and combine their contents into a
1289 128-bit value */
1290static IRExpr *getDReg_pair(UInt archreg) {
1291   IRExpr *high = getDReg( archreg );
1292   IRExpr *low = getDReg( archreg + 1 );
1293
1294   return binop( Iop_D64HLtoD128, high, low );
1295}
1296
1297/* Ditto, but write to a reg instead. */
1298static void putDReg32(UInt archreg, IRExpr* e) {
1299   vassert( archreg < 32 );
1300   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
1301   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1302}
1303
1304static void putDReg(UInt archreg, IRExpr* e) {
1305   vassert( archreg < 32 );
1306   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
1307   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1308}
1309
1310/* Write a 128-bit floating point value into a register pair. */
1311static void putDReg_pair(UInt archreg, IRExpr *e) {
1312   IRTemp low = newTemp( Ity_D64 );
1313   IRTemp high = newTemp( Ity_D64 );
1314
1315   vassert( archreg < 32 );
1316   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
1317
1318   assign( low, unop( Iop_D128LOtoD64, e ) );
1319   assign( high, unop( Iop_D128HItoD64, e ) );
1320
1321   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
1322   stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
1323}
1324
1325static Int vsxGuestRegOffset ( UInt archreg )
1326{
1327   vassert(archreg < 64);
1328   switch (archreg) {
1329   case  0: return offsetofPPCGuestState(guest_VSR0);
1330   case  1: return offsetofPPCGuestState(guest_VSR1);
1331   case  2: return offsetofPPCGuestState(guest_VSR2);
1332   case  3: return offsetofPPCGuestState(guest_VSR3);
1333   case  4: return offsetofPPCGuestState(guest_VSR4);
1334   case  5: return offsetofPPCGuestState(guest_VSR5);
1335   case  6: return offsetofPPCGuestState(guest_VSR6);
1336   case  7: return offsetofPPCGuestState(guest_VSR7);
1337   case  8: return offsetofPPCGuestState(guest_VSR8);
1338   case  9: return offsetofPPCGuestState(guest_VSR9);
1339   case 10: return offsetofPPCGuestState(guest_VSR10);
1340   case 11: return offsetofPPCGuestState(guest_VSR11);
1341   case 12: return offsetofPPCGuestState(guest_VSR12);
1342   case 13: return offsetofPPCGuestState(guest_VSR13);
1343   case 14: return offsetofPPCGuestState(guest_VSR14);
1344   case 15: return offsetofPPCGuestState(guest_VSR15);
1345   case 16: return offsetofPPCGuestState(guest_VSR16);
1346   case 17: return offsetofPPCGuestState(guest_VSR17);
1347   case 18: return offsetofPPCGuestState(guest_VSR18);
1348   case 19: return offsetofPPCGuestState(guest_VSR19);
1349   case 20: return offsetofPPCGuestState(guest_VSR20);
1350   case 21: return offsetofPPCGuestState(guest_VSR21);
1351   case 22: return offsetofPPCGuestState(guest_VSR22);
1352   case 23: return offsetofPPCGuestState(guest_VSR23);
1353   case 24: return offsetofPPCGuestState(guest_VSR24);
1354   case 25: return offsetofPPCGuestState(guest_VSR25);
1355   case 26: return offsetofPPCGuestState(guest_VSR26);
1356   case 27: return offsetofPPCGuestState(guest_VSR27);
1357   case 28: return offsetofPPCGuestState(guest_VSR28);
1358   case 29: return offsetofPPCGuestState(guest_VSR29);
1359   case 30: return offsetofPPCGuestState(guest_VSR30);
1360   case 31: return offsetofPPCGuestState(guest_VSR31);
1361   case 32: return offsetofPPCGuestState(guest_VSR32);
1362   case 33: return offsetofPPCGuestState(guest_VSR33);
1363   case 34: return offsetofPPCGuestState(guest_VSR34);
1364   case 35: return offsetofPPCGuestState(guest_VSR35);
1365   case 36: return offsetofPPCGuestState(guest_VSR36);
1366   case 37: return offsetofPPCGuestState(guest_VSR37);
1367   case 38: return offsetofPPCGuestState(guest_VSR38);
1368   case 39: return offsetofPPCGuestState(guest_VSR39);
1369   case 40: return offsetofPPCGuestState(guest_VSR40);
1370   case 41: return offsetofPPCGuestState(guest_VSR41);
1371   case 42: return offsetofPPCGuestState(guest_VSR42);
1372   case 43: return offsetofPPCGuestState(guest_VSR43);
1373   case 44: return offsetofPPCGuestState(guest_VSR44);
1374   case 45: return offsetofPPCGuestState(guest_VSR45);
1375   case 46: return offsetofPPCGuestState(guest_VSR46);
1376   case 47: return offsetofPPCGuestState(guest_VSR47);
1377   case 48: return offsetofPPCGuestState(guest_VSR48);
1378   case 49: return offsetofPPCGuestState(guest_VSR49);
1379   case 50: return offsetofPPCGuestState(guest_VSR50);
1380   case 51: return offsetofPPCGuestState(guest_VSR51);
1381   case 52: return offsetofPPCGuestState(guest_VSR52);
1382   case 53: return offsetofPPCGuestState(guest_VSR53);
1383   case 54: return offsetofPPCGuestState(guest_VSR54);
1384   case 55: return offsetofPPCGuestState(guest_VSR55);
1385   case 56: return offsetofPPCGuestState(guest_VSR56);
1386   case 57: return offsetofPPCGuestState(guest_VSR57);
1387   case 58: return offsetofPPCGuestState(guest_VSR58);
1388   case 59: return offsetofPPCGuestState(guest_VSR59);
1389   case 60: return offsetofPPCGuestState(guest_VSR60);
1390   case 61: return offsetofPPCGuestState(guest_VSR61);
1391   case 62: return offsetofPPCGuestState(guest_VSR62);
1392   case 63: return offsetofPPCGuestState(guest_VSR63);
1393   default: break;
1394   }
1395   vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1396}
1397
1398/* Vector registers are mapped to VSX registers[32..63]. */
1399static Int vectorGuestRegOffset ( UInt archreg )
1400{
1401   vassert(archreg < 32);
1402
1403   switch (archreg) {
1404   case  0: return offsetofPPCGuestState(guest_VSR32);
1405   case  1: return offsetofPPCGuestState(guest_VSR33);
1406   case  2: return offsetofPPCGuestState(guest_VSR34);
1407   case  3: return offsetofPPCGuestState(guest_VSR35);
1408   case  4: return offsetofPPCGuestState(guest_VSR36);
1409   case  5: return offsetofPPCGuestState(guest_VSR37);
1410   case  6: return offsetofPPCGuestState(guest_VSR38);
1411   case  7: return offsetofPPCGuestState(guest_VSR39);
1412   case  8: return offsetofPPCGuestState(guest_VSR40);
1413   case  9: return offsetofPPCGuestState(guest_VSR41);
1414   case 10: return offsetofPPCGuestState(guest_VSR42);
1415   case 11: return offsetofPPCGuestState(guest_VSR43);
1416   case 12: return offsetofPPCGuestState(guest_VSR44);
1417   case 13: return offsetofPPCGuestState(guest_VSR45);
1418   case 14: return offsetofPPCGuestState(guest_VSR46);
1419   case 15: return offsetofPPCGuestState(guest_VSR47);
1420   case 16: return offsetofPPCGuestState(guest_VSR48);
1421   case 17: return offsetofPPCGuestState(guest_VSR49);
1422   case 18: return offsetofPPCGuestState(guest_VSR50);
1423   case 19: return offsetofPPCGuestState(guest_VSR51);
1424   case 20: return offsetofPPCGuestState(guest_VSR52);
1425   case 21: return offsetofPPCGuestState(guest_VSR53);
1426   case 22: return offsetofPPCGuestState(guest_VSR54);
1427   case 23: return offsetofPPCGuestState(guest_VSR55);
1428   case 24: return offsetofPPCGuestState(guest_VSR56);
1429   case 25: return offsetofPPCGuestState(guest_VSR57);
1430   case 26: return offsetofPPCGuestState(guest_VSR58);
1431   case 27: return offsetofPPCGuestState(guest_VSR59);
1432   case 28: return offsetofPPCGuestState(guest_VSR60);
1433   case 29: return offsetofPPCGuestState(guest_VSR61);
1434   case 30: return offsetofPPCGuestState(guest_VSR62);
1435   case 31: return offsetofPPCGuestState(guest_VSR63);
1436   default: break;
1437   }
1438   vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1439}
1440
1441static IRExpr* getVReg ( UInt archreg )
1442{
1443   vassert(archreg < 32);
1444   return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1445}
1446
1447/* Ditto, but write to a reg instead. */
1448static void putVReg ( UInt archreg, IRExpr* e )
1449{
1450   vassert(archreg < 32);
1451   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1452   stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1453}
1454
1455/* Get contents of VSX guest register */
1456static IRExpr* getVSReg ( UInt archreg )
1457{
1458   vassert(archreg < 64);
1459   return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
1460}
1461
1462/* Ditto, but write to a VSX reg instead. */
1463static void putVSReg ( UInt archreg, IRExpr* e )
1464{
1465   vassert(archreg < 64);
1466   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1467   stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
1468}
1469
1470
1471static Int guestCR321offset ( UInt cr )
1472{
1473   switch (cr) {
1474   case 0: return offsetofPPCGuestState(guest_CR0_321 );
1475   case 1: return offsetofPPCGuestState(guest_CR1_321 );
1476   case 2: return offsetofPPCGuestState(guest_CR2_321 );
1477   case 3: return offsetofPPCGuestState(guest_CR3_321 );
1478   case 4: return offsetofPPCGuestState(guest_CR4_321 );
1479   case 5: return offsetofPPCGuestState(guest_CR5_321 );
1480   case 6: return offsetofPPCGuestState(guest_CR6_321 );
1481   case 7: return offsetofPPCGuestState(guest_CR7_321 );
1482   default: vpanic("guestCR321offset(ppc)");
1483   }
1484}
1485
1486static Int guestCR0offset ( UInt cr )
1487{
1488   switch (cr) {
1489   case 0: return offsetofPPCGuestState(guest_CR0_0 );
1490   case 1: return offsetofPPCGuestState(guest_CR1_0 );
1491   case 2: return offsetofPPCGuestState(guest_CR2_0 );
1492   case 3: return offsetofPPCGuestState(guest_CR3_0 );
1493   case 4: return offsetofPPCGuestState(guest_CR4_0 );
1494   case 5: return offsetofPPCGuestState(guest_CR5_0 );
1495   case 6: return offsetofPPCGuestState(guest_CR6_0 );
1496   case 7: return offsetofPPCGuestState(guest_CR7_0 );
1497   default: vpanic("guestCR3offset(ppc)");
1498   }
1499}
1500
1501typedef enum {
1502   _placeholder0,
1503   _placeholder1,
1504   _placeholder2,
1505   BYTE,
1506   HWORD,
1507   WORD,
1508   DWORD
1509} _popcount_data_type;
1510
1511/* Generate an IR sequence to do a popcount operation on the supplied
1512   IRTemp, and return a new IRTemp holding the result.  'ty' may be
1513   Ity_I32 or Ity_I64 only. */
1514static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type )
1515{
1516  /* Do count across 2^data_type bits,
1517     byte:        data_type = 3
1518     half word:   data_type = 4
1519     word:        data_type = 5
1520     double word: data_type = 6  (not supported for 32-bit type)
1521    */
1522   Int shift[6];
1523   _popcount_data_type idx, i;
1524   IRTemp mask[6];
1525   IRTemp old = IRTemp_INVALID;
1526   IRTemp nyu = IRTemp_INVALID;
1527
1528   vassert(ty == Ity_I64 || ty == Ity_I32);
1529
1530   if (ty == Ity_I32) {
1531
1532      for (idx = 0; idx < WORD; idx++) {
1533         mask[idx]  = newTemp(ty);
1534         shift[idx] = 1 << idx;
1535      }
1536      assign(mask[0], mkU32(0x55555555));
1537      assign(mask[1], mkU32(0x33333333));
1538      assign(mask[2], mkU32(0x0F0F0F0F));
1539      assign(mask[3], mkU32(0x00FF00FF));
1540      assign(mask[4], mkU32(0x0000FFFF));
1541      old = src;
1542      for (i = 0; i < data_type; i++) {
1543         nyu = newTemp(ty);
1544         assign(nyu,
1545                binop(Iop_Add32,
1546                      binop(Iop_And32,
1547                            mkexpr(old),
1548                            mkexpr(mask[i])),
1549                      binop(Iop_And32,
1550                            binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1551                            mkexpr(mask[i]))));
1552         old = nyu;
1553      }
1554      return nyu;
1555   }
1556
1557// else, ty == Ity_I64
1558   vassert(mode64);
1559
1560   for (i = 0; i < DWORD; i++) {
1561      mask[i] = newTemp( Ity_I64 );
1562      shift[i] = 1 << i;
1563   }
1564   assign( mask[0], mkU64( 0x5555555555555555ULL ) );
1565   assign( mask[1], mkU64( 0x3333333333333333ULL ) );
1566   assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
1567   assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
1568   assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
1569   assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
1570   old = src;
1571   for (i = 0; i < data_type; i++) {
1572      nyu = newTemp( Ity_I64 );
1573      assign( nyu,
1574              binop( Iop_Add64,
1575                     binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
1576                     binop( Iop_And64,
1577                            binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
1578                            mkexpr( mask[i] ) ) ) );
1579      old = nyu;
1580   }
1581   return nyu;
1582}
1583
1584/* Special purpose population count function for
1585 * vpopcntd in 32-bit mode.
1586 */
1587static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 )
1588{
1589   Int i, shift[6];
1590   IRTemp mask[6];
1591   IRTemp old = IRTemp_INVALID;
1592   IRTemp nyu1 = IRTemp_INVALID;
1593   IRTemp nyu2 = IRTemp_INVALID;
1594   IRTemp retval = newTemp(Ity_I64);
1595
1596   vassert(!mode64);
1597
1598   for (i = 0; i < WORD; i++) {
1599      mask[i]  = newTemp(Ity_I32);
1600      shift[i] = 1 << i;
1601   }
1602   assign(mask[0], mkU32(0x55555555));
1603   assign(mask[1], mkU32(0x33333333));
1604   assign(mask[2], mkU32(0x0F0F0F0F));
1605   assign(mask[3], mkU32(0x00FF00FF));
1606   assign(mask[4], mkU32(0x0000FFFF));
1607   old = src1;
1608   for (i = 0; i < WORD; i++) {
1609      nyu1 = newTemp(Ity_I32);
1610      assign(nyu1,
1611             binop(Iop_Add32,
1612                   binop(Iop_And32,
1613                         mkexpr(old),
1614                         mkexpr(mask[i])),
1615                   binop(Iop_And32,
1616                         binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1617                         mkexpr(mask[i]))));
1618      old = nyu1;
1619   }
1620
1621   old = src2;
1622   for (i = 0; i < WORD; i++) {
1623      nyu2 = newTemp(Ity_I32);
1624      assign(nyu2,
1625             binop(Iop_Add32,
1626                   binop(Iop_And32,
1627                         mkexpr(old),
1628                         mkexpr(mask[i])),
1629                   binop(Iop_And32,
1630                         binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1631                         mkexpr(mask[i]))));
1632      old = nyu2;
1633   }
1634   assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2))));
1635   return retval;
1636}
1637
1638
1639// ROTL(src32/64, rot_amt5/6)
1640static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1641                                          IRExpr* rot_amt )
1642{
1643   IRExpr *mask, *rot;
1644   vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1645
1646   if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1647      // rot = (src << rot_amt) | (src >> (64-rot_amt))
1648      mask = binop(Iop_And8, rot_amt, mkU8(63));
1649      rot  = binop(Iop_Or64,
1650                binop(Iop_Shl64, src, mask),
1651                binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1652   } else {
1653      // rot = (src << rot_amt) | (src >> (32-rot_amt))
1654      mask = binop(Iop_And8, rot_amt, mkU8(31));
1655      rot  = binop(Iop_Or32,
1656                binop(Iop_Shl32, src, mask),
1657                binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
1658   }
1659   /* Note: the ITE not merely an optimisation; it's needed
1660      because otherwise the Shr is a shift by the word size when
1661      mask denotes zero.  For rotates by immediates, a lot of
1662      this junk gets folded out. */
1663   return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)),
1664                      /* non-zero rotate */ rot,
1665                      /*     zero rotate */ src);
1666}
1667
1668/* Standard effective address calc: (rA + rB) */
1669static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1670{
1671   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1672   vassert(rA < 32);
1673   vassert(rB < 32);
1674   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1675}
1676
1677/* Standard effective address calc: (rA + simm) */
1678static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1679{
1680   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1681   vassert(rA < 32);
1682   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
1683                mkSzExtendS16(ty, simm16));
1684}
1685
1686/* Standard effective address calc: (rA|0) */
1687static IRExpr* ea_rAor0 ( UInt rA )
1688{
1689   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1690   vassert(rA < 32);
1691   if (rA == 0) {
1692      return mkSzImm(ty, 0);
1693   } else {
1694      return getIReg(rA);
1695   }
1696}
1697
1698/* Standard effective address calc: (rA|0) + rB */
1699static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1700{
1701   vassert(rA < 32);
1702   vassert(rB < 32);
1703   return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1704}
1705
1706/* Standard effective address calc: (rA|0) + simm16 */
1707static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
1708{
1709   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1710   vassert(rA < 32);
1711   if (rA == 0) {
1712      return mkSzExtendS16(ty, simm16);
1713   } else {
1714      return ea_rA_simm( rA, simm16 );
1715   }
1716}
1717
1718
1719/* Align effective address */
1720static IRExpr* addr_align( IRExpr* addr, UChar align )
1721{
1722   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1723   ULong mask;
1724   switch (align) {
1725   case 1:  return addr;                    // byte aligned
1726   case 2:  mask = ~0ULL << 1; break;       // half-word aligned
1727   case 4:  mask = ~0ULL << 2; break;       // word aligned
1728   case 16: mask = ~0ULL << 4; break;       // quad-word aligned
1729   default:
1730      vex_printf("addr_align: align = %u\n", align);
1731      vpanic("addr_align(ppc)");
1732   }
1733
1734   vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1735   return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
1736}
1737
1738
1739/* Exit the trace if ADDR (intended to be a guest memory address) is
1740   not ALIGN-aligned, generating a request for a SIGBUS followed by a
1741   restart of the current insn. */
1742static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1743{
1744   vassert(align == 2 || align == 4 || align == 8 || align == 16);
1745   if (mode64) {
1746      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1747      stmt(
1748         IRStmt_Exit(
1749            binop(Iop_CmpNE64,
1750                  binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1751                  mkU64(0)),
1752            Ijk_SigBUS,
1753            IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
1754         )
1755      );
1756   } else {
1757      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1758      stmt(
1759         IRStmt_Exit(
1760            binop(Iop_CmpNE32,
1761                  binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1762                  mkU32(0)),
1763            Ijk_SigBUS,
1764            IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
1765         )
1766      );
1767   }
1768}
1769
1770
1771/* Generate AbiHints which mark points at which the ELF or PowerOpen
1772   ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1773   N) becomes undefined.  That is at function calls and returns.  ELF
1774   ppc32 doesn't have this "feature" (how fortunate for it).  nia is
1775   the address of the next instruction to be executed.
1776*/
1777static void make_redzone_AbiHint ( const VexAbiInfo* vbi,
1778                                   IRTemp nia, const HChar* who )
1779{
1780   Int szB = vbi->guest_stack_redzone_size;
1781   if (0) vex_printf("AbiHint: %s\n", who);
1782   vassert(szB >= 0);
1783   if (szB > 0) {
1784      if (mode64) {
1785         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1786         stmt( IRStmt_AbiHint(
1787                  binop(Iop_Sub64, getIReg(1), mkU64(szB)),
1788                  szB,
1789                  mkexpr(nia)
1790         ));
1791      } else {
1792         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1793         stmt( IRStmt_AbiHint(
1794                  binop(Iop_Sub32, getIReg(1), mkU32(szB)),
1795                  szB,
1796                  mkexpr(nia)
1797         ));
1798      }
1799   }
1800}
1801
1802
1803/*------------------------------------------------------------*/
1804/*--- Helpers for condition codes.                         ---*/
1805/*------------------------------------------------------------*/
1806
1807/* Condition register layout.
1808
1809   In the hardware, CR is laid out like this.  The leftmost end is the
1810   most significant bit in the register; however the IBM documentation
1811   numbers the bits backwards for some reason.
1812
1813   CR0      CR1    ..........   CR6       CR7
1814   0 .. 3   .......................  28 .. 31    (IBM bit numbering)
1815   31  28                             3    0     (normal bit numbering)
1816
1817   Each CR field is 4 bits:  [<,>,==,SO]
1818
1819   Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1820
1821   Indexing from BI to guest state:
1822
1823     let    n = BI / 4
1824          off = BI % 4
1825     this references CR n:
1826
1827        off==0   ->  guest_CRn_321 >> 3
1828        off==1   ->  guest_CRn_321 >> 2
1829        off==2   ->  guest_CRn_321 >> 1
1830        off==3   ->  guest_CRn_SO
1831
1832   Bear in mind the only significant bit in guest_CRn_SO is bit 0
1833   (normal notation) and in guest_CRn_321 the significant bits are
1834   3, 2 and 1 (normal notation).
1835*/
1836
1837static void putCR321 ( UInt cr, IRExpr* e )
1838{
1839   vassert(cr < 8);
1840   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1841   stmt( IRStmt_Put(guestCR321offset(cr), e) );
1842}
1843
1844static void putCR0 ( UInt cr, IRExpr* e )
1845{
1846   vassert(cr < 8);
1847   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1848   stmt( IRStmt_Put(guestCR0offset(cr), e) );
1849}
1850
1851static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1852{
1853   vassert(cr < 8);
1854   return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1855}
1856
1857static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1858{
1859   vassert(cr < 8);
1860   return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1861}
1862
1863/* Fetch the specified CR bit (as per IBM/hardware notation) and
1864   return it at the bottom of an I32; the top 31 bits are guaranteed
1865   to be zero. */
1866static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1867{
1868   UInt n   = bi / 4;
1869   UInt off = bi % 4;
1870   vassert(bi < 32);
1871   if (off == 3) {
1872      /* Fetch the SO bit for this CR field */
1873      /* Note: And32 is redundant paranoia iff guest state only has 0
1874         or 1 in that slot. */
1875      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1876   } else {
1877      /* Fetch the <, > or == bit for this CR field */
1878      return binop( Iop_And32,
1879                    binop( Iop_Shr32,
1880                           unop(Iop_8Uto32, getCR321(n)),
1881                           mkU8(toUChar(3-off)) ),
1882                    mkU32(1) );
1883   }
1884}
1885
1886/* Dually, write the least significant bit of BIT to the specified CR
1887   bit.  Indexing as per getCRbit. */
1888static void putCRbit ( UInt bi, IRExpr* bit )
1889{
1890   UInt    n, off;
1891   IRExpr* safe;
1892   vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
1893   safe = binop(Iop_And32, bit, mkU32(1));
1894   n   = bi / 4;
1895   off = bi % 4;
1896   vassert(bi < 32);
1897   if (off == 3) {
1898      /* This is the SO bit for this CR field */
1899      putCR0(n, unop(Iop_32to8, safe));
1900   } else {
1901      off = 3 - off;
1902      vassert(off == 1 || off == 2 || off == 3);
1903      putCR321(
1904         n,
1905         unop( Iop_32to8,
1906               binop( Iop_Or32,
1907                      /* old value with field masked out */
1908                      binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
1909                                       mkU32(~(1 << off))),
1910                      /* new value in the right place */
1911                      binop(Iop_Shl32, safe, mkU8(toUChar(off)))
1912               )
1913         )
1914      );
1915   }
1916}
1917
1918/* Fetch the specified CR bit (as per IBM/hardware notation) and
1919   return it somewhere in an I32; it does not matter where, but
1920   whichever bit it is, all other bits are guaranteed to be zero.  In
1921   other words, the I32-typed expression will be zero if the bit is
1922   zero and nonzero if the bit is 1.  Write into *where the index
1923   of where the bit will be. */
1924
1925static
1926IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
1927{
1928   UInt n   = bi / 4;
1929   UInt off = bi % 4;
1930   vassert(bi < 32);
1931   if (off == 3) {
1932      /* Fetch the SO bit for this CR field */
1933      /* Note: And32 is redundant paranoia iff guest state only has 0
1934         or 1 in that slot. */
1935      *where = 0;
1936      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1937   } else {
1938      /* Fetch the <, > or == bit for this CR field */
1939      *where = 3-off;
1940      return binop( Iop_And32,
1941                    unop(Iop_8Uto32, getCR321(n)),
1942                    mkU32(1 << (3-off)) );
1943   }
1944}
1945
1946/* Set the CR0 flags following an arithmetic operation.
1947   (Condition Register CR0 Field Definition, PPC32 p60)
1948*/
1949static IRExpr* getXER_SO ( void );
1950static void set_CR0 ( IRExpr* result )
1951{
1952   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
1953           typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
1954   if (mode64) {
1955      putCR321( 0, unop(Iop_64to8,
1956                        binop(Iop_CmpORD64S, result, mkU64(0))) );
1957   } else {
1958      putCR321( 0, unop(Iop_32to8,
1959                        binop(Iop_CmpORD32S, result, mkU32(0))) );
1960   }
1961   putCR0( 0, getXER_SO() );
1962}
1963
1964
1965/* Set the CR6 flags following an AltiVec compare operation.
1966 * NOTE: This also works for VSX single-precision compares.
1967 * */
1968static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
1969{
1970   /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
1971      all_ones  = (v[0] && v[1] && v[2] && v[3])
1972      all_zeros = ~(v[0] || v[1] || v[2] || v[3])
1973   */
1974   IRTemp v0 = newTemp(Ity_V128);
1975   IRTemp v1 = newTemp(Ity_V128);
1976   IRTemp v2 = newTemp(Ity_V128);
1977   IRTemp v3 = newTemp(Ity_V128);
1978   IRTemp rOnes  = newTemp(Ity_I8);
1979   IRTemp rZeros = newTemp(Ity_I8);
1980
1981   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
1982
1983   assign( v0, result );
1984   assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
1985   assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
1986   assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
1987
1988   assign( rZeros, unop(Iop_1Uto8,
1989       binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1990             unop(Iop_Not32,
1991                  unop(Iop_V128to32,
1992                       binop(Iop_OrV128,
1993                             binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
1994                             binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
1995                  ))) );
1996
1997   if (test_all_ones) {
1998      assign( rOnes, unop(Iop_1Uto8,
1999         binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
2000               unop(Iop_V128to32,
2001                    binop(Iop_AndV128,
2002                          binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
2003                          binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
2004                    ))) );
2005      putCR321( 6, binop(Iop_Or8,
2006                         binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
2007                         binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
2008   } else {
2009      putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
2010   }
2011   putCR0( 6, mkU8(0) );
2012}
2013
2014
2015
2016/*------------------------------------------------------------*/
2017/*--- Helpers for XER flags.                               ---*/
2018/*------------------------------------------------------------*/
2019
2020static void putXER_SO ( IRExpr* e )
2021{
2022   IRExpr* so;
2023   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2024   so = binop(Iop_And8, e, mkU8(1));
2025   stmt( IRStmt_Put( OFFB_XER_SO, so ) );
2026}
2027
2028static void putXER_OV ( IRExpr* e )
2029{
2030   IRExpr* ov;
2031   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2032   ov = binop(Iop_And8, e, mkU8(1));
2033   stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
2034}
2035
2036static void putXER_CA ( IRExpr* e )
2037{
2038   IRExpr* ca;
2039   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2040   ca = binop(Iop_And8, e, mkU8(1));
2041   stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
2042}
2043
2044static void putXER_BC ( IRExpr* e )
2045{
2046   IRExpr* bc;
2047   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2048   bc = binop(Iop_And8, e, mkU8(0x7F));
2049   stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
2050}
2051
2052static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
2053{
2054   return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
2055}
2056
2057static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
2058{
2059   return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
2060}
2061
2062static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
2063{
2064   return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
2065}
2066
2067static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
2068{
2069   return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
2070}
2071
2072static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
2073{
2074   IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
2075   return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
2076}
2077
2078static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
2079{
2080   return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2081}
2082
2083static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
2084{
2085   IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2086   return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
2087}
2088
2089
2090/* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
2091   %XER.SO accordingly. */
2092
2093static void set_XER_OV_32( UInt op, IRExpr* res,
2094                           IRExpr* argL, IRExpr* argR )
2095{
2096   IRTemp  t64;
2097   IRExpr* xer_ov;
2098   vassert(op < PPCG_FLAG_OP_NUMBER);
2099   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
2100   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
2101   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
2102
2103#  define INT32_MIN 0x80000000
2104
2105#  define XOR2(_aa,_bb) \
2106      binop(Iop_Xor32,(_aa),(_bb))
2107
2108#  define XOR3(_cc,_dd,_ee) \
2109      binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
2110
2111#  define AND3(_ff,_gg,_hh) \
2112      binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
2113
2114#define NOT(_jj) \
2115      unop(Iop_Not32, (_jj))
2116
2117   switch (op) {
2118   case /* 0  */ PPCG_FLAG_OP_ADD:
2119   case /* 1  */ PPCG_FLAG_OP_ADDE:
2120      /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
2121      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2122      xer_ov
2123         = AND3( XOR3(argL,argR,mkU32(-1)),
2124                 XOR2(argL,res),
2125                 mkU32(INT32_MIN) );
2126      /* xer_ov can only be 0 or 1<<31 */
2127      xer_ov
2128         = binop(Iop_Shr32, xer_ov, mkU8(31) );
2129      break;
2130
2131   case /* 2  */ PPCG_FLAG_OP_DIVW:
2132      /* (argL == INT32_MIN && argR == -1) || argR == 0 */
2133      xer_ov
2134         = mkOR1(
2135              mkAND1(
2136                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
2137                 binop(Iop_CmpEQ32, argR, mkU32(-1))
2138              ),
2139              binop(Iop_CmpEQ32, argR, mkU32(0) )
2140           );
2141      xer_ov
2142         = unop(Iop_1Uto32, xer_ov);
2143      break;
2144
2145   case /* 3  */ PPCG_FLAG_OP_DIVWU:
2146      /* argR == 0 */
2147      xer_ov
2148         = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
2149      break;
2150
2151   case /* 4  */ PPCG_FLAG_OP_MULLW:
2152      /* OV true if result can't be represented in 32 bits
2153         i.e sHi != sign extension of sLo */
2154      t64 = newTemp(Ity_I64);
2155      assign( t64, binop(Iop_MullS32, argL, argR) );
2156      xer_ov
2157         = binop( Iop_CmpNE32,
2158                  unop(Iop_64HIto32, mkexpr(t64)),
2159                  binop( Iop_Sar32,
2160                         unop(Iop_64to32, mkexpr(t64)),
2161                         mkU8(31))
2162                  );
2163      xer_ov
2164         = unop(Iop_1Uto32, xer_ov);
2165      break;
2166
2167   case /* 5  */ PPCG_FLAG_OP_NEG:
2168      /* argL == INT32_MIN */
2169      xer_ov
2170         = unop( Iop_1Uto32,
2171                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
2172      break;
2173
2174   case /* 6  */ PPCG_FLAG_OP_SUBF:
2175   case /* 7  */ PPCG_FLAG_OP_SUBFC:
2176   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2177      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
2178      xer_ov
2179         = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
2180                 XOR2(NOT(argL),res),
2181                 mkU32(INT32_MIN) );
2182      /* xer_ov can only be 0 or 1<<31 */
2183      xer_ov
2184         = binop(Iop_Shr32, xer_ov, mkU8(31) );
2185      break;
2186
2187   case PPCG_FLAG_OP_DIVWEU:
2188      xer_ov
2189               = binop( Iop_Or32,
2190                        unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2191                        unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
2192      break;
2193
2194   case PPCG_FLAG_OP_DIVWE:
2195
2196      /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
2197       * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
2198       * an overflow is implied.
2199       */
2200      xer_ov = binop( Iop_Or32,
2201                      unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2202                      unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
2203                              mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
2204                                      binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
2205      break;
2206
2207
2208
2209   default:
2210      vex_printf("set_XER_OV: op = %u\n", op);
2211      vpanic("set_XER_OV(ppc)");
2212   }
2213
2214   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2215   putXER_OV( unop(Iop_32to8, xer_ov) );
2216
2217   /* Update the summary overflow */
2218   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2219
2220#  undef INT32_MIN
2221#  undef AND3
2222#  undef XOR3
2223#  undef XOR2
2224#  undef NOT
2225}
2226
2227static void set_XER_OV_64( UInt op, IRExpr* res,
2228                           IRExpr* argL, IRExpr* argR )
2229{
2230   IRExpr* xer_ov;
2231   vassert(op < PPCG_FLAG_OP_NUMBER);
2232   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
2233   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
2234   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
2235
2236#  define INT64_MIN 0x8000000000000000ULL
2237
2238#  define XOR2(_aa,_bb) \
2239      binop(Iop_Xor64,(_aa),(_bb))
2240
2241#  define XOR3(_cc,_dd,_ee) \
2242      binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
2243
2244#  define AND3(_ff,_gg,_hh) \
2245      binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
2246
2247#define NOT(_jj) \
2248      unop(Iop_Not64, (_jj))
2249
2250   switch (op) {
2251   case /* 0  */ PPCG_FLAG_OP_ADD:
2252   case /* 1  */ PPCG_FLAG_OP_ADDE:
2253      /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
2254      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2255      xer_ov
2256         = AND3( XOR3(argL,argR,mkU64(-1)),
2257                 XOR2(argL,res),
2258                 mkU64(INT64_MIN) );
2259      /* xer_ov can only be 0 or 1<<63 */
2260      xer_ov
2261         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2262      break;
2263
2264   case /* 2  */ PPCG_FLAG_OP_DIVW:
2265      /* (argL == INT64_MIN && argR == -1) || argR == 0 */
2266      xer_ov
2267         = mkOR1(
2268              mkAND1(
2269                 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
2270                 binop(Iop_CmpEQ64, argR, mkU64(-1))
2271              ),
2272              binop(Iop_CmpEQ64, argR, mkU64(0) )
2273           );
2274      break;
2275
2276   case /* 3  */ PPCG_FLAG_OP_DIVWU:
2277      /* argR == 0 */
2278      xer_ov
2279         = binop(Iop_CmpEQ64, argR, mkU64(0));
2280      break;
2281
2282   case /* 4  */ PPCG_FLAG_OP_MULLW: {
2283      /* OV true if result can't be represented in 64 bits
2284         i.e sHi != sign extension of sLo */
2285      xer_ov
2286         = binop( Iop_CmpNE32,
2287                  unop(Iop_64HIto32, res),
2288                  binop( Iop_Sar32,
2289                         unop(Iop_64to32, res),
2290                         mkU8(31))
2291                  );
2292      break;
2293   }
2294
2295   case /* 5  */ PPCG_FLAG_OP_NEG:
2296      /* argL == INT64_MIN */
2297      xer_ov
2298         = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
2299      break;
2300
2301   case /* 6  */ PPCG_FLAG_OP_SUBF:
2302   case /* 7  */ PPCG_FLAG_OP_SUBFC:
2303   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2304      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2305      xer_ov
2306         = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
2307                 XOR2(NOT(argL),res),
2308                 mkU64(INT64_MIN) );
2309      /* xer_ov can only be 0 or 1<<63 */
2310      xer_ov
2311         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2312      break;
2313
2314   case PPCG_FLAG_OP_DIVDE:
2315
2316      /* If argR == 0, we must set the OV bit.  But there's another condition
2317       * where we can get overflow set for divde . . . when the
2318       * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
2319       * both dividend and divisor are non-zero, it implies an overflow.
2320       */
2321      xer_ov
2322                  = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2323                           mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
2324                                   mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
2325                                           binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
2326      break;
2327
2328   case PPCG_FLAG_OP_DIVDEU:
2329     /* If argR == 0 or if argL >= argR, set OV. */
2330     xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2331                         binop( Iop_CmpLE64U, argR, argL ) );
2332     break;
2333
2334   case /* 18 */ PPCG_FLAG_OP_MULLD: {
2335      IRTemp  t128;
2336      /* OV true if result can't be represented in 64 bits
2337         i.e sHi != sign extension of sLo */
2338      t128 = newTemp(Ity_I128);
2339      assign( t128, binop(Iop_MullS64, argL, argR) );
2340      xer_ov
2341         = binop( Iop_CmpNE64,
2342                  unop(Iop_128HIto64, mkexpr(t128)),
2343                  binop( Iop_Sar64,
2344                         unop(Iop_128to64, mkexpr(t128)),
2345                         mkU8(63))
2346                  );
2347      break;
2348   }
2349
2350   default:
2351      vex_printf("set_XER_OV: op = %u\n", op);
2352      vpanic("set_XER_OV(ppc64)");
2353   }
2354
2355   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2356   putXER_OV( unop(Iop_1Uto8, xer_ov) );
2357
2358   /* Update the summary overflow */
2359   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2360
2361#  undef INT64_MIN
2362#  undef AND3
2363#  undef XOR3
2364#  undef XOR2
2365#  undef NOT
2366}
2367
2368static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
2369                         IRExpr* argL, IRExpr* argR )
2370{
2371   if (ty == Ity_I32)
2372      set_XER_OV_32( op, res, argL, argR );
2373   else
2374      set_XER_OV_64( op, res, argL, argR );
2375}
2376
2377
2378
2379/* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2380   value being OLDCA.  Set %XER.CA accordingly. */
2381
2382static void set_XER_CA_32 ( UInt op, IRExpr* res,
2383                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2384{
2385   IRExpr* xer_ca;
2386   vassert(op < PPCG_FLAG_OP_NUMBER);
2387   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
2388   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
2389   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
2390   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
2391
2392   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2393      seems reasonable given that it's always generated by
2394      getXER_CA32(), which masks it accordingly.  In any case it being
2395      0 or 1 is an invariant of the ppc guest state representation;
2396      if it has any other value, that invariant has been violated. */
2397
2398   switch (op) {
2399   case /* 0 */ PPCG_FLAG_OP_ADD:
2400      /* res <u argL */
2401      xer_ca
2402         = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
2403      break;
2404
2405   case /* 1 */ PPCG_FLAG_OP_ADDE:
2406      /* res <u argL || (old_ca==1 && res==argL) */
2407      xer_ca
2408         = mkOR1(
2409              binop(Iop_CmpLT32U, res, argL),
2410              mkAND1(
2411                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2412                 binop(Iop_CmpEQ32, res, argL)
2413              )
2414           );
2415      xer_ca
2416         = unop(Iop_1Uto32, xer_ca);
2417      break;
2418
2419   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2420      /* res <u argR || (old_ca==1 && res==argR) */
2421      xer_ca
2422         = mkOR1(
2423              binop(Iop_CmpLT32U, res, argR),
2424              mkAND1(
2425                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2426                 binop(Iop_CmpEQ32, res, argR)
2427              )
2428           );
2429      xer_ca
2430         = unop(Iop_1Uto32, xer_ca);
2431      break;
2432
2433   case /* 7 */ PPCG_FLAG_OP_SUBFC:
2434   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2435      /* res <=u argR */
2436      xer_ca
2437         = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
2438      break;
2439
2440   case /* 10 */ PPCG_FLAG_OP_SRAW:
2441      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2442         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2443         bit of argL. */
2444      /* This term valid for shift amount < 32 only */
2445      xer_ca
2446         = binop(
2447              Iop_And32,
2448              binop(Iop_Sar32, argL, mkU8(31)),
2449              binop( Iop_And32,
2450                     argL,
2451                     binop( Iop_Sub32,
2452                            binop(Iop_Shl32, mkU32(1),
2453                                             unop(Iop_32to8,argR)),
2454                            mkU32(1) )
2455                     )
2456              );
2457      xer_ca
2458         = IRExpr_ITE(
2459              /* shift amt > 31 ? */
2460              binop(Iop_CmpLT32U, mkU32(31), argR),
2461              /* yes -- get sign bit of argL */
2462              binop(Iop_Shr32, argL, mkU8(31)),
2463              /* no -- be like srawi */
2464              unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)))
2465           );
2466      break;
2467
2468   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2469      /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2470         0.  Since the shift amount is known to be in the range
2471         0 .. 31 inclusive the following seems viable:
2472         xer.ca == 1 iff the following is nonzero:
2473         (argL >>s 31)           -- either all 0s or all 1s
2474         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2475      xer_ca
2476         = binop(
2477              Iop_And32,
2478              binop(Iop_Sar32, argL, mkU8(31)),
2479              binop( Iop_And32,
2480                     argL,
2481                     binop( Iop_Sub32,
2482                            binop(Iop_Shl32, mkU32(1),
2483                                             unop(Iop_32to8,argR)),
2484                            mkU32(1) )
2485                     )
2486              );
2487      xer_ca
2488         = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2489      break;
2490
2491   default:
2492      vex_printf("set_XER_CA: op = %u\n", op);
2493      vpanic("set_XER_CA(ppc)");
2494   }
2495
2496   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2497   putXER_CA( unop(Iop_32to8, xer_ca) );
2498}
2499
2500static void set_XER_CA_64 ( UInt op, IRExpr* res,
2501                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2502{
2503   IRExpr* xer_ca;
2504   vassert(op < PPCG_FLAG_OP_NUMBER);
2505   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
2506   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
2507   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
2508   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
2509
2510   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2511      seems reasonable given that it's always generated by
2512      getXER_CA32(), which masks it accordingly.  In any case it being
2513      0 or 1 is an invariant of the ppc guest state representation;
2514      if it has any other value, that invariant has been violated. */
2515
2516   switch (op) {
2517   case /* 0 */ PPCG_FLAG_OP_ADD:
2518      /* res <u argL */
2519      xer_ca
2520         = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2521      break;
2522
2523   case /* 1 */ PPCG_FLAG_OP_ADDE:
2524      /* res <u argL || (old_ca==1 && res==argL) */
2525      xer_ca
2526         = mkOR1(
2527              binop(Iop_CmpLT64U, res, argL),
2528              mkAND1(
2529                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2530                 binop(Iop_CmpEQ64, res, argL)
2531                 )
2532              );
2533      xer_ca
2534         = unop(Iop_1Uto32, xer_ca);
2535      break;
2536
2537   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2538      /* res <u argR || (old_ca==1 && res==argR) */
2539      xer_ca
2540         = mkOR1(
2541              binop(Iop_CmpLT64U, res, argR),
2542              mkAND1(
2543                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2544                 binop(Iop_CmpEQ64, res, argR)
2545              )
2546           );
2547      xer_ca
2548         = unop(Iop_1Uto32, xer_ca);
2549      break;
2550
2551   case /* 7 */ PPCG_FLAG_OP_SUBFC:
2552   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2553      /* res <=u argR */
2554      xer_ca
2555         = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2556      break;
2557
2558
2559   case /* 10 */ PPCG_FLAG_OP_SRAW:
2560      /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2561         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2562         bit of argL. */
2563         /* This term valid for shift amount < 31 only */
2564
2565      xer_ca
2566         = binop(
2567              Iop_And64,
2568              binop(Iop_Sar64, argL, mkU8(31)),
2569              binop( Iop_And64,
2570                     argL,
2571                     binop( Iop_Sub64,
2572                            binop(Iop_Shl64, mkU64(1),
2573                                             unop(Iop_64to8,argR)),
2574                            mkU64(1) )
2575              )
2576           );
2577      xer_ca
2578         = IRExpr_ITE(
2579              /* shift amt > 31 ? */
2580              binop(Iop_CmpLT64U, mkU64(31), argR),
2581              /* yes -- get sign bit of argL */
2582              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2583              /* no -- be like srawi */
2584              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2585          );
2586      break;
2587
2588   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2589      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2590         Since the shift amount is known to be in the range 0 .. 31
2591         inclusive the following seems viable:
2592         xer.ca == 1 iff the following is nonzero:
2593         (argL >>s 31)           -- either all 0s or all 1s
2594         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2595
2596      xer_ca
2597         = binop(
2598              Iop_And64,
2599              binop(Iop_Sar64, argL, mkU8(31)),
2600              binop( Iop_And64,
2601                     argL,
2602                     binop( Iop_Sub64,
2603                            binop(Iop_Shl64, mkU64(1),
2604                                             unop(Iop_64to8,argR)),
2605                            mkU64(1) )
2606              )
2607           );
2608      xer_ca
2609         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2610      break;
2611
2612
2613   case /* 12 */ PPCG_FLAG_OP_SRAD:
2614      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2615         If it is <= 63, behave like SRADI; else XER.CA is the sign
2616         bit of argL. */
2617         /* This term valid for shift amount < 63 only */
2618
2619      xer_ca
2620         = binop(
2621              Iop_And64,
2622              binop(Iop_Sar64, argL, mkU8(63)),
2623              binop( Iop_And64,
2624                     argL,
2625                     binop( Iop_Sub64,
2626                            binop(Iop_Shl64, mkU64(1),
2627                                             unop(Iop_64to8,argR)),
2628                            mkU64(1) )
2629              )
2630           );
2631      xer_ca
2632         = IRExpr_ITE(
2633              /* shift amt > 63 ? */
2634              binop(Iop_CmpLT64U, mkU64(63), argR),
2635              /* yes -- get sign bit of argL */
2636              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2637              /* no -- be like sradi */
2638              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2639           );
2640      break;
2641
2642
2643   case /* 13 */ PPCG_FLAG_OP_SRADI:
2644      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2645         Since the shift amount is known to be in the range 0 .. 63
2646         inclusive, the following seems viable:
2647         xer.ca == 1 iff the following is nonzero:
2648         (argL >>s 63)           -- either all 0s or all 1s
2649         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2650
2651      xer_ca
2652         = binop(
2653              Iop_And64,
2654              binop(Iop_Sar64, argL, mkU8(63)),
2655              binop( Iop_And64,
2656                     argL,
2657                     binop( Iop_Sub64,
2658                            binop(Iop_Shl64, mkU64(1),
2659                                             unop(Iop_64to8,argR)),
2660                            mkU64(1) )
2661              )
2662           );
2663      xer_ca
2664         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2665      break;
2666
2667   default:
2668      vex_printf("set_XER_CA: op = %u\n", op);
2669      vpanic("set_XER_CA(ppc64)");
2670   }
2671
2672   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2673   putXER_CA( unop(Iop_32to8, xer_ca) );
2674}
2675
2676static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
2677                         IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2678{
2679   if (ty == Ity_I32)
2680      set_XER_CA_32( op, res, argL, argR, oldca );
2681   else
2682      set_XER_CA_64( op, res, argL, argR, oldca );
2683}
2684
2685
2686
2687/*------------------------------------------------------------*/
2688/*--- Read/write to guest-state                           --- */
2689/*------------------------------------------------------------*/
2690
2691static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
2692{
2693   IRType ty = mode64 ? Ity_I64 : Ity_I32;
2694   switch (reg) {
2695   case PPC_GST_SPRG3_RO:
2696      return IRExpr_Get( OFFB_SPRG3_RO, ty );
2697
2698   case PPC_GST_CIA:
2699      return IRExpr_Get( OFFB_CIA, ty );
2700
2701   case PPC_GST_LR:
2702      return IRExpr_Get( OFFB_LR, ty );
2703
2704   case PPC_GST_CTR:
2705      return IRExpr_Get( OFFB_CTR, ty );
2706
2707   case PPC_GST_VRSAVE:
2708      return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
2709
2710   case PPC_GST_VSCR:
2711      return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
2712                              mkU32(MASK_VSCR_VALID));
2713
2714   case PPC_GST_CR: {
2715      /* Synthesise the entire CR into a single word.  Expensive. */
2716#     define FIELD(_n)                                               \
2717         binop(Iop_Shl32,                                            \
2718               unop(Iop_8Uto32,                                      \
2719                    binop(Iop_Or8,                                   \
2720                          binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
2721                          binop(Iop_And8, getCR0(_n), mkU8(1))       \
2722                    )                                                \
2723               ),                                                    \
2724               mkU8(4 * (7-(_n)))                                    \
2725         )
2726      return binop(Iop_Or32,
2727                   binop(Iop_Or32,
2728                         binop(Iop_Or32, FIELD(0), FIELD(1)),
2729                         binop(Iop_Or32, FIELD(2), FIELD(3))
2730                         ),
2731                   binop(Iop_Or32,
2732                         binop(Iop_Or32, FIELD(4), FIELD(5)),
2733                         binop(Iop_Or32, FIELD(6), FIELD(7))
2734                         )
2735                   );
2736#     undef FIELD
2737   }
2738
2739   case PPC_GST_XER:
2740      return binop(Iop_Or32,
2741                   binop(Iop_Or32,
2742                         binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
2743                         binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
2744                   binop(Iop_Or32,
2745                         binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
2746                         getXER_BC32()));
2747
2748   case PPC_GST_TFHAR:
2749      return IRExpr_Get( OFFB_TFHAR, ty );
2750
2751   case PPC_GST_TEXASR:
2752      return IRExpr_Get( OFFB_TEXASR, ty );
2753
2754   case PPC_GST_TEXASRU:
2755      return IRExpr_Get( OFFB_TEXASRU, ty );
2756
2757   case PPC_GST_TFIAR:
2758      return IRExpr_Get( OFFB_TFIAR, ty );
2759
2760   case PPC_GST_PPR:
2761      return IRExpr_Get( OFFB_PPR, ty );
2762
2763   case PPC_GST_PPR32:
2764      return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) );
2765
2766   case PPC_GST_PSPB:
2767      return IRExpr_Get( OFFB_PSPB, ty );
2768
2769   default:
2770      vex_printf("getGST(ppc): reg = %u", reg);
2771      vpanic("getGST(ppc)");
2772   }
2773}
2774
2775/* Get a masked word from the given reg */
2776static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
2777{
2778   IRTemp val = newTemp(Ity_I32);
2779   vassert( reg < PPC_GST_MAX );
2780
2781   switch (reg) {
2782
2783   case PPC_GST_FPSCR: {
2784      /* Vex-generated code expects the FPSCR to be set as follows:
2785         all exceptions masked, round-to-nearest.
2786         This corresponds to a FPSCR value of 0x0. */
2787
2788      /* In the lower 32 bits of FPSCR, we're only keeping track of
2789       * the binary floating point rounding mode, so if the mask isn't
2790       * asking for this, just return 0x0.
2791       */
2792      if (mask & MASK_FPSCR_RN) {
2793         assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) );
2794      } else {
2795         assign( val, mkU32(0x0) );
2796      }
2797      break;
2798   }
2799
2800   default:
2801      vex_printf("getGST_masked(ppc): reg = %u", reg);
2802      vpanic("getGST_masked(ppc)");
2803   }
2804
2805   if (mask != 0xFFFFFFFF) {
2806      return binop(Iop_And32, mkexpr(val), mkU32(mask));
2807   } else {
2808      return mkexpr(val);
2809   }
2810}
2811
2812/* Get a masked word from the given reg */
2813static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
2814   IRExpr * val;
2815   vassert( reg < PPC_GST_MAX );
2816
2817   switch (reg) {
2818
2819   case PPC_GST_FPSCR: {
2820      /* In the upper 32 bits of FPSCR, we're only keeping track
2821       * of the decimal floating point rounding mode, so if the mask
2822       * isn't asking for this, just return 0x0.
2823       */
2824      if (mask & MASK_FPSCR_DRN) {
2825         val = binop( Iop_And32,
2826                      unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
2827                      unop( Iop_64HIto32, mkU64( mask ) ) );
2828      } else {
2829         val = mkU32( 0x0ULL );
2830      }
2831      break;
2832   }
2833
2834   default:
2835      vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
2836      vpanic( "getGST_masked_upper(ppc)" );
2837   }
2838   return val;
2839}
2840
2841
2842/* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
2843   and return it at the bottom of an I32; the top 27 bits are
2844   guaranteed to be zero. */
2845static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
2846{
2847   UInt shft, mask;
2848
2849   vassert( fld < 8 );
2850   vassert( reg < PPC_GST_MAX );
2851
2852   shft = 4*(7-fld);
2853   mask = 0xF<<shft;
2854
2855   switch (reg) {
2856   case PPC_GST_XER:
2857      vassert(fld ==7);
2858      return binop(Iop_Or32,
2859                   binop(Iop_Or32,
2860                         binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
2861                         binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
2862                   binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
2863      break;
2864
2865   default:
2866      if (shft == 0)
2867         return getGST_masked( reg, mask );
2868      else
2869         return binop(Iop_Shr32,
2870                      getGST_masked( reg, mask ),
2871                      mkU8(toUChar( shft )));
2872   }
2873}
2874
2875static void putGST ( PPC_GST reg, IRExpr* src )
2876{
2877   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
2878   IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
2879   vassert( reg < PPC_GST_MAX );
2880   switch (reg) {
2881   case PPC_GST_IP_AT_SYSCALL:
2882      vassert( ty_src == ty );
2883      stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
2884      break;
2885   case PPC_GST_CIA:
2886      vassert( ty_src == ty );
2887      stmt( IRStmt_Put( OFFB_CIA, src ) );
2888      break;
2889   case PPC_GST_LR:
2890      vassert( ty_src == ty );
2891      stmt( IRStmt_Put( OFFB_LR, src ) );
2892      break;
2893   case PPC_GST_CTR:
2894      vassert( ty_src == ty );
2895      stmt( IRStmt_Put( OFFB_CTR, src ) );
2896      break;
2897   case PPC_GST_VRSAVE:
2898      vassert( ty_src == Ity_I32 );
2899      stmt( IRStmt_Put( OFFB_VRSAVE,src));
2900      break;
2901   case PPC_GST_VSCR:
2902      vassert( ty_src == Ity_I32 );
2903      stmt( IRStmt_Put( OFFB_VSCR,
2904                        binop(Iop_And32, src,
2905                              mkU32(MASK_VSCR_VALID)) ) );
2906      break;
2907   case PPC_GST_XER:
2908      vassert( ty_src == Ity_I32 );
2909      putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
2910      putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
2911      putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
2912      putXER_BC( unop(Iop_32to8, src) );
2913      break;
2914
2915   case PPC_GST_EMWARN:
2916      vassert( ty_src == Ity_I32 );
2917      stmt( IRStmt_Put( OFFB_EMNOTE,src) );
2918      break;
2919
2920   case PPC_GST_CMSTART:
2921      vassert( ty_src == ty );
2922      stmt( IRStmt_Put( OFFB_CMSTART, src) );
2923      break;
2924
2925   case PPC_GST_CMLEN:
2926      vassert( ty_src == ty );
2927      stmt( IRStmt_Put( OFFB_CMLEN, src) );
2928      break;
2929
2930   case PPC_GST_TEXASR:
2931      vassert( ty_src == Ity_I64 );
2932      stmt( IRStmt_Put( OFFB_TEXASR, src ) );
2933      break;
2934
2935   case PPC_GST_TEXASRU:
2936      vassert( ty_src == Ity_I32 );
2937      stmt( IRStmt_Put( OFFB_TEXASRU, src ) );
2938      break;
2939
2940   case PPC_GST_TFIAR:
2941      vassert( ty_src == Ity_I64 );
2942      stmt( IRStmt_Put( OFFB_TFIAR, src ) );
2943      break;
2944   case PPC_GST_TFHAR:
2945      vassert( ty_src == Ity_I64 );
2946      stmt( IRStmt_Put( OFFB_TFHAR, src ) );
2947      break;
2948
2949   case PPC_GST_PPR32:
2950   case PPC_GST_PPR:
2951      {
2952         /* The Program Priority Register (PPR) stores the priority in
2953          * bits [52:50].  The user setable priorities are:
2954          *
2955          *    001  very low
2956          *    010  low
2957          *    011  medium low
2958          *    100  medium
2959          *    101  medium high
2960          *
2961          * If the argument is not between 0b001 and 0b100 the priority is set
2962          * to 0b100.  The priority can only be set to 0b101 if the the Problem
2963          * State Boost Register is non-zero.  The value of the PPR is not
2964          * changed if the input is not valid.
2965          */
2966
2967         IRTemp not_valid = newTemp(Ity_I64);
2968         IRTemp has_perm = newTemp(Ity_I64);
2969         IRTemp new_src  = newTemp(Ity_I64);
2970         IRTemp PSPB_val = newTemp(Ity_I64);
2971         IRTemp value    = newTemp(Ity_I64);
2972
2973         vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 ));
2974         assign( PSPB_val, binop( Iop_32HLto64,
2975                                  mkU32( 0 ),
2976                                  IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) );
2977         if( reg == PPC_GST_PPR32 ) {
2978            vassert( ty_src == Ity_I32 );
2979            assign( value, binop( Iop_32HLto64,
2980                                  mkU32(0),
2981                                  binop( Iop_And32,
2982                                         binop( Iop_Shr32, src,  mkU8( 18 ) ),
2983                                         mkU32( 0x7 ) ) ) );
2984         } else {
2985            vassert( ty_src == Ity_I64 );
2986            assign( value, binop( Iop_And64,
2987                                  binop( Iop_Shr64, src,  mkU8( 50 ) ),
2988                                  mkU64( 0x7 ) ) );
2989         }
2990         assign( has_perm,
2991                 binop( Iop_And64,
2992                        unop( Iop_1Sto64,
2993                              binop( Iop_CmpEQ64,
2994                                     mkexpr( PSPB_val ),
2995                                     mkU64( 0 ) ) ),
2996                        unop( Iop_1Sto64,
2997                              binop( Iop_CmpEQ64,
2998                                     mkU64( 0x5 ),
2999                                     mkexpr( value ) ) ) ) );
3000         assign( not_valid,
3001                 binop( Iop_Or64,
3002                        unop( Iop_1Sto64,
3003                              binop( Iop_CmpEQ64,
3004                                     mkexpr( value ),
3005                                     mkU64( 0 ) ) ),
3006                        unop( Iop_1Sto64,
3007                              binop( Iop_CmpLT64U,
3008                                     mkU64( 0x5 ),
3009                                     mkexpr( value ) ) ) ) );
3010         assign( new_src,
3011                 binop( Iop_Or64,
3012                        binop( Iop_And64,
3013                               unop( Iop_Not64,
3014                                     mkexpr( not_valid ) ),
3015                               src ),
3016                        binop( Iop_And64,
3017                               mkexpr( not_valid ),
3018                               binop( Iop_Or64,
3019                                      binop( Iop_And64,
3020                                             mkexpr( has_perm),
3021                                             binop( Iop_Shl64,
3022                                                    mkexpr( value ),
3023                                                    mkU8( 50 ) ) ),
3024                                      binop( Iop_And64,
3025                                             IRExpr_Get( OFFB_PPR, ty ),
3026                                             unop( Iop_Not64,
3027                                                   mkexpr( has_perm )
3028                                                   ) ) ) ) ) );
3029
3030                 /* make sure we only set the valid bit field [52:50] */
3031                 stmt( IRStmt_Put( OFFB_PPR,
3032                                   binop( Iop_And64,
3033                                          mkexpr( new_src ),
3034                                          mkU64( 0x1C000000000000) ) ) );
3035      break;
3036      }
3037   default:
3038      vex_printf("putGST(ppc): reg = %u", reg);
3039      vpanic("putGST(ppc)");
3040   }
3041}
3042
3043/* Write masked src to the given reg */
3044static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
3045{
3046   IRType ty = mode64 ? Ity_I64 : Ity_I32;
3047   vassert( reg < PPC_GST_MAX );
3048   vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
3049
3050   switch (reg) {
3051   case PPC_GST_FPSCR: {
3052      /* Allow writes to either binary or decimal floating point
3053         Rounding Mode.
3054      */
3055      /* If any part of |mask| covers FPSCR.RN, update the bits of
3056         FPSCR.RN by copying in |src| for locations where the
3057         corresponding bit in |mask| is 1, and leaving it unchanged
3058         for corresponding |mask| zero bits. */
3059      if (mask & MASK_FPSCR_RN) {
3060         stmt(
3061            IRStmt_Put(
3062               OFFB_FPROUND,
3063               unop(
3064                  Iop_32to8,
3065                  binop(
3066                     Iop_Or32,
3067                     binop(
3068                        Iop_And32,
3069                        unop(Iop_64to32, src),
3070                        mkU32(MASK_FPSCR_RN & mask)
3071                     ),
3072                     binop(
3073                        Iop_And32,
3074                        unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)),
3075                        mkU32(MASK_FPSCR_RN & ~mask)
3076                     )
3077                  )
3078               )
3079            )
3080         );
3081      }
3082      /* Similarly, update FPSCR.DRN if any bits of |mask|
3083         corresponding to FPSCR.DRN are set. */
3084      if (mask & MASK_FPSCR_DRN) {
3085         stmt(
3086            IRStmt_Put(
3087               OFFB_DFPROUND,
3088               unop(
3089                  Iop_32to8,
3090                  binop(
3091                     Iop_Or32,
3092                     binop(
3093                        Iop_And32,
3094                        unop(Iop_64HIto32, src),
3095                        mkU32((MASK_FPSCR_DRN & mask) >> 32)
3096                     ),
3097                     binop(
3098                        Iop_And32,
3099                        unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)),
3100                        mkU32((MASK_FPSCR_DRN & ~mask) >> 32)
3101                     )
3102                  )
3103               )
3104            )
3105         );
3106      }
3107
3108      /* Give EmNote for attempted writes to:
3109         - Exception Controls
3110         - Non-IEEE Mode
3111      */
3112      if (mask & 0xFC) {  // Exception Control, Non-IEE mode
3113         VexEmNote ew = EmWarn_PPCexns;
3114
3115         /* If any of the src::exception_control bits are actually set,
3116            side-exit to the next insn, reporting the warning,
3117            so that Valgrind's dispatcher sees the warning. */
3118         putGST( PPC_GST_EMWARN, mkU32(ew) );
3119         stmt(
3120            IRStmt_Exit(
3121               binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
3122               Ijk_EmWarn,
3123               mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
3124      }
3125
3126      /* Ignore all other writes */
3127      break;
3128   }
3129
3130   default:
3131      vex_printf("putGST_masked(ppc): reg = %u", reg);
3132      vpanic("putGST_masked(ppc)");
3133   }
3134}
3135
3136/* Write the least significant nibble of src to the specified
3137   REG[FLD] (as per IBM/hardware notation). */
3138static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
3139{
3140   UInt shft;
3141   ULong mask;
3142
3143   vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
3144   vassert( fld < 16 );
3145   vassert( reg < PPC_GST_MAX );
3146
3147   if (fld < 8)
3148      shft = 4*(7-fld);
3149   else
3150      shft = 4*(15-fld);
3151   mask = 0xF;
3152   mask = mask << shft;
3153
3154   switch (reg) {
3155   case PPC_GST_CR:
3156      putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
3157      putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
3158      break;
3159
3160   default:
3161      {
3162         IRExpr * src64 = unop( Iop_32Uto64, src );
3163
3164         if (shft == 0) {
3165            putGST_masked( reg, src64, mask );
3166         } else {
3167            putGST_masked( reg,
3168                           binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
3169                           mask );
3170         }
3171      }
3172   }
3173}
3174
3175/*------------------------------------------------------------*/
3176/* Helpers for VSX instructions that do floating point
3177 * operations and need to determine if a src contains a
3178 * special FP value.
3179 *
3180 *------------------------------------------------------------*/
3181
3182#define NONZERO_FRAC_MASK 0x000fffffffffffffULL
3183#define FP_FRAC_PART(x) binop( Iop_And64, \
3184                               mkexpr( x ), \
3185                               mkU64( NONZERO_FRAC_MASK ) )
3186
3187// Returns exponent part of a single precision floating point as I32
3188static IRExpr * fp_exp_part_sp(IRTemp src)
3189{
3190   return binop( Iop_And32,
3191                 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
3192                 mkU32( 0xff ) );
3193}
3194
3195// Returns exponent part of floating point as I32
3196static IRExpr * fp_exp_part(IRTemp src, Bool sp)
3197{
3198   IRExpr * exp;
3199   if (sp)
3200      return fp_exp_part_sp(src);
3201
3202   if (!mode64)
3203      exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
3204                                                      mkexpr( src ) ),
3205                                     mkU8( 20 ) ), mkU32( 0x7ff ) );
3206   else
3207      exp = unop( Iop_64to32,
3208                  binop( Iop_And64,
3209                         binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
3210                         mkU64( 0x7ff ) ) );
3211   return exp;
3212}
3213
3214static IRExpr * is_Inf_sp(IRTemp src)
3215{
3216   IRTemp frac_part = newTemp(Ity_I32);
3217   IRExpr * Inf_exp;
3218
3219   assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
3220   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
3221   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
3222}
3223
3224
3225// Infinity: exp = 7ff and fraction is zero; s = 0/1
3226static IRExpr * is_Inf(IRTemp src, Bool sp)
3227{
3228   IRExpr * Inf_exp, * hi32, * low32;
3229   IRTemp frac_part;
3230
3231   if (sp)
3232      return is_Inf_sp(src);
3233
3234   frac_part = newTemp(Ity_I64);
3235   assign( frac_part, FP_FRAC_PART(src) );
3236   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
3237   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
3238   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
3239   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
3240                                  mkU32( 0 ) ) );
3241}
3242
3243static IRExpr * is_Zero_sp(IRTemp src)
3244{
3245   IRTemp sign_less_part = newTemp(Ity_I32);
3246   assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
3247   return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
3248}
3249
3250// Zero: exp is zero and fraction is zero; s = 0/1
3251static IRExpr * is_Zero(IRTemp src, Bool sp)
3252{
3253   IRExpr * hi32, * low32;
3254   IRTemp sign_less_part;
3255   if (sp)
3256      return is_Zero_sp(src);
3257
3258   sign_less_part = newTemp(Ity_I64);
3259
3260   assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
3261   hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
3262   low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
3263   return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
3264                              mkU32( 0 ) );
3265}
3266
3267/*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
3268 *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
3269 *  This function returns an IRExpr value of '1' for any type of NaN.
3270 */
3271static IRExpr * is_NaN(IRTemp src)
3272{
3273   IRExpr * NaN_exp, * hi32, * low32;
3274   IRTemp frac_part = newTemp(Ity_I64);
3275
3276   assign( frac_part, FP_FRAC_PART(src) );
3277   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
3278   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
3279   NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
3280                    mkU32( 0x7ff ) );
3281
3282   return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
3283                                               mkU32( 0 ) ) );
3284}
3285
3286/* This function returns an IRExpr value of '1' for any type of NaN.
3287 * The passed 'src' argument is assumed to be Ity_I32.
3288 */
3289static IRExpr * is_NaN_32(IRTemp src)
3290{
3291#define NONZERO_FRAC_MASK32 0x007fffffULL
3292#define FP_FRAC_PART32(x) binop( Iop_And32, \
3293                                 mkexpr( x ), \
3294                                 mkU32( NONZERO_FRAC_MASK32 ) )
3295
3296   IRExpr * frac_part = FP_FRAC_PART32(src);
3297   IRExpr * exp_part = binop( Iop_And32,
3298                              binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
3299                              mkU32( 0x0ff ) );
3300   IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
3301
3302   return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
3303}
3304
3305/* This function takes an Ity_I32 input argument interpreted
3306 * as a single-precision floating point value. If src is a
3307 * SNaN, it is changed to a QNaN and returned; otherwise,
3308 * the original value is returned.
3309 */
3310static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src)
3311{
3312#define SNAN_MASK32 0x00400000
3313   IRTemp tmp = newTemp(Ity_I32);
3314   IRTemp mask = newTemp(Ity_I32);
3315   IRTemp is_SNAN = newTemp(Ity_I1);
3316
3317   vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 );
3318   assign(tmp, src);
3319
3320   /* check if input is SNaN, if it is convert to QNaN */
3321   assign( is_SNAN,
3322           mkAND1( is_NaN_32( tmp ),
3323                   binop( Iop_CmpEQ32,
3324                          binop( Iop_And32, mkexpr( tmp ),
3325                                 mkU32( SNAN_MASK32 ) ),
3326                          mkU32( 0 ) ) ) );
3327   /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
3328   assign ( mask, binop( Iop_And32,
3329                         unop( Iop_1Sto32, mkexpr( is_SNAN ) ),
3330                         mkU32( SNAN_MASK32 ) ) );
3331   return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) );
3332}
3333
3334
3335/* This helper function performs the negation part of operations of the form:
3336 *    "Negate Multiply-<op>"
3337 *  where "<op>" is either "Add" or "Sub".
3338 *
3339 * This function takes one argument -- the floating point intermediate result (converted to
3340 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
3341 * the operation described above.
3342 */
3343static IRTemp getNegatedResult(IRTemp intermediateResult)
3344{
3345   ULong signbit_mask = 0x8000000000000000ULL;
3346   IRTemp signbit_32 = newTemp(Ity_I32);
3347   IRTemp resultantSignbit = newTemp(Ity_I1);
3348   IRTemp negatedResult = newTemp(Ity_I64);
3349   assign( signbit_32, binop( Iop_Shr32,
3350                          unop( Iop_64HIto32,
3351                                 binop( Iop_And64, mkexpr( intermediateResult ),
3352                                        mkU64( signbit_mask ) ) ),
3353                                 mkU8( 31 ) ) );
3354   /* We negate the signbit if and only if the intermediate result from the
3355    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
3356    */
3357   assign( resultantSignbit,
3358        unop( Iop_Not1,
3359              binop( Iop_CmpEQ32,
3360                     binop( Iop_Xor32,
3361                            mkexpr( signbit_32 ),
3362                            unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
3363                     mkU32( 1 ) ) ) );
3364
3365   assign( negatedResult,
3366        binop( Iop_Or64,
3367               binop( Iop_And64,
3368                      mkexpr( intermediateResult ),
3369                      mkU64( ~signbit_mask ) ),
3370               binop( Iop_32HLto64,
3371                      binop( Iop_Shl32,
3372                             unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
3373                             mkU8( 31 ) ),
3374                      mkU32( 0 ) ) ) );
3375
3376   return negatedResult;
3377}
3378
3379/* This helper function performs the negation part of operations of the form:
3380 *    "Negate Multiply-<op>"
3381 *  where "<op>" is either "Add" or "Sub".
3382 *
3383 * This function takes one argument -- the floating point intermediate result (converted to
3384 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
3385 * the operation described above.
3386 */
3387static IRTemp getNegatedResult_32(IRTemp intermediateResult)
3388{
3389   UInt signbit_mask = 0x80000000;
3390   IRTemp signbit_32 = newTemp(Ity_I32);
3391   IRTemp resultantSignbit = newTemp(Ity_I1);
3392   IRTemp negatedResult = newTemp(Ity_I32);
3393   assign( signbit_32, binop( Iop_Shr32,
3394                                 binop( Iop_And32, mkexpr( intermediateResult ),
3395                                        mkU32( signbit_mask ) ),
3396                                 mkU8( 31 ) ) );
3397   /* We negate the signbit if and only if the intermediate result from the
3398    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
3399    */
3400   assign( resultantSignbit,
3401        unop( Iop_Not1,
3402              binop( Iop_CmpEQ32,
3403                     binop( Iop_Xor32,
3404                            mkexpr( signbit_32 ),
3405                            unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
3406                     mkU32( 1 ) ) ) );
3407
3408   assign( negatedResult,
3409           binop( Iop_Or32,
3410                  binop( Iop_And32,
3411                         mkexpr( intermediateResult ),
3412                         mkU32( ~signbit_mask ) ),
3413                  binop( Iop_Shl32,
3414                         unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
3415                         mkU8( 31 ) ) ) );
3416
3417   return negatedResult;
3418}
3419
3420/*------------------------------------------------------------*/
3421/* Transactional memory helpers
3422 *
3423 *------------------------------------------------------------*/
3424
3425static ULong generate_TMreason( UInt failure_code,
3426                                             UInt persistant,
3427                                             UInt nest_overflow,
3428                                             UInt tm_exact )
3429{
3430   ULong tm_err_code =
3431     ( (ULong) 0) << (63-6)   /* Failure code */
3432     | ( (ULong) persistant) << (63-7)     /* Failure persistant */
3433     | ( (ULong) 0) << (63-8)   /* Disallowed */
3434     | ( (ULong) nest_overflow) << (63-9)   /* Nesting Overflow */
3435     | ( (ULong) 0) << (63-10)  /* Footprint Overflow */
3436     | ( (ULong) 0) << (63-11)  /* Self-Induced Conflict */
3437     | ( (ULong) 0) << (63-12)  /* Non-Transactional Conflict */
3438     | ( (ULong) 0) << (63-13)  /* Transactional Conflict */
3439     | ( (ULong) 0) << (63-14)  /* Translation Invalidation Conflict */
3440     | ( (ULong) 0) << (63-15)  /* Implementation-specific */
3441     | ( (ULong) 0) << (63-16)  /* Instruction Fetch Conflict */
3442     | ( (ULong) 0) << (63-30)  /* Reserved */
3443     | ( (ULong) 0) << (63-31)  /* Abort */
3444     | ( (ULong) 0) << (63-32)  /* Suspend */
3445     | ( (ULong) 0) << (63-33)  /* Reserved */
3446     | ( (ULong) 0) << (63-35)  /* Privilege */
3447     | ( (ULong) 0) << (63-36)  /* Failure Summary */
3448     | ( (ULong) tm_exact) << (63-37)  /* TFIAR Exact */
3449     | ( (ULong) 0) << (63-38)  /* ROT */
3450     | ( (ULong) 0) << (63-51)  /* Reserved */
3451     | ( (ULong) 0) << (63-63);  /* Transaction Level */
3452
3453     return tm_err_code;
3454}
3455
3456static void storeTMfailure( Addr64 err_address, ULong tm_reason,
3457                            Addr64 handler_address )
3458{
3459   putGST( PPC_GST_TFIAR,   mkU64( err_address ) );
3460   putGST( PPC_GST_TEXASR,  mkU64( tm_reason ) );
3461   putGST( PPC_GST_TEXASRU, mkU32( 0 ) );
3462   putGST( PPC_GST_TFHAR,   mkU64( handler_address ) );
3463}
3464
3465/*------------------------------------------------------------*/
3466/*--- Integer Instruction Translation                     --- */
3467/*------------------------------------------------------------*/
3468
3469/*
3470  Integer Arithmetic Instructions
3471*/
3472static Bool dis_int_arith ( UInt theInstr )
3473{
3474   /* D-Form, XO-Form */
3475   UChar opc1    = ifieldOPC(theInstr);
3476   UChar rD_addr = ifieldRegDS(theInstr);
3477   UChar rA_addr = ifieldRegA(theInstr);
3478   UInt  uimm16  = ifieldUIMM16(theInstr);
3479   UChar rB_addr = ifieldRegB(theInstr);
3480   UChar flag_OE = ifieldBIT10(theInstr);
3481   UInt  opc2    = ifieldOPClo9(theInstr);
3482   UChar flag_rC = ifieldBIT0(theInstr);
3483
3484   Long   simm16 = extend_s_16to64(uimm16);
3485   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3486   IRTemp rA     = newTemp(ty);
3487   IRTemp rB     = newTemp(ty);
3488   IRTemp rD     = newTemp(ty);
3489
3490   Bool do_rc = False;
3491
3492   assign( rA, getIReg(rA_addr) );
3493   assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
3494
3495   switch (opc1) {
3496   /* D-Form */
3497   case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
3498      DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3499      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3500                         mkSzExtendS16(ty, uimm16) ) );
3501      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3502                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3503                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3504      break;
3505
3506   case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
3507      DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3508      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3509                         mkSzExtendS16(ty, uimm16) ) );
3510      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3511                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3512                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3513      do_rc = True;  // Always record to CR
3514      flag_rC = 1;
3515      break;
3516
3517   case 0x0E: // addi   (Add Immediate, PPC32 p350)
3518      // li rD,val   == addi rD,0,val
3519      // la disp(rA) == addi rD,rA,disp
3520      if ( rA_addr == 0 ) {
3521         DIP("li r%u,%d\n", rD_addr, (Int)simm16);
3522         assign( rD, mkSzExtendS16(ty, uimm16) );
3523      } else {
3524         DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3525         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3526                            mkSzExtendS16(ty, uimm16) ) );
3527      }
3528      break;
3529
3530   case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
3531      // lis rD,val == addis rD,0,val
3532      if ( rA_addr == 0 ) {
3533         DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
3534         assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
3535      } else {
3536         DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (UInt)simm16);
3537         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3538                            mkSzExtendS32(ty, uimm16 << 16) ) );
3539      }
3540      break;
3541
3542   case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
3543      DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3544      if (mode64)
3545         assign( rD, unop(Iop_128to64,
3546                          binop(Iop_MullS64, mkexpr(rA),
3547                                mkSzExtendS16(ty, uimm16))) );
3548      else
3549         assign( rD, unop(Iop_64to32,
3550                          binop(Iop_MullS32, mkexpr(rA),
3551                                mkSzExtendS16(ty, uimm16))) );
3552      break;
3553
3554   case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
3555      DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3556      // rD = simm16 - rA
3557      assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3558                         mkSzExtendS16(ty, uimm16),
3559                         mkexpr(rA)) );
3560      set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
3561                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3562                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3563      break;
3564
3565   /* XO-Form */
3566   case 0x1F:
3567      do_rc = True;    // All below record to CR
3568
3569      switch (opc2) {
3570      case 0x10A: // add  (Add, PPC32 p347)
3571         DIP("add%s%s r%u,r%u,r%u\n",
3572             flag_OE ? "o" : "", flag_rC ? ".":"",
3573             rD_addr, rA_addr, rB_addr);
3574         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3575                            mkexpr(rA), mkexpr(rB) ) );
3576         if (flag_OE) {
3577            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
3578                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3579         }
3580         break;
3581
3582      case 0x00A: // addc      (Add Carrying, PPC32 p348)
3583         DIP("addc%s%s r%u,r%u,r%u\n",
3584             flag_OE ? "o" : "", flag_rC ? ".":"",
3585             rD_addr, rA_addr, rB_addr);
3586         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3587                            mkexpr(rA), mkexpr(rB)) );
3588         set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3589                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3590                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3591         if (flag_OE) {
3592            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
3593                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3594         }
3595         break;
3596
3597      case 0x08A: { // adde      (Add Extended, PPC32 p349)
3598         IRTemp old_xer_ca = newTemp(ty);
3599         DIP("adde%s%s r%u,r%u,r%u\n",
3600             flag_OE ? "o" : "", flag_rC ? ".":"",
3601             rD_addr, rA_addr, rB_addr);
3602         // rD = rA + rB + XER[CA]
3603         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3604         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3605                            binop( mkSzOp(ty, Iop_Add8),
3606                                   mkexpr(rB), mkexpr(old_xer_ca))) );
3607         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3608                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3609                     mkexpr(old_xer_ca) );
3610         if (flag_OE) {
3611            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3612                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3613         }
3614         break;
3615      }
3616
3617      case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
3618         IRTemp old_xer_ca = newTemp(ty);
3619         IRExpr *min_one;
3620         if (rB_addr != 0) {
3621            vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
3622            return False;
3623         }
3624         DIP("addme%s%s r%u,r%u,r%u\n",
3625             flag_OE ? "o" : "", flag_rC ? ".":"",
3626             rD_addr, rA_addr, rB_addr);
3627         // rD = rA + (-1) + XER[CA]
3628         // => Just another form of adde
3629         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3630         min_one = mkSzImm(ty, (Long)-1);
3631         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3632                            binop( mkSzOp(ty, Iop_Add8),
3633                                   min_one, mkexpr(old_xer_ca)) ));
3634         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3635                     mkexpr(rD), mkexpr(rA), min_one,
3636                     mkexpr(old_xer_ca) );
3637         if (flag_OE) {
3638            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3639                        mkexpr(rD), mkexpr(rA), min_one );
3640         }
3641         break;
3642      }
3643
3644      case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
3645         IRTemp old_xer_ca = newTemp(ty);
3646         if (rB_addr != 0) {
3647            vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
3648            return False;
3649         }
3650         DIP("addze%s%s r%u,r%u,r%u\n",
3651             flag_OE ? "o" : "", flag_rC ? ".":"",
3652             rD_addr, rA_addr, rB_addr);
3653         // rD = rA + (0) + XER[CA]
3654         // => Just another form of adde
3655         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3656         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3657                            mkexpr(rA), mkexpr(old_xer_ca)) );
3658         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3659                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3660                     mkexpr(old_xer_ca) );
3661         if (flag_OE) {
3662            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3663                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3664         }
3665         break;
3666      }
3667
3668      case 0x1EB: // divw       (Divide Word, PPC32 p388)
3669         DIP("divw%s%s r%u,r%u,r%u\n",
3670             flag_OE ? "o" : "", flag_rC ? ".":"",
3671             rD_addr, rA_addr, rB_addr);
3672         if (mode64) {
3673            /* Note:
3674               XER settings are mode independent, and reflect the
3675               overflow of the low-order 32bit result
3676               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3677            */
3678            /* rD[hi32] are undefined: setting them to sign of lo32
3679                - makes set_CR0 happy */
3680            IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
3681            IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
3682            assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
3683                                                         divisor) ) );
3684            if (flag_OE) {
3685               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3686                           mkexpr(rD), dividend, divisor );
3687            }
3688         } else {
3689            assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
3690            if (flag_OE) {
3691               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3692                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3693            }
3694         }
3695         /* Note:
3696            if (0x8000_0000 / -1) or (x / 0)
3697            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3698            => But _no_ exception raised. */
3699         break;
3700
3701      case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
3702         DIP("divwu%s%s r%u,r%u,r%u\n",
3703             flag_OE ? "o" : "", flag_rC ? ".":"",
3704             rD_addr, rA_addr, rB_addr);
3705         if (mode64) {
3706            /* Note:
3707               XER settings are mode independent, and reflect the
3708               overflow of the low-order 32bit result
3709               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3710            */
3711            IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
3712            IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
3713            assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
3714                                                         divisor) ) );
3715            if (flag_OE) {
3716               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3717                           mkexpr(rD), dividend, divisor );
3718            }
3719         } else {
3720            assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
3721            if (flag_OE) {
3722               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3723                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3724            }
3725         }
3726         /* Note: ditto comment divw, for (x / 0) */
3727         break;
3728
3729      case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
3730         if (flag_OE != 0) {
3731            vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
3732            return False;
3733         }
3734         DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3735             rD_addr, rA_addr, rB_addr);
3736         if (mode64) {
3737            /* rD[hi32] are undefined: setting them to sign of lo32
3738                - makes set_CR0 happy */
3739            assign( rD, binop(Iop_Sar64,
3740                           binop(Iop_Mul64,
3741                                 mk64lo32Sto64( mkexpr(rA) ),
3742                                 mk64lo32Sto64( mkexpr(rB) )),
3743                              mkU8(32)) );
3744         } else {
3745            assign( rD, unop(Iop_64HIto32,
3746                             binop(Iop_MullS32,
3747                                   mkexpr(rA), mkexpr(rB))) );
3748         }
3749         break;
3750
3751      case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
3752         if (flag_OE != 0) {
3753            vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
3754            return False;
3755         }
3756         DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3757             rD_addr, rA_addr, rB_addr);
3758         if (mode64) {
3759            /* rD[hi32] are undefined: setting them to sign of lo32
3760                - makes set_CR0 happy */
3761            assign( rD, binop(Iop_Sar64,
3762                           binop(Iop_Mul64,
3763                                 mk64lo32Uto64( mkexpr(rA) ),
3764                                 mk64lo32Uto64( mkexpr(rB) ) ),
3765                              mkU8(32)) );
3766         } else {
3767            assign( rD, unop(Iop_64HIto32,
3768                             binop(Iop_MullU32,
3769                                   mkexpr(rA), mkexpr(rB))) );
3770         }
3771         break;
3772
3773      case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
3774         DIP("mullw%s%s r%u,r%u,r%u\n",
3775             flag_OE ? "o" : "", flag_rC ? ".":"",
3776             rD_addr, rA_addr, rB_addr);
3777         if (mode64) {
3778            /* rD[hi32] are undefined: setting them to sign of lo32
3779                - set_XER_OV() and set_CR0() depend on this */
3780            IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
3781            IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
3782            assign( rD, binop(Iop_MullS32, a, b) );
3783            if (flag_OE) {
3784               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3785                           mkexpr(rD),
3786                           unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
3787            }
3788         } else {
3789            assign( rD, unop(Iop_64to32,
3790                             binop(Iop_MullU32,
3791                                   mkexpr(rA), mkexpr(rB))) );
3792            if (flag_OE) {
3793               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3794                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3795            }
3796         }
3797         break;
3798
3799      case 0x068: // neg        (Negate, PPC32 p493)
3800         if (rB_addr != 0) {
3801            vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
3802            return False;
3803         }
3804         DIP("neg%s%s r%u,r%u\n",
3805             flag_OE ? "o" : "", flag_rC ? ".":"",
3806             rD_addr, rA_addr);
3807         // rD = (~rA) + 1
3808         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3809                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
3810                            mkSzImm(ty, 1)) );
3811         if (flag_OE) {
3812            set_XER_OV( ty, PPCG_FLAG_OP_NEG,
3813                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3814         }
3815         break;
3816
3817      case 0x028: // subf       (Subtract From, PPC32 p537)
3818         DIP("subf%s%s r%u,r%u,r%u\n",
3819             flag_OE ? "o" : "", flag_rC ? ".":"",
3820             rD_addr, rA_addr, rB_addr);
3821         // rD = rB - rA
3822         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3823                            mkexpr(rB), mkexpr(rA)) );
3824         if (flag_OE) {
3825            set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
3826                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3827         }
3828         break;
3829
3830      case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
3831         DIP("subfc%s%s r%u,r%u,r%u\n",
3832             flag_OE ? "o" : "", flag_rC ? ".":"",
3833             rD_addr, rA_addr, rB_addr);
3834         // rD = rB - rA
3835         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3836                            mkexpr(rB), mkexpr(rA)) );
3837         set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
3838                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3839                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3840         if (flag_OE) {
3841            set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
3842                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3843         }
3844         break;
3845
3846      case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
3847         IRTemp old_xer_ca = newTemp(ty);
3848         DIP("subfe%s%s r%u,r%u,r%u\n",
3849             flag_OE ? "o" : "", flag_rC ? ".":"",
3850             rD_addr, rA_addr, rB_addr);
3851         // rD = (log not)rA + rB + XER[CA]
3852         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3853         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3854                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3855                            binop( mkSzOp(ty, Iop_Add8),
3856                                   mkexpr(rB), mkexpr(old_xer_ca))) );
3857         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3858                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3859                     mkexpr(old_xer_ca) );
3860         if (flag_OE) {
3861            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3862                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3863         }
3864         break;
3865      }
3866
3867      case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
3868         IRTemp old_xer_ca = newTemp(ty);
3869         IRExpr *min_one;
3870         if (rB_addr != 0) {
3871            vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
3872            return False;
3873         }
3874         DIP("subfme%s%s r%u,r%u\n",
3875             flag_OE ? "o" : "", flag_rC ? ".":"",
3876             rD_addr, rA_addr);
3877         // rD = (log not)rA + (-1) + XER[CA]
3878         // => Just another form of subfe
3879         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3880         min_one = mkSzImm(ty, (Long)-1);
3881         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3882                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3883                            binop( mkSzOp(ty, Iop_Add8),
3884                                   min_one, mkexpr(old_xer_ca))) );
3885         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3886                     mkexpr(rD), mkexpr(rA), min_one,
3887                     mkexpr(old_xer_ca) );
3888         if (flag_OE) {
3889            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3890                        mkexpr(rD), mkexpr(rA), min_one );
3891         }
3892         break;
3893      }
3894
3895      case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
3896         IRTemp old_xer_ca = newTemp(ty);
3897         if (rB_addr != 0) {
3898            vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
3899            return False;
3900         }
3901         DIP("subfze%s%s r%u,r%u\n",
3902             flag_OE ? "o" : "", flag_rC ? ".":"",
3903             rD_addr, rA_addr);
3904         // rD = (log not)rA + (0) + XER[CA]
3905         // => Just another form of subfe
3906         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3907         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3908                           unop( mkSzOp(ty, Iop_Not8),
3909                                 mkexpr(rA)), mkexpr(old_xer_ca)) );
3910         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3911                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3912                     mkexpr(old_xer_ca) );
3913         if (flag_OE) {
3914            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3915                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3916         }
3917         break;
3918      }
3919
3920
3921      /* 64bit Arithmetic */
3922      case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
3923         if (flag_OE != 0) {
3924            vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
3925            return False;
3926         }
3927         DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3928             rD_addr, rA_addr, rB_addr);
3929         assign( rD, unop(Iop_128HIto64,
3930                          binop(Iop_MullS64,
3931                                mkexpr(rA), mkexpr(rB))) );
3932
3933         break;
3934
3935      case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
3936         if (flag_OE != 0) {
3937            vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
3938            return False;
3939         }
3940         DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3941             rD_addr, rA_addr, rB_addr);
3942         assign( rD, unop(Iop_128HIto64,
3943                          binop(Iop_MullU64,
3944                                mkexpr(rA), mkexpr(rB))) );
3945         break;
3946
3947      case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
3948         DIP("mulld%s%s r%u,r%u,r%u\n",
3949             flag_OE ? "o" : "", flag_rC ? ".":"",
3950             rD_addr, rA_addr, rB_addr);
3951         assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
3952         if (flag_OE) {
3953            set_XER_OV( ty, PPCG_FLAG_OP_MULLD,
3954                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3955         }
3956         break;
3957
3958      case 0x1E9: // divd (Divide DWord, PPC64 p419)
3959         DIP("divd%s%s r%u,r%u,r%u\n",
3960             flag_OE ? "o" : "", flag_rC ? ".":"",
3961             rD_addr, rA_addr, rB_addr);
3962         assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
3963         if (flag_OE) {
3964            set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3965                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3966         }
3967         break;
3968         /* Note:
3969            if (0x8000_0000_0000_0000 / -1) or (x / 0)
3970            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3971            => But _no_ exception raised. */
3972
3973      case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
3974         DIP("divdu%s%s r%u,r%u,r%u\n",
3975             flag_OE ? "o" : "", flag_rC ? ".":"",
3976             rD_addr, rA_addr, rB_addr);
3977         assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
3978         if (flag_OE) {
3979            set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3980                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3981         }
3982         break;
3983         /* Note: ditto comment divd, for (x / 0) */
3984
3985      case 0x18B: // divweu (Divide Word Extended Unsigned)
3986      {
3987        /*
3988         *  If (RA) >= (RB), or if an attempt is made to perform the division
3989         *         <anything> / 0
3990         * then the contents of register RD are undefined as are (if Rc=1) the contents of
3991         * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
3992         * to 1.
3993         */
3994         IRTemp res = newTemp(Ity_I32);
3995         IRExpr * dividend, * divisor;
3996         DIP("divweu%s%s r%u,r%u,r%u\n",
3997             flag_OE ? "o" : "", flag_rC ? ".":"",
3998                                         rD_addr, rA_addr, rB_addr);
3999         if (mode64) {
4000            dividend = unop( Iop_64to32, mkexpr( rA ) );
4001            divisor = unop( Iop_64to32, mkexpr( rB ) );
4002            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
4003            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
4004         } else {
4005            dividend = mkexpr( rA );
4006            divisor =  mkexpr( rB );
4007            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
4008            assign( rD, mkexpr( res) );
4009         }
4010
4011         if (flag_OE) {
4012            set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
4013                           mkexpr(res), dividend, divisor );
4014         }
4015         break;
4016      }
4017
4018      case 0x1AB: // divwe (Divide Word Extended)
4019      {
4020         /*
4021          * If the quotient cannot be represented in 32 bits, or if an
4022          * attempt is made to perform the division
4023          *      <anything> / 0
4024          * then the contents of register RD are undefined as are (if
4025          * Rc=1) the contents of the LT, GT, and EQ bits of CR
4026          * Field 0. In these cases, if OE=1 then OV is set to 1.
4027          */
4028
4029         IRTemp res = newTemp(Ity_I32);
4030         IRExpr * dividend, * divisor;
4031         DIP("divwe%s%s r%u,r%u,r%u\n",
4032             flag_OE ? "o" : "", flag_rC ? ".":"",
4033                                         rD_addr, rA_addr, rB_addr);
4034         if (mode64) {
4035            dividend = unop( Iop_64to32, mkexpr( rA ) );
4036            divisor = unop( Iop_64to32, mkexpr( rB ) );
4037            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
4038            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
4039         } else {
4040            dividend = mkexpr( rA );
4041            divisor =  mkexpr( rB );
4042            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
4043            assign( rD, mkexpr( res) );
4044         }
4045
4046         if (flag_OE) {
4047            set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
4048                           mkexpr(res), dividend, divisor );
4049         }
4050         break;
4051      }
4052
4053
4054      case 0x1A9: // divde (Divide Doubleword Extended)
4055        /*
4056         * If the quotient cannot be represented in 64 bits, or if an
4057         * attempt is made to perform the division
4058         *      <anything> / 0
4059         * then the contents of register RD are undefined as are (if
4060         * Rc=1) the contents of the LT, GT, and EQ bits of CR
4061         * Field 0. In these cases, if OE=1 then OV is set to 1.
4062         */
4063         DIP("divde%s%s r%u,r%u,r%u\n",
4064             flag_OE ? "o" : "", flag_rC ? ".":"",
4065             rD_addr, rA_addr, rB_addr);
4066         assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
4067         if (flag_OE) {
4068            set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
4069                           mkexpr( rA ), mkexpr( rB ) );
4070         }
4071         break;
4072
4073      case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
4074        // Same CR and OV rules as given for divweu above
4075        DIP("divdeu%s%s r%u,r%u,r%u\n",
4076            flag_OE ? "o" : "", flag_rC ? ".":"",
4077            rD_addr, rA_addr, rB_addr);
4078        assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
4079        if (flag_OE) {
4080           set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
4081                          mkexpr( rA ), mkexpr( rB ) );
4082        }
4083        break;
4084
4085      default:
4086         vex_printf("dis_int_arith(ppc)(opc2)\n");
4087         return False;
4088      }
4089      break;
4090
4091   default:
4092      vex_printf("dis_int_arith(ppc)(opc1)\n");
4093      return False;
4094   }
4095
4096   putIReg( rD_addr, mkexpr(rD) );
4097
4098   if (do_rc && flag_rC) {
4099      set_CR0( mkexpr(rD) );
4100   }
4101   return True;
4102}
4103
4104
4105
4106/*
4107  Integer Compare Instructions
4108*/
4109static Bool dis_int_cmp ( UInt theInstr )
4110{
4111   /* D-Form, X-Form */
4112   UChar opc1    = ifieldOPC(theInstr);
4113   UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
4114   UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
4115   UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
4116   UChar rA_addr = ifieldRegA(theInstr);
4117   UInt  uimm16  = ifieldUIMM16(theInstr);
4118   UChar rB_addr = ifieldRegB(theInstr);
4119   UInt  opc2    = ifieldOPClo10(theInstr);
4120   UChar b0      = ifieldBIT0(theInstr);
4121
4122   IRType ty = mode64 ? Ity_I64 : Ity_I32;
4123   IRExpr *a = getIReg(rA_addr);
4124   IRExpr *b;
4125
4126   if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
4127      vex_printf("dis_int_cmp(ppc)(flag_L)\n");
4128      return False;
4129   }
4130
4131   if (b22 != 0) {
4132      vex_printf("dis_int_cmp(ppc)(b22)\n");
4133      return False;
4134   }
4135
4136   switch (opc1) {
4137   case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
4138      DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
4139          (Int)extend_s_16to32(uimm16));
4140      b = mkSzExtendS16( ty, uimm16 );
4141      if (flag_L == 1) {
4142         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
4143      } else {
4144         a = mkNarrowTo32( ty, a );
4145         b = mkNarrowTo32( ty, b );
4146         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
4147      }
4148      putCR0( crfD, getXER_SO() );
4149      break;
4150
4151   case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
4152      DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
4153      b = mkSzImm( ty, uimm16 );
4154      if (flag_L == 1) {
4155         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
4156      } else {
4157         a = mkNarrowTo32( ty, a );
4158         b = mkNarrowTo32( ty, b );
4159         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
4160      }
4161      putCR0( crfD, getXER_SO() );
4162      break;
4163
4164   /* X Form */
4165   case 0x1F:
4166      if (b0 != 0) {
4167         vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
4168         return False;
4169      }
4170      b = getIReg(rB_addr);
4171
4172      switch (opc2) {
4173      case 0x000: // cmp (Compare, PPC32 p367)
4174         DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
4175         /* Comparing a reg with itself produces a result which
4176            doesn't depend on the contents of the reg.  Therefore
4177            remove the false dependency, which has been known to cause
4178            memcheck to produce false errors. */
4179         if (rA_addr == rB_addr)
4180            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
4181                    ? mkU64(0)  : mkU32(0);
4182         if (flag_L == 1) {
4183            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
4184         } else {
4185            a = mkNarrowTo32( ty, a );
4186            b = mkNarrowTo32( ty, b );
4187            putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
4188         }
4189         putCR0( crfD, getXER_SO() );
4190         break;
4191
4192      case 0x020: // cmpl (Compare Logical, PPC32 p369)
4193         DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
4194         /* Comparing a reg with itself produces a result which
4195            doesn't depend on the contents of the reg.  Therefore
4196            remove the false dependency, which has been known to cause
4197            memcheck to produce false errors. */
4198         if (rA_addr == rB_addr)
4199            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
4200                    ? mkU64(0)  : mkU32(0);
4201         if (flag_L == 1) {
4202            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
4203         } else {
4204            a = mkNarrowTo32( ty, a );
4205            b = mkNarrowTo32( ty, b );
4206            putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
4207         }
4208         putCR0( crfD, getXER_SO() );
4209         break;
4210
4211      default:
4212         vex_printf("dis_int_cmp(ppc)(opc2)\n");
4213         return False;
4214      }
4215      break;
4216
4217   default:
4218      vex_printf("dis_int_cmp(ppc)(opc1)\n");
4219      return False;
4220   }
4221
4222   return True;
4223}
4224
4225
4226/*
4227  Integer Logical Instructions
4228*/
4229static Bool dis_int_logic ( UInt theInstr )
4230{
4231   /* D-Form, X-Form */
4232   UChar opc1    = ifieldOPC(theInstr);
4233   UChar rS_addr = ifieldRegDS(theInstr);
4234   UChar rA_addr = ifieldRegA(theInstr);
4235   UInt  uimm16  = ifieldUIMM16(theInstr);
4236   UChar rB_addr = ifieldRegB(theInstr);
4237   UInt  opc2    = ifieldOPClo10(theInstr);
4238   UChar flag_rC = ifieldBIT0(theInstr);
4239
4240   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4241   IRTemp rS     = newTemp(ty);
4242   IRTemp rA     = newTemp(ty);
4243   IRTemp rB     = newTemp(ty);
4244   IRExpr* irx;
4245   Bool do_rc    = False;
4246
4247   assign( rS, getIReg(rS_addr) );
4248   assign( rB, getIReg(rB_addr) );
4249
4250   switch (opc1) {
4251   case 0x1C: // andi. (AND Immediate, PPC32 p358)
4252      DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4253      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
4254                         mkSzImm(ty, uimm16)) );
4255      do_rc = True;  // Always record to CR
4256      flag_rC = 1;
4257      break;
4258
4259   case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
4260      DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4261      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
4262                         mkSzImm(ty, uimm16 << 16)) );
4263      do_rc = True;  // Always record to CR
4264      flag_rC = 1;
4265      break;
4266
4267   case 0x18: // ori (OR Immediate, PPC32 p497)
4268      DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4269      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4270                         mkSzImm(ty, uimm16)) );
4271      break;
4272
4273   case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
4274      DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4275      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4276                         mkSzImm(ty, uimm16 << 16)) );
4277      break;
4278
4279   case 0x1A: // xori (XOR Immediate, PPC32 p550)
4280      DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4281      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
4282                         mkSzImm(ty, uimm16)) );
4283      break;
4284
4285   case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
4286      DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4287      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
4288                         mkSzImm(ty, uimm16 << 16)) );
4289      break;
4290
4291   /* X Form */
4292   case 0x1F:
4293      do_rc = True; // All below record to CR, except for where we return at case end.
4294
4295      switch (opc2) {
4296      case 0x01C: // and (AND, PPC32 p356)
4297         DIP("and%s r%u,r%u,r%u\n",
4298             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4299         assign(rA, binop( mkSzOp(ty, Iop_And8),
4300                           mkexpr(rS), mkexpr(rB)));
4301         break;
4302
4303      case 0x03C: // andc (AND with Complement, PPC32 p357)
4304         DIP("andc%s r%u,r%u,r%u\n",
4305             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4306         assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
4307                           unop( mkSzOp(ty, Iop_Not8),
4308                                 mkexpr(rB))));
4309         break;
4310
4311      case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
4312         IRExpr* lo32;
4313         if (rB_addr!=0) {
4314            vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
4315            return False;
4316         }
4317         DIP("cntlzw%s r%u,r%u\n",
4318             flag_rC ? ".":"", rA_addr, rS_addr);
4319
4320         // mode64: count in low word only
4321         lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
4322
4323         // Iop_Clz32 undefined for arg==0, so deal with that case:
4324         irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
4325         assign(rA, mkWidenFrom32(ty,
4326                         IRExpr_ITE( irx,
4327                                     unop(Iop_Clz32, lo32),
4328                                     mkU32(32)),
4329                         False));
4330
4331         // TODO: alternatively: assign(rA, verbose_Clz32(rS));
4332         break;
4333      }
4334
4335      case 0x11C: // eqv (Equivalent, PPC32 p396)
4336         DIP("eqv%s r%u,r%u,r%u\n",
4337             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4338         assign( rA, unop( mkSzOp(ty, Iop_Not8),
4339                           binop( mkSzOp(ty, Iop_Xor8),
4340                                  mkexpr(rS), mkexpr(rB))) );
4341         break;
4342
4343      case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
4344         if (rB_addr!=0) {
4345            vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
4346            return False;
4347         }
4348         DIP("extsb%s r%u,r%u\n",
4349             flag_rC ? ".":"", rA_addr, rS_addr);
4350         if (mode64)
4351            assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
4352         else
4353            assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
4354         break;
4355
4356      case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
4357         if (rB_addr!=0) {
4358            vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
4359            return False;
4360         }
4361         DIP("extsh%s r%u,r%u\n",
4362             flag_rC ? ".":"", rA_addr, rS_addr);
4363         if (mode64)
4364            assign( rA, unop(Iop_16Sto64,
4365                             unop(Iop_64to16, mkexpr(rS))) );
4366         else
4367            assign( rA, unop(Iop_16Sto32,
4368                             unop(Iop_32to16, mkexpr(rS))) );
4369         break;
4370
4371      case 0x1DC: // nand (NAND, PPC32 p492)
4372         DIP("nand%s r%u,r%u,r%u\n",
4373             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4374         assign( rA, unop( mkSzOp(ty, Iop_Not8),
4375                           binop( mkSzOp(ty, Iop_And8),
4376                                  mkexpr(rS), mkexpr(rB))) );
4377         break;
4378
4379      case 0x07C: // nor (NOR, PPC32 p494)
4380         DIP("nor%s r%u,r%u,r%u\n",
4381             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4382         assign( rA, unop( mkSzOp(ty, Iop_Not8),
4383                           binop( mkSzOp(ty, Iop_Or8),
4384                                  mkexpr(rS), mkexpr(rB))) );
4385         break;
4386
4387      case 0x1BC: // or (OR, PPC32 p495)
4388         if ((!flag_rC) && rS_addr == rB_addr) {
4389            DIP("mr r%u,r%u\n", rA_addr, rS_addr);
4390            assign( rA, mkexpr(rS) );
4391         } else {
4392            DIP("or%s r%u,r%u,r%u\n",
4393                flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4394            assign( rA, binop( mkSzOp(ty, Iop_Or8),
4395                               mkexpr(rS), mkexpr(rB)) );
4396         }
4397         break;
4398
4399      case 0x19C: // orc  (OR with Complement, PPC32 p496)
4400         DIP("orc%s r%u,r%u,r%u\n",
4401             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4402         assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4403                            unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
4404         break;
4405
4406      case 0x13C: // xor (XOR, PPC32 p549)
4407         DIP("xor%s r%u,r%u,r%u\n",
4408             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4409         assign( rA, binop( mkSzOp(ty, Iop_Xor8),
4410                            mkexpr(rS), mkexpr(rB)) );
4411         break;
4412
4413
4414      /* 64bit Integer Logical Instructions */
4415      case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
4416         if (rB_addr!=0) {
4417            vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
4418            return False;
4419         }
4420         DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
4421         assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
4422         break;
4423
4424      case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
4425         if (rB_addr!=0) {
4426            vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
4427            return False;
4428         }
4429         DIP("cntlzd%s r%u,r%u\n",
4430             flag_rC ? ".":"", rA_addr, rS_addr);
4431         // Iop_Clz64 undefined for arg==0, so deal with that case:
4432         irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
4433         assign(rA, IRExpr_ITE( irx,
4434                                unop(Iop_Clz64, mkexpr(rS)),
4435                                mkU64(64) ));
4436         // TODO: alternatively: assign(rA, verbose_Clz64(rS));
4437         break;
4438
4439      case 0x1FC: // cmpb (Power6: compare bytes)
4440         DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
4441
4442         if (mode64)
4443            assign( rA, unop( Iop_V128to64,
4444                              binop( Iop_CmpEQ8x16,
4445                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
4446                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
4447                                     )) );
4448         else
4449            assign( rA, unop( Iop_V128to32,
4450                              binop( Iop_CmpEQ8x16,
4451                                     unop( Iop_32UtoV128, mkexpr(rS) ),
4452                                     unop( Iop_32UtoV128, mkexpr(rB) )
4453                                     )) );
4454         break;
4455
4456      case 0x2DF: { // mftgpr (move floating-point to general purpose register)
4457         IRTemp frB = newTemp(Ity_F64);
4458         DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
4459
4460         assign( frB, getFReg(rB_addr));  // always F64
4461         if (mode64)
4462            assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
4463         else
4464            assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
4465
4466         putIReg( rS_addr, mkexpr(rA));
4467         return True;
4468      }
4469
4470      case 0x25F: { // mffgpr (move floating-point from general purpose register)
4471         IRTemp frA = newTemp(Ity_F64);
4472         DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
4473
4474         if (mode64)
4475            assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
4476         else
4477            assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
4478
4479         putFReg( rS_addr, mkexpr(frA));
4480         return True;
4481      }
4482      case 0x1FA: // popcntd (population count doubleword
4483      {
4484    	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
4485    	  IRTemp result = gen_POPCOUNT(ty, rS, DWORD);
4486    	  putIReg( rA_addr, mkexpr(result) );
4487    	  return True;
4488      }
4489      case 0x17A: // popcntw (Population Count Words)
4490      {
4491         DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
4492         if (mode64) {
4493            IRTemp resultHi, resultLo;
4494            IRTemp argLo = newTemp(Ity_I32);
4495            IRTemp argHi = newTemp(Ity_I32);
4496            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4497            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
4498            resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD);
4499            resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD);
4500            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
4501         } else {
4502            IRTemp result = gen_POPCOUNT(ty, rS, WORD);
4503            putIReg( rA_addr, mkexpr(result) );
4504         }
4505         return True;
4506      }
4507      case 0x7A: // popcntb (Population Count Byte)
4508      {
4509         DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
4510
4511         if (mode64) {
4512            IRTemp resultHi, resultLo;
4513            IRTemp argLo = newTemp(Ity_I32);
4514            IRTemp argHi = newTemp(Ity_I32);
4515            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4516            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
4517            resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE);
4518            resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE);
4519            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
4520                                    mkexpr(resultLo)));
4521         } else {
4522            IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
4523            putIReg( rA_addr, mkexpr(result) );
4524         }
4525         return True;
4526      }
4527       case 0x0FC: // bpermd (Bit Permute Doubleword)
4528       {
4529          /* This is a lot of rigmarole to emulate bpermd like this, as it
4530           * could be done much faster by implementing a call to the native
4531           * instruction.  However, where possible I want to avoid using new
4532           * native instructions so that we can use valgrind to emulate those
4533           * instructions on older PPC64 hardware.
4534           */
4535 #define BPERMD_IDX_MASK 0x00000000000000FFULL
4536 #define BPERMD_BIT_MASK 0x8000000000000000ULL
4537          int i;
4538          IRExpr * rS_expr = mkexpr(rS);
4539          IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
4540          DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
4541          for (i = 0; i < 8; i++) {
4542             IRTemp idx_tmp = newTemp( Ity_I64 );
4543             IRTemp perm_bit = newTemp( Ity_I64 );
4544             IRTemp idx = newTemp( Ity_I8 );
4545             IRTemp idx_LT64 = newTemp( Ity_I1 );
4546             IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
4547
4548             assign( idx_tmp,
4549                     binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
4550             assign( idx_LT64,
4551                           binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
4552             assign( idx,
4553                           binop( Iop_And8,
4554                                  unop( Iop_1Sto8,
4555                                        mkexpr(idx_LT64) ),
4556                                  unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
4557             /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
4558              * to determine which bit of rB to use for the perm bit, and then we shift
4559              * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
4560              * to set the final perm bit.
4561              */
4562             assign( idx_LT64_ity64,
4563                           unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
4564             assign( perm_bit,
4565                           binop( Iop_And64,
4566                                  mkexpr( idx_LT64_ity64 ),
4567                                  binop( Iop_Shr64,
4568                                         binop( Iop_And64,
4569                                                mkU64( BPERMD_BIT_MASK ),
4570                                                binop( Iop_Shl64,
4571                                                       mkexpr( rB ),
4572                                                       mkexpr( idx ) ) ),
4573                                         mkU8( 63 ) ) ) );
4574             res = binop( Iop_Or64,
4575                                res,
4576                                binop( Iop_Shl64,
4577                                       mkexpr( perm_bit ),
4578                                       mkU8( i ) ) );
4579             rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
4580          }
4581          putIReg(rA_addr, res);
4582          return True;
4583       }
4584
4585      default:
4586         vex_printf("dis_int_logic(ppc)(opc2)\n");
4587         return False;
4588      }
4589      break;
4590
4591   default:
4592      vex_printf("dis_int_logic(ppc)(opc1)\n");
4593      return False;
4594   }
4595
4596   putIReg( rA_addr, mkexpr(rA) );
4597
4598   if (do_rc && flag_rC) {
4599      set_CR0( mkexpr(rA) );
4600   }
4601   return True;
4602}
4603
4604/*
4605  Integer Parity Instructions
4606*/
4607static Bool dis_int_parity ( UInt theInstr )
4608{
4609   /* X-Form */
4610   UChar opc1    = ifieldOPC(theInstr);
4611   UChar rS_addr = ifieldRegDS(theInstr);
4612   UChar rA_addr = ifieldRegA(theInstr);
4613   UChar rB_addr = ifieldRegB(theInstr);
4614   UInt  opc2    = ifieldOPClo10(theInstr);
4615   UChar b0      = ifieldBIT0(theInstr);
4616   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4617
4618   IRTemp rS     = newTemp(ty);
4619   IRTemp rA     = newTemp(ty);
4620   IRTemp iTot1  = newTemp(Ity_I32);
4621   IRTemp iTot2  = newTemp(Ity_I32);
4622   IRTemp iTot3  = newTemp(Ity_I32);
4623   IRTemp iTot4  = newTemp(Ity_I32);
4624   IRTemp iTot5  = newTemp(Ity_I32);
4625   IRTemp iTot6  = newTemp(Ity_I32);
4626   IRTemp iTot7  = newTemp(Ity_I32);
4627   IRTemp iTot8  = newTemp(Ity_I32);
4628   IRTemp rS1    = newTemp(ty);
4629   IRTemp rS2    = newTemp(ty);
4630   IRTemp rS3    = newTemp(ty);
4631   IRTemp rS4    = newTemp(ty);
4632   IRTemp rS5    = newTemp(ty);
4633   IRTemp rS6    = newTemp(ty);
4634   IRTemp rS7    = newTemp(ty);
4635   IRTemp iHi    = newTemp(Ity_I32);
4636   IRTemp iLo    = newTemp(Ity_I32);
4637   IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
4638   IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
4639
4640   if (opc1 != 0x1f || rB_addr || b0) {
4641      vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
4642      return False;
4643   }
4644
4645   assign( rS, getIReg(rS_addr) );
4646
4647   switch (opc2) {
4648   case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
4649      DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
4650      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4651      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4652      assign( iTot2, binop(Iop_Add32,
4653                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4654                           mkexpr(iTot1)) );
4655      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4656      assign( iTot3, binop(Iop_Add32,
4657                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4658                           mkexpr(iTot2)) );
4659      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4660      assign( iTot4, binop(Iop_Add32,
4661                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4662                           mkexpr(iTot3)) );
4663      if (mode64) {
4664         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4665         assign( iTot5, binop(Iop_Add32,
4666                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
4667                              mkexpr(iTot4)) );
4668         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4669         assign( iTot6, binop(Iop_Add32,
4670                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4671                              mkexpr(iTot5)) );
4672         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4673         assign( iTot7, binop(Iop_Add32,
4674                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4675                              mkexpr(iTot6)) );
4676         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
4677         assign( iTot8, binop(Iop_Add32,
4678                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4679                              mkexpr(iTot7)) );
4680         assign( rA, unop(Iop_32Uto64,
4681                          binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
4682      } else
4683         assign( rA, mkexpr(iTot4) );
4684
4685      break;
4686   case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
4687      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4688      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4689      assign( iTot2, binop(Iop_Add32,
4690                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4691                           mkexpr(iTot1)) );
4692      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4693      assign( iTot3, binop(Iop_Add32,
4694                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4695                           mkexpr(iTot2)) );
4696      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4697      assign( iTot4, binop(Iop_Add32,
4698                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4699                           mkexpr(iTot3)) );
4700      assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
4701
4702      if (mode64) {
4703         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4704         assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
4705         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4706         assign( iTot6, binop(Iop_Add32,
4707                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4708                              mkexpr(iTot5)) );
4709         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4710         assign( iTot7, binop(Iop_Add32,
4711                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4712                              mkexpr(iTot6)) );
4713         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
4714         assign( iTot8, binop(Iop_Add32,
4715                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4716                              mkexpr(iTot7)) );
4717         assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
4718            assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
4719      } else
4720         assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
4721      break;
4722   default:
4723      vex_printf("dis_int_parity(ppc)(opc2)\n");
4724      return False;
4725   }
4726
4727   putIReg( rA_addr, mkexpr(rA) );
4728
4729   return True;
4730}
4731
4732
4733/*
4734  Integer Rotate Instructions
4735*/
4736static Bool dis_int_rot ( UInt theInstr )
4737{
4738   /* M-Form, MDS-Form */
4739   UChar opc1    = ifieldOPC(theInstr);
4740   UChar rS_addr = ifieldRegDS(theInstr);
4741   UChar rA_addr = ifieldRegA(theInstr);
4742   UChar rB_addr = ifieldRegB(theInstr);
4743   UChar sh_imm  = rB_addr;
4744   UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
4745   UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
4746   UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
4747   UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
4748   UChar b1      = ifieldBIT1(theInstr);
4749   UChar flag_rC = ifieldBIT0(theInstr);
4750
4751   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4752   IRTemp rS     = newTemp(ty);
4753   IRTemp rA     = newTemp(ty);
4754   IRTemp rB     = newTemp(ty);
4755   IRTemp rot    = newTemp(ty);
4756   IRExpr *r;
4757   UInt   mask32;
4758   ULong  mask64;
4759
4760   assign( rS, getIReg(rS_addr) );
4761   assign( rB, getIReg(rB_addr) );
4762
4763   switch (opc1) {
4764   case 0x14: {
4765      // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
4766      DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4767          rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4768      if (mode64) {
4769         // tmp32 = (ROTL(rS_Lo32, Imm)
4770         // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
4771         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4772         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4773         r = unop(Iop_32Uto64, r);
4774         assign( rot, binop(Iop_Or64, r,
4775                            binop(Iop_Shl64, r, mkU8(32))) );
4776         assign( rA,
4777            binop(Iop_Or64,
4778                  binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
4779                  binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
4780      }
4781      else {
4782         // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
4783         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4784         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4785         assign( rA,
4786            binop(Iop_Or32,
4787                  binop(Iop_And32, mkU32(mask32), r),
4788                  binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
4789      }
4790      break;
4791   }
4792
4793   case 0x15: {
4794      // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
4795      vassert(MaskBeg < 32);
4796      vassert(MaskEnd < 32);
4797      vassert(sh_imm  < 32);
4798
4799      if (mode64) {
4800         IRTemp rTmp = newTemp(Ity_I64);
4801         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4802         DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4803             rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4804         // tmp32 = (ROTL(rS_Lo32, Imm)
4805         // rA = ((tmp32 || tmp32) & mask64)
4806         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4807         r = unop(Iop_32Uto64, r);
4808         assign( rTmp, r );
4809         r = NULL;
4810         assign( rot, binop(Iop_Or64, mkexpr(rTmp),
4811                            binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
4812         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4813      }
4814      else {
4815         if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
4816            /* Special-case the ,n,0,31-n form as that is just n-bit
4817               shift left, PPC32 p501 */
4818            DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4819                rA_addr, rS_addr, sh_imm);
4820            assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
4821         }
4822         else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
4823            /* Special-case the ,32-n,n,31 form as that is just n-bit
4824               unsigned shift right, PPC32 p501 */
4825            DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4826                rA_addr, rS_addr, MaskBeg);
4827            assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
4828         }
4829         else {
4830            /* General case. */
4831            mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4832            DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4833                rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4834            // rA = ROTL(rS, Imm) & mask
4835            assign( rA, binop(Iop_And32,
4836                              ROTL(mkexpr(rS), mkU8(sh_imm)),
4837                              mkU32(mask32)) );
4838         }
4839      }
4840      break;
4841   }
4842
4843   case 0x17: {
4844      // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
4845      DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
4846          rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
4847      if (mode64) {
4848         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4849         /* weird insn alert!
4850            tmp32 = (ROTL(rS_Lo32, rB[0-4])
4851            rA = ((tmp32 || tmp32) & mask64)
4852         */
4853         // note, ROTL does the masking, so we don't do it here
4854         r = ROTL( unop(Iop_64to32, mkexpr(rS)),
4855                   unop(Iop_64to8, mkexpr(rB)) );
4856         r = unop(Iop_32Uto64, r);
4857         assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
4858         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4859      } else {
4860         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4861         // rA = ROTL(rS, rB[0-4]) & mask
4862         // note, ROTL does the masking, so we don't do it here
4863         assign( rA, binop(Iop_And32,
4864                           ROTL(mkexpr(rS),
4865                                unop(Iop_32to8, mkexpr(rB))),
4866                           mkU32(mask32)) );
4867      }
4868      break;
4869   }
4870
4871   /* 64bit Integer Rotates */
4872   case 0x1E: {
4873      msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
4874      sh_imm |= b1 << 5;
4875
4876      vassert( msk_imm < 64 );
4877      vassert( sh_imm < 64 );
4878
4879      switch (opc2) {
4880      case 0x4: {
4881         /* r = ROTL64( rS, rB_lo6) */
4882         r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
4883
4884         if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
4885            DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4886                rA_addr, rS_addr, rB_addr, msk_imm);
4887            // note, ROTL does the masking, so we don't do it here
4888            mask64 = MASK64(0, 63-msk_imm);
4889            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4890            break;
4891         } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
4892            DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4893                rA_addr, rS_addr, rB_addr, msk_imm);
4894            mask64 = MASK64(63-msk_imm, 63);
4895            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4896            break;
4897         }
4898         break;
4899      }
4900      case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
4901         DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4902             rA_addr, rS_addr, sh_imm, msk_imm);
4903         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4904         mask64 = MASK64(sh_imm, 63-msk_imm);
4905         assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4906         break;
4907         // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
4908         /*
4909           Hmm... looks like this'll do the job more simply:
4910           r = SHL(rS, sh_imm)
4911           m = ~(1 << (63-msk_imm))
4912           assign(rA, r & m);
4913         */
4914
4915      case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
4916         if (mode64
4917             && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
4918            /* special-case the ,64-n,n form as that is just
4919               unsigned shift-right by n */
4920            DIP("srdi%s r%u,r%u,%u\n",
4921                flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
4922            assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
4923         } else {
4924            DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4925                rA_addr, rS_addr, sh_imm, msk_imm);
4926            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4927            mask64 = MASK64(0, 63-msk_imm);
4928            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4929         }
4930         break;
4931
4932      case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
4933         if (mode64
4934             && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
4935            /* special-case the ,n,63-n form as that is just
4936               shift-left by n */
4937            DIP("sldi%s r%u,r%u,%u\n",
4938                flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
4939            assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
4940         } else {
4941            DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4942                rA_addr, rS_addr, sh_imm, msk_imm);
4943            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4944            mask64 = MASK64(63-msk_imm, 63);
4945            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4946         }
4947         break;
4948
4949      case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
4950         IRTemp rA_orig = newTemp(ty);
4951         DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4952             rA_addr, rS_addr, sh_imm, msk_imm);
4953         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4954         mask64 = MASK64(sh_imm, 63-msk_imm);
4955         assign( rA_orig, getIReg(rA_addr) );
4956         assign( rA, binop(Iop_Or64,
4957                           binop(Iop_And64, mkU64(mask64),  r),
4958                           binop(Iop_And64, mkU64(~mask64),
4959                                            mkexpr(rA_orig))) );
4960         break;
4961      }
4962      default:
4963         vex_printf("dis_int_rot(ppc)(opc2)\n");
4964         return False;
4965      }
4966      break;
4967   }
4968
4969   default:
4970      vex_printf("dis_int_rot(ppc)(opc1)\n");
4971      return False;
4972   }
4973
4974   putIReg( rA_addr, mkexpr(rA) );
4975
4976   if (flag_rC) {
4977      set_CR0( mkexpr(rA) );
4978   }
4979   return True;
4980}
4981
4982
4983/*
4984  Integer Load Instructions
4985*/
4986static Bool dis_int_load ( UInt theInstr )
4987{
4988   /* D-Form, X-Form, DS-Form */
4989   UChar opc1     = ifieldOPC(theInstr);
4990   UChar rD_addr  = ifieldRegDS(theInstr);
4991   UChar rA_addr  = ifieldRegA(theInstr);
4992   UInt  uimm16   = ifieldUIMM16(theInstr);
4993   UChar rB_addr  = ifieldRegB(theInstr);
4994   UInt  opc2     = ifieldOPClo10(theInstr);
4995   UChar b1       = ifieldBIT1(theInstr);
4996   UChar b0       = ifieldBIT0(theInstr);
4997
4998   Int     simm16 = extend_s_16to32(uimm16);
4999   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
5000   IRTemp  EA     = newTemp(ty);
5001   IRExpr* val;
5002
5003   switch (opc1) {
5004   case 0x1F: // register offset
5005      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5006      break;
5007   case 0x38: // immediate offset: 64bit: lq: maskoff
5008              // lowest 4 bits of immediate before forming EA
5009      simm16 = simm16 & 0xFFFFFFF0;
5010      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5011      break;
5012   case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
5013              // lowest 2 bits of immediate before forming EA
5014      simm16 = simm16 & 0xFFFFFFFC;
5015      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5016      break;
5017   default:   // immediate offset
5018      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5019      break;
5020   }
5021
5022   switch (opc1) {
5023   case 0x22: // lbz (Load B & Zero, PPC32 p433)
5024      DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5025      val = load(Ity_I8, mkexpr(EA));
5026      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5027      break;
5028
5029   case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
5030      if (rA_addr == 0 || rA_addr == rD_addr) {
5031         vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
5032         return False;
5033      }
5034      DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5035      val = load(Ity_I8, mkexpr(EA));
5036      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5037      putIReg( rA_addr, mkexpr(EA) );
5038      break;
5039
5040   case 0x2A: // lha (Load HW Alg, PPC32 p445)
5041      DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5042      val = load(Ity_I16, mkexpr(EA));
5043      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5044      break;
5045
5046   case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
5047      if (rA_addr == 0 || rA_addr == rD_addr) {
5048         vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
5049         return False;
5050      }
5051      DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5052      val = load(Ity_I16, mkexpr(EA));
5053      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5054      putIReg( rA_addr, mkexpr(EA) );
5055      break;
5056
5057   case 0x28: // lhz (Load HW & Zero, PPC32 p450)
5058      DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5059      val = load(Ity_I16, mkexpr(EA));
5060      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5061      break;
5062
5063   case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
5064      if (rA_addr == 0 || rA_addr == rD_addr) {
5065         vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
5066         return False;
5067      }
5068      DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5069      val = load(Ity_I16, mkexpr(EA));
5070      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5071      putIReg( rA_addr, mkexpr(EA) );
5072      break;
5073
5074   case 0x20: // lwz (Load W & Zero, PPC32 p460)
5075      DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5076      val = load(Ity_I32, mkexpr(EA));
5077      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5078      break;
5079
5080   case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
5081      if (rA_addr == 0 || rA_addr == rD_addr) {
5082         vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
5083         return False;
5084      }
5085      DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5086      val = load(Ity_I32, mkexpr(EA));
5087      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5088      putIReg( rA_addr, mkexpr(EA) );
5089      break;
5090
5091   /* X Form */
5092   case 0x1F:
5093      if (b0 != 0) {
5094         vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
5095         return False;
5096      }
5097
5098      switch (opc2) {
5099      case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
5100         DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5101         if (rA_addr == 0 || rA_addr == rD_addr) {
5102            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
5103            return False;
5104         }
5105         val = load(Ity_I8, mkexpr(EA));
5106         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5107         putIReg( rA_addr, mkexpr(EA) );
5108         break;
5109
5110      case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
5111         DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5112         val = load(Ity_I8, mkexpr(EA));
5113         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5114         break;
5115
5116      case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
5117         if (rA_addr == 0 || rA_addr == rD_addr) {
5118            vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
5119            return False;
5120         }
5121         DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5122         val = load(Ity_I16, mkexpr(EA));
5123         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5124         putIReg( rA_addr, mkexpr(EA) );
5125         break;
5126
5127      case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
5128         DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5129         val = load(Ity_I16, mkexpr(EA));
5130         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5131         break;
5132
5133      case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
5134         if (rA_addr == 0 || rA_addr == rD_addr) {
5135            vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
5136            return False;
5137         }
5138         DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5139         val = load(Ity_I16, mkexpr(EA));
5140         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5141         putIReg( rA_addr, mkexpr(EA) );
5142         break;
5143
5144      case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
5145         DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5146         val = load(Ity_I16, mkexpr(EA));
5147         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5148         break;
5149
5150      case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
5151         if (rA_addr == 0 || rA_addr == rD_addr) {
5152            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
5153            return False;
5154         }
5155         DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5156         val = load(Ity_I32, mkexpr(EA));
5157         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5158         putIReg( rA_addr, mkexpr(EA) );
5159         break;
5160
5161      case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
5162         DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5163         val = load(Ity_I32, mkexpr(EA));
5164         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5165         break;
5166
5167
5168      /* 64bit Loads */
5169      case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
5170         if (rA_addr == 0 || rA_addr == rD_addr) {
5171            vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
5172            return False;
5173         }
5174         DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5175         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5176         putIReg( rA_addr, mkexpr(EA) );
5177         break;
5178
5179      case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
5180         DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5181         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5182         break;
5183
5184      case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
5185         if (rA_addr == 0 || rA_addr == rD_addr) {
5186            vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
5187            return False;
5188         }
5189         DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5190         putIReg( rD_addr,
5191                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5192         putIReg( rA_addr, mkexpr(EA) );
5193         break;
5194
5195      case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
5196         DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5197         putIReg( rD_addr,
5198                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5199         break;
5200
5201      default:
5202         vex_printf("dis_int_load(ppc)(opc2)\n");
5203         return False;
5204      }
5205      break;
5206
5207   /* DS Form - 64bit Loads.  In each case EA will have been formed
5208      with the lowest 2 bits masked off the immediate offset. */
5209   case 0x3A:
5210      switch ((b1<<1) | b0) {
5211      case 0x0: // ld (Load DWord, PPC64 p472)
5212         DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5213         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5214         break;
5215
5216      case 0x1: // ldu (Load DWord, Update, PPC64 p474)
5217         if (rA_addr == 0 || rA_addr == rD_addr) {
5218            vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
5219            return False;
5220         }
5221         DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5222         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5223         putIReg( rA_addr, mkexpr(EA) );
5224         break;
5225
5226      case 0x2: // lwa (Load Word Alg, PPC64 p499)
5227         DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5228         putIReg( rD_addr,
5229                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5230         break;
5231
5232      default:
5233         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
5234         return False;
5235      }
5236      break;
5237
5238   case 0x38: {
5239      IRTemp  high = newTemp(ty);
5240      IRTemp  low  = newTemp(ty);
5241      /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
5242      DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5243      /* NOTE: there are some changes to XER[41:42] that have not been
5244       * implemented.
5245       */
5246      // trap if EA misaligned on 16 byte address
5247      if (mode64) {
5248         if (host_endness == VexEndnessBE) {
5249            assign(high, load(ty, mkexpr( EA ) ) );
5250            assign(low, load(ty, binop( Iop_Add64,
5251                                        mkexpr( EA ),
5252                                        mkU64( 8 ) ) ) );
5253	 } else {
5254            assign(low, load(ty, mkexpr( EA ) ) );
5255            assign(high, load(ty, binop( Iop_Add64,
5256                                         mkexpr( EA ),
5257                                         mkU64( 8 ) ) ) );
5258	 }
5259      } else {
5260         assign(high, load(ty, binop( Iop_Add32,
5261                                      mkexpr( EA ),
5262                                      mkU32( 4 ) ) ) );
5263         assign(low, load(ty, binop( Iop_Add32,
5264                                      mkexpr( EA ),
5265                                      mkU32( 12 ) ) ) );
5266      }
5267      gen_SIGBUS_if_misaligned( EA, 16 );
5268      putIReg( rD_addr,  mkexpr( high) );
5269      putIReg( rD_addr+1,  mkexpr( low) );
5270      break;
5271   }
5272   default:
5273      vex_printf("dis_int_load(ppc)(opc1)\n");
5274      return False;
5275   }
5276   return True;
5277}
5278
5279
5280
5281/*
5282  Integer Store Instructions
5283*/
5284static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi )
5285{
5286   /* D-Form, X-Form, DS-Form */
5287   UChar opc1    = ifieldOPC(theInstr);
5288   UInt  rS_addr = ifieldRegDS(theInstr);
5289   UInt  rA_addr = ifieldRegA(theInstr);
5290   UInt  uimm16  = ifieldUIMM16(theInstr);
5291   UInt  rB_addr = ifieldRegB(theInstr);
5292   UInt  opc2    = ifieldOPClo10(theInstr);
5293   UChar b1      = ifieldBIT1(theInstr);
5294   UChar b0      = ifieldBIT0(theInstr);
5295
5296   Int    simm16 = extend_s_16to32(uimm16);
5297   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
5298   IRTemp rS     = newTemp(ty);
5299   IRTemp rB     = newTemp(ty);
5300   IRTemp EA     = newTemp(ty);
5301
5302   assign( rB, getIReg(rB_addr) );
5303   assign( rS, getIReg(rS_addr) );
5304
5305   switch (opc1) {
5306   case 0x1F: // register offset
5307      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5308      break;
5309   case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
5310              // lowest 2 bits of immediate before forming EA
5311      simm16 = simm16 & 0xFFFFFFFC;
5312   default:   // immediate offset
5313      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5314      break;
5315   }
5316
5317   switch (opc1) {
5318   case 0x26: // stb (Store B, PPC32 p509)
5319      DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5320      store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5321      break;
5322
5323   case 0x27: // stbu (Store B, Update, PPC32 p510)
5324      if (rA_addr == 0 ) {
5325         vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
5326         return False;
5327      }
5328      DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5329      putIReg( rA_addr, mkexpr(EA) );
5330      store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5331      break;
5332
5333   case 0x2C: // sth (Store HW, PPC32 p522)
5334      DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5335      store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5336      break;
5337
5338   case 0x2D: // sthu (Store HW, Update, PPC32 p524)
5339      if (rA_addr == 0) {
5340         vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
5341         return False;
5342      }
5343      DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5344      putIReg( rA_addr, mkexpr(EA) );
5345      store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5346      break;
5347
5348   case 0x24: // stw (Store W, PPC32 p530)
5349      DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5350      store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5351      break;
5352
5353   case 0x25: // stwu (Store W, Update, PPC32 p534)
5354      if (rA_addr == 0) {
5355         vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
5356         return False;
5357      }
5358      DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5359      putIReg( rA_addr, mkexpr(EA) );
5360      store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5361      break;
5362
5363   /* X Form : all these use EA_indexed */
5364   case 0x1F:
5365      if (b0 != 0) {
5366         vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
5367         return False;
5368      }
5369
5370      switch (opc2) {
5371      case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
5372         if (rA_addr == 0) {
5373            vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
5374            return False;
5375         }
5376         DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5377         putIReg( rA_addr, mkexpr(EA) );
5378         store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5379         break;
5380
5381      case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
5382         DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5383         store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5384         break;
5385
5386      case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
5387         if (rA_addr == 0) {
5388            vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
5389            return False;
5390         }
5391         DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5392         putIReg( rA_addr, mkexpr(EA) );
5393         store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5394         break;
5395
5396      case 0x197: // sthx (Store HW Indexed, PPC32 p526)
5397         DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5398         store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5399         break;
5400
5401      case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
5402         if (rA_addr == 0) {
5403            vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
5404            return False;
5405         }
5406         DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5407         putIReg( rA_addr, mkexpr(EA) );
5408         store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5409         break;
5410
5411      case 0x097: // stwx (Store W Indexed, PPC32 p536)
5412         DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5413         store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5414         break;
5415
5416
5417      /* 64bit Stores */
5418      case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
5419         if (rA_addr == 0) {
5420            vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
5421            return False;
5422         }
5423         DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5424         putIReg( rA_addr, mkexpr(EA) );
5425         store( mkexpr(EA), mkexpr(rS) );
5426         break;
5427
5428      case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
5429         DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5430         store( mkexpr(EA), mkexpr(rS) );
5431         break;
5432
5433      default:
5434         vex_printf("dis_int_store(ppc)(opc2)\n");
5435         return False;
5436      }
5437      break;
5438
5439   /* DS Form - 64bit Stores.  In each case EA will have been formed
5440      with the lowest 2 bits masked off the immediate offset. */
5441   case 0x3E:
5442      switch ((b1<<1) | b0) {
5443      case 0x0: // std (Store DWord, PPC64 p580)
5444         if (!mode64)
5445            return False;
5446
5447         DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5448         store( mkexpr(EA), mkexpr(rS) );
5449         break;
5450
5451      case 0x1: // stdu (Store DWord, Update, PPC64 p583)
5452         if (!mode64)
5453            return False;
5454
5455         DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5456         putIReg( rA_addr, mkexpr(EA) );
5457         store( mkexpr(EA), mkexpr(rS) );
5458         break;
5459
5460      case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
5461         IRTemp EA_hi = newTemp(ty);
5462         IRTemp EA_lo = newTemp(ty);
5463         DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5464
5465         if (mode64) {
5466            if (host_endness == VexEndnessBE) {
5467
5468               /* upper 64-bits */
5469               assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
5470
5471               /* lower 64-bits */
5472               assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) );
5473	    } else {
5474               /* upper 64-bits */
5475               assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) );
5476
5477               /* lower 64-bits */
5478               assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) );
5479	    }
5480         } else {
5481            /* upper half of upper 64-bits */
5482            assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) );
5483
5484            /* lower half of upper 64-bits */
5485            assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
5486         }
5487         store( mkexpr(EA_hi), mkexpr(rS) );
5488         store( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
5489         break;
5490      }
5491      default:
5492         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
5493         return False;
5494      }
5495      break;
5496
5497   default:
5498      vex_printf("dis_int_store(ppc)(opc1)\n");
5499      return False;
5500   }
5501   return True;
5502}
5503
5504
5505
5506/*
5507  Integer Load/Store Multiple Instructions
5508*/
5509static Bool dis_int_ldst_mult ( UInt theInstr )
5510{
5511   /* D-Form */
5512   UChar opc1     = ifieldOPC(theInstr);
5513   UChar rD_addr  = ifieldRegDS(theInstr);
5514   UChar rS_addr  = rD_addr;
5515   UChar rA_addr  = ifieldRegA(theInstr);
5516   UInt  uimm16   = ifieldUIMM16(theInstr);
5517
5518   Int     simm16 = extend_s_16to32(uimm16);
5519   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
5520   IROp    mkAdd  = mode64 ? Iop_Add64 : Iop_Add32;
5521   IRTemp  EA     = newTemp(ty);
5522   UInt    r      = 0;
5523   UInt    ea_off = 0;
5524   IRExpr* irx_addr;
5525
5526   assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
5527
5528   switch (opc1) {
5529   case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
5530      if (rA_addr >= rD_addr) {
5531         vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
5532         return False;
5533      }
5534      DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5535      for (r = rD_addr; r <= 31; r++) {
5536         irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
5537         putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ),
5538                                       False) );
5539         ea_off += 4;
5540      }
5541      break;
5542
5543   case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
5544      DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5545      for (r = rS_addr; r <= 31; r++) {
5546         irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
5547         store( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
5548         ea_off += 4;
5549      }
5550      break;
5551
5552   default:
5553      vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
5554      return False;
5555   }
5556   return True;
5557}
5558
5559
5560
5561/*
5562  Integer Load/Store String Instructions
5563*/
5564static
5565void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
5566                             IRTemp EA,        // EA
5567                             Int    rD,        // first dst register
5568                             Int    maxBytes ) // 32 or 128
5569{
5570   Int     i, shift = 24;
5571   IRExpr* e_nbytes = mkexpr(tNBytes);
5572   IRExpr* e_EA     = mkexpr(EA);
5573   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
5574
5575   vassert(rD >= 0 && rD < 32);
5576   rD--; if (rD < 0) rD = 31;
5577
5578   for (i = 0; i < maxBytes; i++) {
5579      /* if (nBytes < (i+1)) goto NIA; */
5580      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
5581                         Ijk_Boring,
5582                         mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
5583      /* when crossing into a new dest register, set it to zero. */
5584      if ((i % 4) == 0) {
5585         rD++; if (rD == 32) rD = 0;
5586         putIReg(rD, mkSzImm(ty, 0));
5587         shift = 24;
5588      }
5589      /* rD |=  (8Uto32(*(EA+i))) << shift */
5590      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
5591      putIReg(
5592         rD,
5593         mkWidenFrom32(
5594            ty,
5595            binop(
5596               Iop_Or32,
5597               mkNarrowTo32(ty, getIReg(rD)),
5598               binop(
5599                  Iop_Shl32,
5600                  unop(
5601                     Iop_8Uto32,
5602                     load( Ity_I8,
5603                           binop( mkSzOp(ty,Iop_Add8),
5604                                  e_EA, mkSzImm(ty,i)))
5605                  ),
5606                  mkU8(toUChar(shift))
5607               )
5608            ),
5609            /*Signed*/False
5610	 )
5611      );
5612      shift -= 8;
5613   }
5614}
5615
5616static
5617void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
5618                              IRTemp EA,        // EA
5619                              Int    rS,        // first src register
5620                              Int    maxBytes ) // 32 or 128
5621{
5622   Int     i, shift = 24;
5623   IRExpr* e_nbytes = mkexpr(tNBytes);
5624   IRExpr* e_EA     = mkexpr(EA);
5625   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
5626
5627   vassert(rS >= 0 && rS < 32);
5628   rS--; if (rS < 0) rS = 31;
5629
5630   for (i = 0; i < maxBytes; i++) {
5631      /* if (nBytes < (i+1)) goto NIA; */
5632      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
5633                         Ijk_Boring,
5634                         mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
5635      /* check for crossing into a new src register. */
5636      if ((i % 4) == 0) {
5637         rS++; if (rS == 32) rS = 0;
5638         shift = 24;
5639      }
5640      /* *(EA+i) = 32to8(rS >> shift) */
5641      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
5642      store(
5643            binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
5644            unop( Iop_32to8,
5645                  binop( Iop_Shr32,
5646                         mkNarrowTo32( ty, getIReg(rS) ),
5647                         mkU8( toUChar(shift) )))
5648      );
5649      shift -= 8;
5650   }
5651}
5652
5653static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
5654{
5655   /* X-Form */
5656   UChar opc1     = ifieldOPC(theInstr);
5657   UChar rD_addr  = ifieldRegDS(theInstr);
5658   UChar rS_addr  = rD_addr;
5659   UChar rA_addr  = ifieldRegA(theInstr);
5660   UChar rB_addr  = ifieldRegB(theInstr);
5661   UChar NumBytes = rB_addr;
5662   UInt  opc2     = ifieldOPClo10(theInstr);
5663   UChar b0       = ifieldBIT0(theInstr);
5664
5665   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5666   IRTemp t_EA    = newTemp(ty);
5667   IRTemp t_nbytes = IRTemp_INVALID;
5668
5669   *stopHere = False;
5670
5671   if (opc1 != 0x1F || b0 != 0) {
5672      vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
5673      return False;
5674   }
5675
5676   switch (opc2) {
5677   case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
5678      /* NB: does not reject the case where RA is in the range of
5679         registers to be loaded.  It should. */
5680      DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
5681      assign( t_EA, ea_rAor0(rA_addr) );
5682      if (NumBytes == 8 && !mode64) {
5683         /* Special case hack */
5684         /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
5685         putIReg( rD_addr,
5686                  load(Ity_I32, mkexpr(t_EA)) );
5687         putIReg( (rD_addr+1) % 32,
5688                  load(Ity_I32,
5689                       binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
5690      } else {
5691         t_nbytes = newTemp(Ity_I32);
5692         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5693         generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5694         *stopHere = True;
5695      }
5696      return True;
5697
5698   case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
5699      /* NB: does not reject the case where RA is in the range of
5700         registers to be loaded.  It should.  Although considering
5701         that that can only be detected at run time, it's not easy to
5702         do so. */
5703      if (rD_addr == rA_addr || rD_addr == rB_addr)
5704         return False;
5705      if (rD_addr == 0 && rA_addr == 0)
5706         return False;
5707      DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5708      t_nbytes = newTemp(Ity_I32);
5709      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5710      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5711      generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
5712      *stopHere = True;
5713      return True;
5714
5715   case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
5716      DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
5717      assign( t_EA, ea_rAor0(rA_addr) );
5718      if (NumBytes == 8 && !mode64) {
5719         /* Special case hack */
5720         /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
5721         store( mkexpr(t_EA),
5722                getIReg(rD_addr) );
5723         store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
5724                getIReg((rD_addr+1) % 32) );
5725      } else {
5726         t_nbytes = newTemp(Ity_I32);
5727         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5728         generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5729         *stopHere = True;
5730      }
5731      return True;
5732
5733   case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
5734      DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5735      t_nbytes = newTemp(Ity_I32);
5736      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5737      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5738      generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
5739      *stopHere = True;
5740      return True;
5741
5742   default:
5743      vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
5744      return False;
5745   }
5746   return True;
5747}
5748
5749
5750/* ------------------------------------------------------------------
5751   Integer Branch Instructions
5752   ------------------------------------------------------------------ */
5753
5754/*
5755  Branch helper function
5756  ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
5757  Returns an I32 which is 0x00000000 if the ctr condition failed
5758  and 0xFFFFFFFF otherwise.
5759*/
5760static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
5761{
5762   IRType ty = mode64 ? Ity_I64 : Ity_I32;
5763   IRTemp ok = newTemp(Ity_I32);
5764
5765   if ((BO >> 2) & 1) {     // independent of ctr
5766      assign( ok, mkU32(0xFFFFFFFF) );
5767   } else {
5768      if ((BO >> 1) & 1) {  // ctr == 0 ?
5769         assign( ok, unop( Iop_1Sto32,
5770                           binop( mkSzOp(ty, Iop_CmpEQ8),
5771                                  getGST( PPC_GST_CTR ),
5772                                  mkSzImm(ty,0))) );
5773      } else {              // ctr != 0 ?
5774         assign( ok, unop( Iop_1Sto32,
5775                           binop( mkSzOp(ty, Iop_CmpNE8),
5776                                  getGST( PPC_GST_CTR ),
5777                                  mkSzImm(ty,0))) );
5778      }
5779   }
5780   return mkexpr(ok);
5781}
5782
5783
5784/*
5785  Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
5786  Returns an I32 which is either 0 if the condition failed or
5787  some arbitrary nonzero value otherwise. */
5788
5789static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
5790{
5791   Int where;
5792   IRTemp res   = newTemp(Ity_I32);
5793   IRTemp cr_bi = newTemp(Ity_I32);
5794
5795   if ((BO >> 4) & 1) {
5796      assign( res, mkU32(1) );
5797   } else {
5798      // ok = (CR[BI] == BO[3]) Note, the following relies on
5799      // getCRbit_anywhere returning a value which
5800      // is either zero or has exactly 1 bit set.
5801      assign( cr_bi, getCRbit_anywhere( BI, &where ) );
5802
5803      if ((BO >> 3) & 1) {
5804         /* We can use cr_bi as-is. */
5805         assign( res, mkexpr(cr_bi) );
5806      } else {
5807         /* We have to invert the sense of the information held in
5808            cr_bi.  For that we need to know which bit
5809            getCRbit_anywhere regards as significant. */
5810         assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
5811                                       mkU32(1<<where)) );
5812      }
5813   }
5814   return mkexpr(res);
5815}
5816
5817
5818/*
5819  Integer Branch Instructions
5820*/
5821static Bool dis_branch ( UInt theInstr,
5822                         const VexAbiInfo* vbi,
5823                         /*OUT*/DisResult* dres,
5824                         Bool (*resteerOkFn)(void*,Addr),
5825                         void* callback_opaque )
5826{
5827   UChar opc1    = ifieldOPC(theInstr);
5828   UChar BO      = ifieldRegDS(theInstr);
5829   UChar BI      = ifieldRegA(theInstr);
5830   UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
5831   UChar b11to15 = ifieldRegB(theInstr);
5832   UInt  opc2    = ifieldOPClo10(theInstr);
5833   UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
5834   UChar flag_AA = ifieldBIT1(theInstr);
5835   UChar flag_LK = ifieldBIT0(theInstr);
5836
5837   IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
5838   Addr64   tgt       = 0;
5839   UInt     BD        = extend_s_16to32(BD_u16);
5840   IRTemp   do_branch = newTemp(Ity_I32);
5841   IRTemp   ctr_ok    = newTemp(Ity_I32);
5842   IRTemp   cond_ok   = newTemp(Ity_I32);
5843   IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
5844   IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
5845   IRTemp   lr_old    = newTemp(ty);
5846
5847   /* Hack to pass through code that just wants to read the PC */
5848   if (theInstr == 0x429F0005) {
5849      DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
5850      putGST( PPC_GST_LR, e_nia );
5851      return True;
5852   }
5853
5854   /* The default what-next.  Individual cases can override it. */
5855   dres->whatNext = Dis_StopHere;
5856   vassert(dres->jk_StopHere == Ijk_INVALID);
5857
5858   switch (opc1) {
5859   case 0x12: // b     (Branch, PPC32 p360)
5860      if (flag_AA) {
5861         tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
5862      } else {
5863         tgt = mkSzAddr( ty, guest_CIA_curr_instr +
5864                             (Long)extend_s_26to64(LI_u26) );
5865      }
5866      if (mode64) {
5867         DIP("b%s%s 0x%llx\n",
5868             flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
5869      } else {
5870         DIP("b%s%s 0x%x\n",
5871             flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
5872      }
5873
5874      if (flag_LK) {
5875         putGST( PPC_GST_LR, e_nia );
5876         if (vbi->guest_ppc_zap_RZ_at_bl
5877             && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
5878            IRTemp t_tgt = newTemp(ty);
5879            assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
5880            make_redzone_AbiHint( vbi, t_tgt,
5881                                  "branch-and-link (unconditional call)" );
5882         }
5883      }
5884
5885      if (resteerOkFn( callback_opaque, tgt )) {
5886         dres->whatNext   = Dis_ResteerU;
5887         dres->continueAt = tgt;
5888      } else {
5889         dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
5890         putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
5891      }
5892      break;
5893
5894   case 0x10: // bc    (Branch Conditional, PPC32 p361)
5895      DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
5896          flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
5897
5898      if (!(BO & 0x4)) {
5899         putGST( PPC_GST_CTR,
5900                 binop(mkSzOp(ty, Iop_Sub8),
5901                       getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5902      }
5903
5904      /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
5905         cond_ok is either zero or nonzero, since that's the cheapest
5906         way to compute it.  Anding them together gives a value which
5907         is either zero or non zero and so that's what we must test
5908         for in the IRStmt_Exit. */
5909      assign( ctr_ok,  branch_ctr_ok( BO ) );
5910      assign( cond_ok, branch_cond_ok( BO, BI ) );
5911      assign( do_branch,
5912              binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5913
5914      if (flag_AA) {
5915         tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
5916      } else {
5917         tgt = mkSzAddr(ty, guest_CIA_curr_instr +
5918                            (Long)extend_s_16to64(BD_u16));
5919      }
5920      if (flag_LK)
5921         putGST( PPC_GST_LR, e_nia );
5922
5923      stmt( IRStmt_Exit(
5924               binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
5925               flag_LK ? Ijk_Call : Ijk_Boring,
5926               mkSzConst(ty, tgt), OFFB_CIA ) );
5927
5928      dres->jk_StopHere = Ijk_Boring;
5929      putGST( PPC_GST_CIA, e_nia );
5930      break;
5931
5932   case 0x13:
5933      /* For bclr and bcctr, it appears that the lowest two bits of
5934         b11to15 are a branch hint, and so we only need to ensure it's
5935         of the form 000XX. */
5936      if ((b11to15 & ~3) != 0) {
5937         vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15);
5938         return False;
5939      }
5940
5941      switch (opc2) {
5942      case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
5943         if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
5944            vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
5945            return False;
5946         }
5947         DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5948
5949         assign( cond_ok, branch_cond_ok( BO, BI ) );
5950
5951         /* FIXME: this is confusing.  lr_old holds the old value
5952            of ctr, not lr :-) */
5953         assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
5954
5955         if (flag_LK)
5956            putGST( PPC_GST_LR, e_nia );
5957
5958         stmt( IRStmt_Exit(
5959                  binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
5960                  Ijk_Boring,
5961                  c_nia, OFFB_CIA ));
5962
5963         if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
5964            make_redzone_AbiHint( vbi, lr_old,
5965                                  "b-ctr-l (indirect call)" );
5966	 }
5967
5968         dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
5969         putGST( PPC_GST_CIA, mkexpr(lr_old) );
5970         break;
5971
5972      case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
5973         Bool vanilla_return = False;
5974         if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
5975            DIP("blr\n");
5976            vanilla_return = True;
5977         } else {
5978            DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5979         }
5980
5981         if (!(BO & 0x4)) {
5982            putGST( PPC_GST_CTR,
5983                    binop(mkSzOp(ty, Iop_Sub8),
5984                          getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5985         }
5986
5987         /* See comments above for 'bc' about this */
5988         assign( ctr_ok,  branch_ctr_ok( BO ) );
5989         assign( cond_ok, branch_cond_ok( BO, BI ) );
5990         assign( do_branch,
5991                 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5992
5993         assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
5994
5995         if (flag_LK)
5996            putGST( PPC_GST_LR,  e_nia );
5997
5998         stmt( IRStmt_Exit(
5999                  binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
6000                  Ijk_Boring,
6001                  c_nia, OFFB_CIA ));
6002
6003         if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
6004            make_redzone_AbiHint( vbi, lr_old,
6005                                  "branch-to-lr (unconditional return)" );
6006         }
6007
6008         /* blrl is pretty strange; it's like a return that sets the
6009            return address of its caller to the insn following this
6010            one.  Mark it as a return. */
6011         dres->jk_StopHere = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
6012         putGST( PPC_GST_CIA, mkexpr(lr_old) );
6013         break;
6014      }
6015      default:
6016         vex_printf("dis_int_branch(ppc)(opc2)\n");
6017         return False;
6018      }
6019      break;
6020
6021   default:
6022      vex_printf("dis_int_branch(ppc)(opc1)\n");
6023      return False;
6024   }
6025
6026   return True;
6027}
6028
6029
6030
6031/*
6032  Condition Register Logical Instructions
6033*/
6034static Bool dis_cond_logic ( UInt theInstr )
6035{
6036   /* XL-Form */
6037   UChar opc1      = ifieldOPC(theInstr);
6038   UChar crbD_addr = ifieldRegDS(theInstr);
6039   UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
6040   UChar crbA_addr = ifieldRegA(theInstr);
6041   UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
6042   UChar crbB_addr = ifieldRegB(theInstr);
6043   UInt  opc2      = ifieldOPClo10(theInstr);
6044   UChar b0        = ifieldBIT0(theInstr);
6045
6046   IRTemp crbD     = newTemp(Ity_I32);
6047   IRTemp crbA     = newTemp(Ity_I32);
6048   IRTemp crbB     = newTemp(Ity_I32);
6049
6050   if (opc1 != 19 || b0 != 0) {
6051      vex_printf("dis_cond_logic(ppc)(opc1)\n");
6052      return False;
6053   }
6054
6055   if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
6056      if (((crbD_addr & 0x3) != 0) ||
6057          ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
6058         vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
6059         return False;
6060      }
6061      DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
6062      putCR0(   crfD_addr, getCR0(  crfS_addr) );
6063      putCR321( crfD_addr, getCR321(crfS_addr) );
6064   } else {
6065      assign( crbA, getCRbit(crbA_addr) );
6066      if (crbA_addr == crbB_addr)
6067         crbB = crbA;
6068      else
6069         assign( crbB, getCRbit(crbB_addr) );
6070
6071      switch (opc2) {
6072      case 0x101: // crand   (Cond Reg AND, PPC32 p372)
6073         DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6074         assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
6075         break;
6076      case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
6077         DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6078         assign( crbD, binop(Iop_And32,
6079                             mkexpr(crbA),
6080                             unop(Iop_Not32, mkexpr(crbB))) );
6081         break;
6082      case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
6083         DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6084         assign( crbD, unop(Iop_Not32,
6085                            binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
6086         break;
6087      case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
6088         DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6089         assign( crbD, unop(Iop_Not32,
6090                            binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
6091         break;
6092      case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
6093         DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6094         assign( crbD, unop(Iop_Not32,
6095                            binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
6096         break;
6097      case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
6098         DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6099         assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
6100         break;
6101      case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
6102         DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6103         assign( crbD, binop(Iop_Or32,
6104                             mkexpr(crbA),
6105                             unop(Iop_Not32, mkexpr(crbB))) );
6106         break;
6107      case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
6108         DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6109         assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
6110         break;
6111      default:
6112         vex_printf("dis_cond_logic(ppc)(opc2)\n");
6113         return False;
6114      }
6115
6116      putCRbit( crbD_addr, mkexpr(crbD) );
6117   }
6118   return True;
6119}
6120
6121
6122/*
6123  Trap instructions
6124*/
6125
6126/* Do the code generation for a trap.  Returned Bool is true iff
6127   this is an unconditional trap.  If the two arg IRExpr*s are
6128   Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
6129   then they are 64-bit, and we must be disassembling 64-bit
6130   instructions. */
6131static Bool do_trap ( UChar TO,
6132                      IRExpr* argL0, IRExpr* argR0, Addr64 cia )
6133{
6134   IRTemp argL, argR;
6135   IRExpr *argLe, *argRe, *cond, *tmp;
6136
6137   Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
6138
6139   IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
6140   IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
6141   IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
6142   IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
6143   IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
6144   IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
6145   IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
6146   IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
6147   IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
6148   IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
6149
6150   const UChar b11100 = 0x1C;
6151   const UChar b00111 = 0x07;
6152
6153   if (is32bit) {
6154      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
6155      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
6156   } else {
6157      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
6158      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
6159      vassert( mode64 );
6160   }
6161
6162   if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
6163      /* Unconditional trap.  Just do the exit without
6164         testing the arguments. */
6165      stmt( IRStmt_Exit(
6166               binop(opCMPEQ, const0, const0),
6167               Ijk_SigTRAP,
6168               mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
6169               OFFB_CIA
6170      ));
6171      return True; /* unconditional trap */
6172   }
6173
6174   if (is32bit) {
6175      argL = newTemp(Ity_I32);
6176      argR = newTemp(Ity_I32);
6177   } else {
6178      argL = newTemp(Ity_I64);
6179      argR = newTemp(Ity_I64);
6180   }
6181
6182   assign( argL, argL0 );
6183   assign( argR, argR0 );
6184
6185   argLe = mkexpr(argL);
6186   argRe = mkexpr(argR);
6187
6188   cond = const0;
6189   if (TO & 16) { // L <s R
6190      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
6191      cond = binop(opOR, tmp, cond);
6192   }
6193   if (TO & 8) { // L >s R
6194      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
6195      cond = binop(opOR, tmp, cond);
6196   }
6197   if (TO & 4) { // L == R
6198      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
6199      cond = binop(opOR, tmp, cond);
6200   }
6201   if (TO & 2) { // L <u R
6202      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
6203      cond = binop(opOR, tmp, cond);
6204   }
6205   if (TO & 1) { // L >u R
6206      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
6207      cond = binop(opOR, tmp, cond);
6208   }
6209   stmt( IRStmt_Exit(
6210            binop(opCMPNE, cond, const0),
6211            Ijk_SigTRAP,
6212            mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
6213            OFFB_CIA
6214   ));
6215   return False; /* not an unconditional trap */
6216}
6217
6218static Bool dis_trapi ( UInt theInstr,
6219                        /*OUT*/DisResult* dres )
6220{
6221   /* D-Form */
6222   UChar  opc1    = ifieldOPC(theInstr);
6223   UChar  TO      = ifieldRegDS(theInstr);
6224   UChar  rA_addr = ifieldRegA(theInstr);
6225   UInt   uimm16  = ifieldUIMM16(theInstr);
6226   ULong  simm16  = extend_s_16to64(uimm16);
6227   Addr64 cia     = guest_CIA_curr_instr;
6228   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
6229   Bool   uncond  = False;
6230
6231   switch (opc1) {
6232   case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
6233      uncond = do_trap( TO,
6234                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
6235                               : getIReg(rA_addr),
6236                        mkU32( (UInt)simm16 ),
6237                        cia );
6238      if (TO == 4) {
6239         DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16);
6240      } else {
6241         DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16);
6242      }
6243      break;
6244   case 0x02: // tdi
6245      if (!mode64)
6246         return False;
6247      uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
6248      if (TO == 4) {
6249         DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16);
6250      } else {
6251         DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16);
6252      }
6253      break;
6254   default:
6255      return False;
6256   }
6257
6258   if (uncond) {
6259      /* If the trap shows signs of being unconditional, don't
6260         continue decoding past it. */
6261      putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6262      dres->jk_StopHere = Ijk_Boring;
6263      dres->whatNext    = Dis_StopHere;
6264   }
6265
6266   return True;
6267}
6268
6269static Bool dis_trap ( UInt theInstr,
6270                        /*OUT*/DisResult* dres )
6271{
6272   /* X-Form */
6273   UInt   opc2    = ifieldOPClo10(theInstr);
6274   UChar  TO      = ifieldRegDS(theInstr);
6275   UChar  rA_addr = ifieldRegA(theInstr);
6276   UChar  rB_addr = ifieldRegB(theInstr);
6277   Addr64 cia     = guest_CIA_curr_instr;
6278   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
6279   Bool   uncond  = False;
6280
6281   if (ifieldBIT0(theInstr) != 0)
6282      return False;
6283
6284   switch (opc2) {
6285   case 0x004: // tw  (Trap Word, PPC64 p540)
6286      uncond = do_trap( TO,
6287                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
6288                               : getIReg(rA_addr),
6289                        mode64 ? unop(Iop_64to32, getIReg(rB_addr))
6290                               : getIReg(rB_addr),
6291                        cia );
6292      if (TO == 4) {
6293         DIP("tweq r%u,r%u\n", rA_addr, rB_addr);
6294      } else {
6295         DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr);
6296      }
6297      break;
6298   case 0x044: // td (Trap Doubleword, PPC64 p534)
6299      if (!mode64)
6300         return False;
6301      uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
6302      if (TO == 4) {
6303         DIP("tdeq r%u,r%u\n", rA_addr, rB_addr);
6304      } else {
6305         DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr);
6306      }
6307      break;
6308   default:
6309      return False;
6310   }
6311
6312   if (uncond) {
6313      /* If the trap shows signs of being unconditional, don't
6314         continue decoding past it. */
6315      putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6316      dres->jk_StopHere = Ijk_Boring;
6317      dres->whatNext    = Dis_StopHere;
6318   }
6319
6320   return True;
6321}
6322
6323
6324/*
6325  System Linkage Instructions
6326*/
6327static Bool dis_syslink ( UInt theInstr,
6328                          const VexAbiInfo* abiinfo, DisResult* dres )
6329{
6330   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6331
6332   if (theInstr != 0x44000002) {
6333      vex_printf("dis_syslink(ppc)(theInstr)\n");
6334      return False;
6335   }
6336
6337   // sc  (System Call, PPC32 p504)
6338   DIP("sc\n");
6339
6340   /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
6341      Valgrind can back the guest up to this instruction if it needs
6342      to restart the syscall. */
6343   putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
6344
6345   /* It's important that all ArchRegs carry their up-to-date value
6346      at this point.  So we declare an end-of-block here, which
6347      forces any TempRegs caching ArchRegs to be flushed. */
6348   putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6349
6350   dres->whatNext    = Dis_StopHere;
6351   dres->jk_StopHere = Ijk_Sys_syscall;
6352   return True;
6353}
6354
6355
6356/*
6357  Memory Synchronization Instructions
6358
6359  Note on Reservations:
6360  We rely on the assumption that V will in fact only allow one thread at
6361  once to run.  In effect, a thread can make a reservation, but we don't
6362  check any stores it does.  Instead, the reservation is cancelled when
6363  the scheduler switches to another thread (run_thread_for_a_while()).
6364*/
6365static Bool dis_memsync ( UInt theInstr )
6366{
6367   /* X-Form, XL-Form */
6368   UChar opc1    = ifieldOPC(theInstr);
6369   UInt  b11to25 = IFIELD(theInstr, 11, 15);
6370   UChar flag_L  = ifieldRegDS(theInstr);
6371   UInt  b11to20 = IFIELD(theInstr, 11, 10);
6372   UInt  M0      = IFIELD(theInstr, 11, 5);
6373   UChar rD_addr = ifieldRegDS(theInstr);
6374   UChar rS_addr = rD_addr;
6375   UChar rA_addr = ifieldRegA(theInstr);
6376   UChar rB_addr = ifieldRegB(theInstr);
6377   UInt  opc2    = ifieldOPClo10(theInstr);
6378   UChar b0      = ifieldBIT0(theInstr);
6379
6380   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6381   IRTemp EA     = newTemp(ty);
6382
6383   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6384
6385   switch (opc1) {
6386   /* XL-Form */
6387   case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
6388      if (opc2 != 0x096) {
6389         vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
6390         return False;
6391      }
6392      if (b11to25 != 0 || b0 != 0) {
6393         vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
6394         return False;
6395      }
6396      DIP("isync\n");
6397      stmt( IRStmt_MBE(Imbe_Fence) );
6398      break;
6399
6400   /* X-Form */
6401   case 0x1F:
6402      switch (opc2) {
6403      case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394)
6404         if (M0 == 0) {
6405            if (b11to20 != 0 || b0 != 0) {
6406               vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n");
6407               return False;
6408            }
6409            DIP("eieio\n");
6410         } else {
6411            if (b11to20 != 0 || b0 != 0) {
6412               vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n");
6413               return False;
6414            }
6415            DIP("mbar %d\n", M0);
6416         }
6417         /* Insert a memory fence, just to be on the safe side. */
6418         stmt( IRStmt_MBE(Imbe_Fence) );
6419         break;
6420
6421      case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
6422         IRTemp res;
6423         /* According to the PowerPC ISA version 2.05, b0 (called EH
6424            in the documentation) is merely a hint bit to the
6425            hardware, I think as to whether or not contention is
6426            likely.  So we can just ignore it. */
6427         DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6428
6429         // trap if misaligned
6430         gen_SIGBUS_if_misaligned( EA, 4 );
6431
6432         // and actually do the load
6433         res = newTemp(Ity_I32);
6434         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6435
6436         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
6437         break;
6438      }
6439
6440      case 0x034: { // lbarx (Load Word and Reserve Indexed)
6441         IRTemp res;
6442         /* According to the PowerPC ISA version 2.05, b0 (called EH
6443            in the documentation) is merely a hint bit to the
6444            hardware, I think as to whether or not contention is
6445            likely.  So we can just ignore it. */
6446         DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6447
6448         // and actually do the load
6449         res = newTemp(Ity_I8);
6450         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6451
6452         putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) );
6453         break;
6454     }
6455
6456      case 0x074: { // lharx (Load Word and Reserve Indexed)
6457         IRTemp res;
6458         /* According to the PowerPC ISA version 2.05, b0 (called EH
6459            in the documentation) is merely a hint bit to the
6460            hardware, I think as to whether or not contention is
6461            likely.  So we can just ignore it. */
6462         DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6463
6464         // trap if misaligned
6465         gen_SIGBUS_if_misaligned( EA, 2 );
6466
6467         // and actually do the load
6468         res = newTemp(Ity_I16);
6469         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6470
6471         putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) );
6472         break;
6473      }
6474
6475      case 0x096: {
6476         // stwcx. (Store Word Conditional Indexed, PPC32 p532)
6477         // Note this has to handle stwcx. in both 32- and 64-bit modes,
6478         // so isn't quite as straightforward as it might otherwise be.
6479         IRTemp rS = newTemp(Ity_I32);
6480         IRTemp resSC;
6481         if (b0 != 1) {
6482            vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
6483            return False;
6484         }
6485         DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6486
6487         // trap if misaligned
6488         gen_SIGBUS_if_misaligned( EA, 4 );
6489
6490         // Get the data to be stored, and narrow to 32 bits if necessary
6491         assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
6492
6493         // Do the store, and get success/failure bit into resSC
6494         resSC = newTemp(Ity_I1);
6495         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6496
6497         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6498         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6499         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6500         putCR0(0, getXER_SO());
6501
6502         /* Note:
6503            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6504            whether rS is stored is dependent on that value. */
6505         /* So I guess we can just ignore this case? */
6506         break;
6507      }
6508
6509      case 0x2B6: {
6510         // stbcx. (Store Byte Conditional Indexed)
6511         // Note this has to handle stbcx. in both 32- and 64-bit modes,
6512         // so isn't quite as straightforward as it might otherwise be.
6513         IRTemp rS = newTemp(Ity_I8);
6514         IRTemp resSC;
6515         if (b0 != 1) {
6516            vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
6517            return False;
6518         }
6519         DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6520
6521         // Get the data to be stored, and narrow to 32 bits if necessary
6522         assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) );
6523
6524         // Do the store, and get success/failure bit into resSC
6525         resSC = newTemp(Ity_I1);
6526         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6527
6528         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6529         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6530         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6531         putCR0(0, getXER_SO());
6532
6533         /* Note:
6534            If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and
6535            whether rS is stored is dependent on that value. */
6536         /* So I guess we can just ignore this case? */
6537         break;
6538      }
6539
6540      case 0x2D6: {
6541         // sthcx. (Store Word Conditional Indexed, PPC32 p532)
6542         // Note this has to handle sthcx. in both 32- and 64-bit modes,
6543         // so isn't quite as straightforward as it might otherwise be.
6544         IRTemp rS = newTemp(Ity_I16);
6545         IRTemp resSC;
6546         if (b0 != 1) {
6547            vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
6548            return False;
6549         }
6550         DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6551
6552         // trap if misaligned
6553         gen_SIGBUS_if_misaligned( EA, 2 );
6554
6555         // Get the data to be stored, and narrow to 16 bits if necessary
6556         assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) );
6557
6558         // Do the store, and get success/failure bit into resSC
6559         resSC = newTemp(Ity_I1);
6560         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6561
6562         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6563         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6564         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6565         putCR0(0, getXER_SO());
6566
6567         /* Note:
6568            If resaddr != lharx_resaddr, CR0[EQ] is undefined, and
6569            whether rS is stored is dependent on that value. */
6570         /* So I guess we can just ignore this case? */
6571         break;
6572      }
6573
6574      case 0x256: // sync (Synchronize, PPC32 p543),
6575                  // also lwsync (L==1), ptesync (L==2)
6576         /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
6577
6578            The PowerPC architecture used in IBM chips has expanded
6579            the sync instruction into two variants: lightweight sync
6580            and heavyweight sync.  The original sync instruction is
6581            the new heavyweight sync and lightweight sync is a strict
6582            subset of the heavyweight sync functionality. This allows
6583            the programmer to specify a less expensive operation on
6584            high-end systems when the full sync functionality is not
6585            necessary.
6586
6587            The basic "sync" mnemonic now utilizes an operand. "sync"
6588            without an operand now becomes a extended mnemonic for
6589            heavyweight sync.  Processors without the lwsync
6590            instruction will not decode the L field and will perform a
6591            heavyweight sync.  Everything is backward compatible.
6592
6593            sync    =       sync 0
6594            lwsync  =       sync 1
6595            ptesync =       sync 2    *** TODO - not implemented ***
6596         */
6597         if (b11to20 != 0 || b0 != 0) {
6598            vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
6599            return False;
6600         }
6601         if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
6602            vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
6603            return False;
6604         }
6605         DIP("%ssync\n", flag_L == 1 ? "lw" : "");
6606         /* Insert a memory fence.  It's sometimes important that these
6607            are carried through to the generated code. */
6608         stmt( IRStmt_MBE(Imbe_Fence) );
6609         break;
6610
6611      /* 64bit Memsync */
6612      case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
6613         IRTemp res;
6614         /* According to the PowerPC ISA version 2.05, b0 (called EH
6615            in the documentation) is merely a hint bit to the
6616            hardware, I think as to whether or not contention is
6617            likely.  So we can just ignore it. */
6618         if (!mode64)
6619            return False;
6620         DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6621
6622         // trap if misaligned
6623         gen_SIGBUS_if_misaligned( EA, 8 );
6624
6625         // and actually do the load
6626         res = newTemp(Ity_I64);
6627         stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) );
6628
6629         putIReg( rD_addr, mkexpr(res) );
6630         break;
6631      }
6632
6633      case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
6634         // A marginally simplified version of the stwcx. case
6635         IRTemp rS = newTemp(Ity_I64);
6636         IRTemp resSC;
6637         if (b0 != 1) {
6638            vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
6639            return False;
6640         }
6641         if (!mode64)
6642            return False;
6643         DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6644
6645         // trap if misaligned
6646         gen_SIGBUS_if_misaligned( EA, 8 );
6647
6648         // Get the data to be stored
6649         assign( rS, getIReg(rS_addr) );
6650
6651         // Do the store, and get success/failure bit into resSC
6652         resSC = newTemp(Ity_I1);
6653         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6654
6655         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6656         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6657         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6658         putCR0(0, getXER_SO());
6659
6660         /* Note:
6661            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6662            whether rS is stored is dependent on that value. */
6663         /* So I guess we can just ignore this case? */
6664         break;
6665      }
6666
6667      /* 128bit Memsync */
6668      case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
6669         IRTemp res_hi = newTemp(ty);
6670         IRTemp res_lo = newTemp(ty);
6671
6672         /* According to the PowerPC ISA version 2.07, b0 (called EH
6673            in the documentation) is merely a hint bit to the
6674            hardware, I think as to whether or not contention is
6675            likely.  So we can just ignore it. */
6676         DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6677
6678         // trap if misaligned
6679         gen_SIGBUS_if_misaligned( EA, 16 );
6680
6681         // and actually do the load
6682         if (mode64) {
6683            if (host_endness == VexEndnessBE) {
6684               stmt( stmt_load( res_hi,
6685                                mkexpr(EA), NULL/*this is a load*/) );
6686               stmt( stmt_load( res_lo,
6687                                binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
6688                                NULL/*this is a load*/) );
6689	    } else {
6690               stmt( stmt_load( res_lo,
6691                                mkexpr(EA), NULL/*this is a load*/) );
6692               stmt( stmt_load( res_hi,
6693                                binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
6694                                NULL/*this is a load*/) );
6695            }
6696         } else {
6697            stmt( stmt_load( res_hi,
6698                             binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
6699                             NULL/*this is a load*/) );
6700            stmt( stmt_load( res_lo,
6701                             binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
6702                             NULL/*this is a load*/) );
6703         }
6704         putIReg( rD_addr,   mkexpr(res_hi) );
6705         putIReg( rD_addr+1, mkexpr(res_lo) );
6706         break;
6707      }
6708
6709      case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
6710         // A marginally simplified version of the stwcx. case
6711         IRTemp rS_hi = newTemp(ty);
6712         IRTemp rS_lo = newTemp(ty);
6713         IRTemp resSC;
6714         if (b0 != 1) {
6715            vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
6716            return False;
6717         }
6718
6719         DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6720
6721         // trap if misaligned
6722         gen_SIGBUS_if_misaligned( EA, 16 );
6723         // Get the data to be stored
6724         assign( rS_hi, getIReg(rS_addr) );
6725         assign( rS_lo, getIReg(rS_addr+1) );
6726
6727         // Do the store, and get success/failure bit into resSC
6728         resSC = newTemp(Ity_I1);
6729
6730         if (mode64) {
6731            if (host_endness == VexEndnessBE) {
6732               stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) );
6733               store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
6734                      mkexpr(rS_lo) );
6735	    } else {
6736               stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) );
6737               store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
6738                      mkexpr(rS_hi) );
6739	    }
6740         } else {
6741            stmt( stmt_load( resSC, binop( Iop_Add32,
6742                                           mkexpr(EA),
6743                                           mkU32(4) ),
6744                                           mkexpr(rS_hi) ) );
6745            store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
6746         }
6747
6748         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6749         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6750         putCR321(0, binop( Iop_Shl8,
6751                            unop(Iop_1Uto8, mkexpr(resSC) ),
6752                            mkU8(1)));
6753         putCR0(0, getXER_SO());
6754         break;
6755      }
6756
6757      default:
6758         vex_printf("dis_memsync(ppc)(opc2)\n");
6759         return False;
6760      }
6761      break;
6762
6763   default:
6764      vex_printf("dis_memsync(ppc)(opc1)\n");
6765      return False;
6766   }
6767   return True;
6768}
6769
6770
6771
6772/*
6773  Integer Shift Instructions
6774*/
6775static Bool dis_int_shift ( UInt theInstr )
6776{
6777   /* X-Form, XS-Form */
6778   UChar opc1    = ifieldOPC(theInstr);
6779   UChar rS_addr = ifieldRegDS(theInstr);
6780   UChar rA_addr = ifieldRegA(theInstr);
6781   UChar rB_addr = ifieldRegB(theInstr);
6782   UChar sh_imm  = rB_addr;
6783   UInt  opc2    = ifieldOPClo10(theInstr);
6784   UChar b1      = ifieldBIT1(theInstr);
6785   UChar flag_rC = ifieldBIT0(theInstr);
6786
6787   IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
6788   IRTemp  rA         = newTemp(ty);
6789   IRTemp  rS         = newTemp(ty);
6790   IRTemp  rB         = newTemp(ty);
6791   IRTemp  outofrange = newTemp(Ity_I1);
6792   IRTemp  rS_lo32    = newTemp(Ity_I32);
6793   IRTemp  rB_lo32    = newTemp(Ity_I32);
6794   IRExpr* e_tmp;
6795
6796   assign( rS, getIReg(rS_addr) );
6797   assign( rB, getIReg(rB_addr) );
6798   assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
6799   assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
6800
6801   if (opc1 == 0x1F) {
6802      switch (opc2) {
6803      case 0x018: { // slw (Shift Left Word, PPC32 p505)
6804         DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6805             rA_addr, rS_addr, rB_addr);
6806         /* rA = rS << rB */
6807         /* ppc32 semantics are:
6808            slw(x,y) = (x << (y & 31))         -- primary result
6809                       & ~((y << 26) >>s 31)   -- make result 0
6810                                                  for y in 32 .. 63
6811         */
6812         e_tmp =
6813            binop( Iop_And32,
6814               binop( Iop_Shl32,
6815                      mkexpr(rS_lo32),
6816                      unop( Iop_32to8,
6817                            binop(Iop_And32,
6818                                  mkexpr(rB_lo32), mkU32(31)))),
6819               unop( Iop_Not32,
6820                     binop( Iop_Sar32,
6821                            binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
6822                            mkU8(31))) );
6823         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6824         break;
6825      }
6826
6827      case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
6828         IRTemp sh_amt = newTemp(Ity_I32);
6829         DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6830             rA_addr, rS_addr, rB_addr);
6831         /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
6832            amt = rB & 63
6833            rA = Sar32( rS, amt > 31 ? 31 : amt )
6834            XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
6835         */
6836         assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
6837                                          mkexpr(rB_lo32)) );
6838         assign( outofrange,
6839                 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) );
6840         e_tmp = binop( Iop_Sar32,
6841                        mkexpr(rS_lo32),
6842                        unop( Iop_32to8,
6843                              IRExpr_ITE( mkexpr(outofrange),
6844                                          mkU32(31),
6845                                          mkexpr(sh_amt)) ) );
6846         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
6847
6848         set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
6849                     mkexpr(rA),
6850                     mkWidenFrom32(ty, mkexpr(rS_lo32), True),
6851                     mkWidenFrom32(ty, mkexpr(sh_amt), True ),
6852                     mkWidenFrom32(ty, getXER_CA32(), True) );
6853         break;
6854      }
6855
6856      case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
6857         DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
6858             rA_addr, rS_addr, sh_imm);
6859         vassert(sh_imm < 32);
6860         if (mode64) {
6861            assign( rA, binop(Iop_Sar64,
6862                              binop(Iop_Shl64, getIReg(rS_addr),
6863                                               mkU8(32)),
6864                              mkU8(32 + sh_imm)) );
6865         } else {
6866            assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
6867                                         mkU8(sh_imm)) );
6868         }
6869
6870         set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
6871                     mkexpr(rA),
6872                     mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
6873                     mkSzImm(ty, sh_imm),
6874                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6875         break;
6876
6877      case 0x218: // srw (Shift Right Word, PPC32 p508)
6878         DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6879             rA_addr, rS_addr, rB_addr);
6880         /* rA = rS >>u rB */
6881         /* ppc32 semantics are:
6882            srw(x,y) = (x >>u (y & 31))        -- primary result
6883                       & ~((y << 26) >>s 31)   -- make result 0
6884                                                  for y in 32 .. 63
6885         */
6886         e_tmp =
6887            binop(
6888               Iop_And32,
6889               binop( Iop_Shr32,
6890                      mkexpr(rS_lo32),
6891                      unop( Iop_32to8,
6892                            binop(Iop_And32, mkexpr(rB_lo32),
6893                                             mkU32(31)))),
6894               unop( Iop_Not32,
6895                     binop( Iop_Sar32,
6896                            binop(Iop_Shl32, mkexpr(rB_lo32),
6897                                             mkU8(26)),
6898                            mkU8(31))));
6899         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6900         break;
6901
6902
6903      /* 64bit Shifts */
6904      case 0x01B: // sld (Shift Left DWord, PPC64 p568)
6905         DIP("sld%s r%u,r%u,r%u\n",
6906             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6907         /* rA = rS << rB */
6908         /* ppc64 semantics are:
6909            slw(x,y) = (x << (y & 63))         -- primary result
6910                       & ~((y << 57) >>s 63)   -- make result 0
6911                                                  for y in 64 ..
6912         */
6913         assign( rA,
6914            binop(
6915               Iop_And64,
6916               binop( Iop_Shl64,
6917                      mkexpr(rS),
6918                      unop( Iop_64to8,
6919                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6920               unop( Iop_Not64,
6921                     binop( Iop_Sar64,
6922                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6923                            mkU8(63)))) );
6924         break;
6925
6926      case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
6927         IRTemp sh_amt = newTemp(Ity_I64);
6928         DIP("srad%s r%u,r%u,r%u\n",
6929             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6930         /* amt = rB & 127
6931            rA = Sar64( rS, amt > 63 ? 63 : amt )
6932            XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
6933         */
6934         assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
6935         assign( outofrange,
6936                 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) );
6937         assign( rA,
6938                 binop( Iop_Sar64,
6939                        mkexpr(rS),
6940                        unop( Iop_64to8,
6941                              IRExpr_ITE( mkexpr(outofrange),
6942                                          mkU64(63),
6943                                          mkexpr(sh_amt)) ))
6944               );
6945         set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
6946                     mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
6947                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6948         break;
6949      }
6950
6951      case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
6952         sh_imm |= b1<<5;
6953         vassert(sh_imm < 64);
6954         DIP("sradi%s r%u,r%u,%u\n",
6955             flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
6956         assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
6957
6958         set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
6959                     mkexpr(rA),
6960                     getIReg(rS_addr),
6961                     mkU64(sh_imm),
6962                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6963         break;
6964
6965      case 0x21B: // srd (Shift Right DWord, PPC64 p574)
6966         DIP("srd%s r%u,r%u,r%u\n",
6967             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6968         /* rA = rS >>u rB */
6969         /* ppc semantics are:
6970            srw(x,y) = (x >>u (y & 63))        -- primary result
6971                       & ~((y << 57) >>s 63)   -- make result 0
6972                                                  for y in 64 .. 127
6973         */
6974         assign( rA,
6975            binop(
6976               Iop_And64,
6977               binop( Iop_Shr64,
6978                      mkexpr(rS),
6979                      unop( Iop_64to8,
6980                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6981               unop( Iop_Not64,
6982                     binop( Iop_Sar64,
6983                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6984                            mkU8(63)))) );
6985         break;
6986
6987      default:
6988         vex_printf("dis_int_shift(ppc)(opc2)\n");
6989         return False;
6990      }
6991   } else {
6992      vex_printf("dis_int_shift(ppc)(opc1)\n");
6993      return False;
6994   }
6995
6996   putIReg( rA_addr, mkexpr(rA) );
6997
6998   if (flag_rC) {
6999      set_CR0( mkexpr(rA) );
7000   }
7001   return True;
7002}
7003
7004
7005
7006/*
7007  Integer Load/Store Reverse Instructions
7008*/
7009/* Generates code to swap the byte order in an Ity_I32. */
7010static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
7011{
7012   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
7013   return
7014      binop(Iop_Or32,
7015         binop(Iop_Shl32, mkexpr(t), mkU8(24)),
7016      binop(Iop_Or32,
7017         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
7018                          mkU32(0x00FF0000)),
7019      binop(Iop_Or32,
7020         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
7021                          mkU32(0x0000FF00)),
7022         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
7023                          mkU32(0x000000FF) )
7024      )));
7025}
7026
7027/* Generates code to swap the byte order in the lower half of an Ity_I32,
7028   and zeroes the upper half. */
7029static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
7030{
7031   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
7032   return
7033      binop(Iop_Or32,
7034         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
7035                          mkU32(0x0000FF00)),
7036         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
7037                          mkU32(0x000000FF))
7038      );
7039}
7040
7041static Bool dis_int_ldst_rev ( UInt theInstr )
7042{
7043   /* X-Form */
7044   UChar opc1    = ifieldOPC(theInstr);
7045   UChar rD_addr = ifieldRegDS(theInstr);
7046   UChar rS_addr = rD_addr;
7047   UChar rA_addr = ifieldRegA(theInstr);
7048   UChar rB_addr = ifieldRegB(theInstr);
7049   UInt  opc2    = ifieldOPClo10(theInstr);
7050   UChar b0      = ifieldBIT0(theInstr);
7051
7052   IRType ty = mode64 ? Ity_I64 : Ity_I32;
7053   IRTemp EA = newTemp(ty);
7054   IRTemp w1 = newTemp(Ity_I32);
7055   IRTemp w2 = newTemp(Ity_I32);
7056
7057   if (opc1 != 0x1F || b0 != 0) {
7058      vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
7059      return False;
7060   }
7061
7062   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7063
7064   switch (opc2) {
7065
7066      case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
7067         DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7068         assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) );
7069         assign( w2, gen_byterev16(w1) );
7070         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
7071                                         /* Signed */False) );
7072         break;
7073
7074      case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
7075         DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7076         assign( w1, load(Ity_I32, mkexpr(EA)) );
7077         assign( w2, gen_byterev32(w1) );
7078         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
7079                                         /* Signed */False) );
7080         break;
7081
7082      case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
7083      {
7084         IRExpr * nextAddr;
7085         IRTemp w3 = newTemp( Ity_I32 );
7086         IRTemp w4 = newTemp( Ity_I32 );
7087         DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7088         assign( w1, load( Ity_I32, mkexpr( EA ) ) );
7089         assign( w2, gen_byterev32( w1 ) );
7090         nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
7091                           ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
7092         assign( w3, load( Ity_I32, nextAddr ) );
7093         assign( w4, gen_byterev32( w3 ) );
7094         if (host_endness == VexEndnessLE)
7095            putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) );
7096         else
7097            putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
7098         break;
7099      }
7100
7101      case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
7102         DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7103         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
7104         store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
7105         break;
7106
7107      case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
7108         DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7109         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
7110         store( mkexpr(EA), gen_byterev32(w1) );
7111         break;
7112
7113      case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
7114      {
7115         IRTemp lo = newTemp(Ity_I32);
7116         IRTemp hi = newTemp(Ity_I32);
7117         IRTemp rS = newTemp(Ity_I64);
7118         assign( rS, getIReg( rS_addr ) );
7119         DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7120         assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
7121         assign(hi, unop(Iop_64to32, mkexpr(rS)));
7122         store( mkexpr( EA ),
7123                binop( Iop_32HLto64, gen_byterev32( hi ),
7124                       gen_byterev32( lo ) ) );
7125         break;
7126      }
7127
7128      default:
7129         vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
7130         return False;
7131   }
7132   return True;
7133}
7134
7135
7136
7137/*
7138  Processor Control Instructions
7139*/
7140static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr )
7141{
7142   UChar opc1     = ifieldOPC(theInstr);
7143
7144   /* X-Form */
7145   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
7146   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
7147   UChar rD_addr  = ifieldRegDS(theInstr);
7148   UInt  b11to20  = IFIELD( theInstr, 11, 10 );
7149
7150   /* XFX-Form */
7151   UChar rS_addr  = rD_addr;
7152   UInt  SPR      = b11to20;
7153   UInt  TBR      = b11to20;
7154   UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
7155   UInt  CRM      = IFIELD( theInstr, 12, 8 );
7156   UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
7157
7158   UInt  opc2     = ifieldOPClo10(theInstr);
7159   UChar b0       = ifieldBIT0(theInstr);
7160
7161   IRType ty = mode64 ? Ity_I64 : Ity_I32;
7162   IRTemp rS = newTemp(ty);
7163   assign( rS, getIReg(rS_addr) );
7164
7165   /* Reorder SPR field as per PPC32 p470 */
7166   SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
7167   /* Reorder TBR field as per PPC32 p475 */
7168   TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
7169
7170   /* b0 = 0, inst is treated as floating point inst for reservation purposes
7171    * b0 = 1, inst is treated as vector inst for reservation purposes
7172    */
7173   if (opc1 != 0x1F) {
7174      vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0);
7175      return False;
7176   }
7177
7178   switch (opc2) {
7179   /* X-Form */
7180   case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
7181      if (b21to22 != 0 || b11to20 != 0) {
7182         vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
7183         return False;
7184      }
7185      DIP("mcrxr crf%d\n", crfD);
7186      /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
7187      putGST_field( PPC_GST_CR,
7188                    getGST_field( PPC_GST_XER, 7 ),
7189                    crfD );
7190
7191      // Clear XER[0-3]
7192      putXER_SO( mkU8(0) );
7193      putXER_OV( mkU8(0) );
7194      putXER_CA( mkU8(0) );
7195      break;
7196   }
7197
7198   case 0x013:
7199      // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
7200      // b20==1 & b11==0: mfocrf (Move from One CR Field)
7201      // However it seems that the 'mfcr' behaviour is an acceptable
7202      // implementation of mfocr (from the 2.02 arch spec)
7203      if (b11to20 == 0) {
7204         DIP("mfcr r%u\n", rD_addr);
7205         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
7206                                         /* Signed */False) );
7207         break;
7208      }
7209      if (b20 == 1 && b11 == 0) {
7210         DIP("mfocrf r%u,%u\n", rD_addr, CRM);
7211         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
7212                                         /* Signed */False) );
7213         break;
7214      }
7215      /* not decodable */
7216      return False;
7217
7218   /* XFX-Form */
7219   case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
7220
7221      switch (SPR) {  // Choose a register...
7222      case 0x1:
7223         DIP("mfxer r%u\n", rD_addr);
7224         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
7225                                         /* Signed */False) );
7226         break;
7227      case 0x8:
7228         DIP("mflr r%u\n", rD_addr);
7229         putIReg( rD_addr, getGST( PPC_GST_LR ) );
7230         break;
7231      case 0x9:
7232         DIP("mfctr r%u\n", rD_addr);
7233         putIReg( rD_addr, getGST( PPC_GST_CTR ) );
7234         break;
7235      case 0x80:  // 128
7236         DIP("mfspr r%u (TFHAR)\n", rD_addr);
7237         putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
7238         break;
7239      case 0x81:  // 129
7240         DIP("mfspr r%u (TFIAR)\n", rD_addr);
7241         putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
7242         break;
7243      case 0x82:  // 130
7244         DIP("mfspr r%u (TEXASR)\n", rD_addr);
7245         putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
7246         break;
7247      case 0x83:  // 131
7248         DIP("mfspr r%u (TEXASRU)\n", rD_addr);
7249         putIReg( rD_addr, getGST( PPC_GST_TEXASRU) );
7250         break;
7251      case 0x9F:  // 159
7252         DIP("mfspr r%u (PSPB)\n", rD_addr);
7253         putIReg( rD_addr, getGST( PPC_GST_PSPB) );
7254         break;
7255      case 0x380:  // 896
7256         DIP("mfspr r%u (PPR)\n", rD_addr);
7257         putIReg( rD_addr, getGST( PPC_GST_PPR) );
7258         break;
7259      case 0x382:  // 898
7260         DIP("mfspr r%u (PPR)32\n", rD_addr);
7261         putIReg( rD_addr, getGST( PPC_GST_PPR32) );
7262         break;
7263      case 0x100:
7264         DIP("mfvrsave r%u\n", rD_addr);
7265         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
7266                                         /* Signed */False) );
7267         break;
7268
7269      case 0x103:
7270         DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
7271         putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
7272         break;
7273
7274      /* Even a lowly PPC7400 can run the associated helper, so no
7275         obvious need for feature testing at this point. */
7276      case 268 /* 0x10C */:
7277      case 269 /* 0x10D */: {
7278         UInt     arg  = SPR==268 ? 0 : 1;
7279         IRTemp   val  = newTemp(Ity_I32);
7280         IRExpr** args = mkIRExprVec_1( mkU32(arg) );
7281         IRDirty* d    = unsafeIRDirty_1_N(
7282                            val,
7283                            0/*regparms*/,
7284                            "ppc32g_dirtyhelper_MFSPR_268_269",
7285                            fnptr_to_fnentry
7286                               (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
7287                            args
7288                         );
7289         /* execute the dirty call, dumping the result in val. */
7290         stmt( IRStmt_Dirty(d) );
7291         putIReg( rD_addr,
7292                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
7293         DIP("mfspr r%u,%u", rD_addr, SPR);
7294         break;
7295      }
7296
7297      /* Again, runs natively on PPC7400 (7447, really).  Not
7298         bothering with a feature test. */
7299      case 287: /* 0x11F */ {
7300         IRTemp   val  = newTemp(Ity_I32);
7301         IRExpr** args = mkIRExprVec_0();
7302         IRDirty* d    = unsafeIRDirty_1_N(
7303                            val,
7304                            0/*regparms*/,
7305                            "ppc32g_dirtyhelper_MFSPR_287",
7306                            fnptr_to_fnentry
7307                               (vbi, &ppc32g_dirtyhelper_MFSPR_287),
7308                            args
7309                         );
7310         /* execute the dirty call, dumping the result in val. */
7311         stmt( IRStmt_Dirty(d) );
7312         putIReg( rD_addr,
7313                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
7314         DIP("mfspr r%u,%u", rD_addr, SPR);
7315         break;
7316      }
7317
7318      default:
7319         vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
7320         return False;
7321      }
7322      break;
7323
7324   case 0x173: { // mftb (Move from Time Base, PPC32 p475)
7325      IRTemp   val  = newTemp(Ity_I64);
7326      IRExpr** args = mkIRExprVec_0();
7327      IRDirty* d    = unsafeIRDirty_1_N(
7328                              val,
7329                              0/*regparms*/,
7330                              "ppcg_dirtyhelper_MFTB",
7331                              fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
7332                              args );
7333      /* execute the dirty call, dumping the result in val. */
7334      stmt( IRStmt_Dirty(d) );
7335
7336      switch (TBR) {
7337      case 269:
7338         DIP("mftbu r%u", rD_addr);
7339         putIReg( rD_addr,
7340                  mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
7341                                /* Signed */False) );
7342         break;
7343      case 268:
7344         DIP("mftb r%u", rD_addr);
7345         putIReg( rD_addr, (mode64) ? mkexpr(val) :
7346                                      unop(Iop_64to32, mkexpr(val)) );
7347         break;
7348      default:
7349         return False; /* illegal instruction */
7350      }
7351      break;
7352   }
7353
7354   case 0x090: {
7355      // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
7356      // b20==1: mtocrf (Move to One Cond Reg Field)
7357      Int   cr;
7358      UChar shft;
7359      if (b11 != 0)
7360         return False;
7361      if (b20 == 1) {
7362         /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
7363            1 field is written.  It seems more robust to decline to
7364            decode the insn if so. */
7365         switch (CRM) {
7366            case 0x01: case 0x02: case 0x04: case 0x08:
7367            case 0x10: case 0x20: case 0x40: case 0x80:
7368               break;
7369            default:
7370               return False;
7371         }
7372      }
7373      DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
7374                           CRM, rS_addr);
7375      /* Write to each field specified by CRM */
7376      for (cr = 0; cr < 8; cr++) {
7377         if ((CRM & (1 << (7-cr))) == 0)
7378            continue;
7379         shft = 4*(7-cr);
7380         putGST_field( PPC_GST_CR,
7381                       binop(Iop_Shr32,
7382                             mkNarrowTo32(ty, mkexpr(rS)),
7383                             mkU8(shft)), cr );
7384      }
7385      break;
7386   }
7387
7388   case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
7389
7390      switch (SPR) {  // Choose a register...
7391      case 0x1:
7392         DIP("mtxer r%u\n", rS_addr);
7393         putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
7394         break;
7395      case 0x8:
7396         DIP("mtlr r%u\n", rS_addr);
7397         putGST( PPC_GST_LR, mkexpr(rS) );
7398         break;
7399      case 0x9:
7400         DIP("mtctr r%u\n", rS_addr);
7401         putGST( PPC_GST_CTR, mkexpr(rS) );
7402         break;
7403      case 0x100:
7404         DIP("mtvrsave r%u\n", rS_addr);
7405         putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
7406         break;
7407      case 0x80:  // 128
7408         DIP("mtspr r%u (TFHAR)\n", rS_addr);
7409         putGST( PPC_GST_TFHAR, mkexpr(rS) );
7410         break;
7411      case 0x81:  // 129
7412         DIP("mtspr r%u (TFIAR)\n", rS_addr);
7413         putGST( PPC_GST_TFIAR, mkexpr(rS) );
7414         break;
7415      case 0x82:  // 130
7416         DIP("mtspr r%u (TEXASR)\n", rS_addr);
7417         putGST( PPC_GST_TEXASR, mkexpr(rS) );
7418         break;
7419      case 0x9F:  // 159
7420         DIP("mtspr r%u (PSPB)\n", rS_addr);
7421         putGST( PPC_GST_PSPB, mkexpr(rS) );
7422         break;
7423      case 0x380:  // 896
7424         DIP("mtspr r%u (PPR)\n", rS_addr);
7425         putGST( PPC_GST_PPR, mkexpr(rS) );
7426         break;
7427      case 0x382:  // 898
7428         DIP("mtspr r%u (PPR32)\n", rS_addr);
7429         putGST( PPC_GST_PPR32, mkexpr(rS) );
7430         break;
7431      default:
7432         vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
7433         return False;
7434      }
7435      break;
7436
7437   case 0x33:                // mfvsrd
7438   {
7439      UChar XS = ifieldRegXS( theInstr );
7440      UChar rA_addr = ifieldRegA(theInstr);
7441      IRExpr * high64;
7442      IRTemp vS = newTemp( Ity_V128 );
7443      DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS);
7444
7445      /*  XS = SX || S
7446       *  For SX=0, mfvsrd is treated as a Floating-Point
7447       *            instruction in terms of resource availability.
7448       *  For SX=1, mfvsrd is treated as a Vector instruction in
7449       *            terms of resource availability.
7450       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7451       */
7452      assign( vS, getVSReg( XS ) );
7453      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
7454      putIReg( rA_addr, (mode64) ? high64 :
7455      unop( Iop_64to32, high64 ) );
7456      break;
7457   }
7458
7459   case 0x73:                // mfvsrwz
7460   {
7461      UChar XS = ifieldRegXS( theInstr );
7462      UChar rA_addr = ifieldRegA(theInstr);
7463      IRExpr * high64;
7464      IRTemp vS = newTemp( Ity_V128 );
7465      DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS);
7466      /*  XS = SX || S
7467       *  For SX=0, mfvsrwz is treated as a Floating-Point
7468       *            instruction in terms of resource availability.
7469       *  For SX=1, mfvsrwz is treated as a Vector instruction in
7470       *            terms of resource availability.
7471       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7472       */
7473
7474      assign( vS, getVSReg( XS ) );
7475      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
7476      /* move value to the destination setting the upper 32-bits to zero */
7477      putIReg( rA_addr, (mode64) ?
7478                                  binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) :
7479                                  unop(  Iop_64to32,
7480                                         binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
7481      break;
7482   }
7483
7484   case 0xB3:                // mtvsrd
7485   {
7486      UChar XT = ifieldRegXT( theInstr );
7487      UChar rA_addr = ifieldRegA(theInstr);
7488      IRTemp rA = newTemp(ty);
7489      DIP("mtvsrd vsr%d,r%u\n", XT, rA_addr);
7490      /*  XS = SX || S
7491       *  For SX=0, mfvsrd is treated as a Floating-Point
7492       *            instruction in terms of resource availability.
7493       *  For SX=1, mfvsrd is treated as a Vector instruction in
7494       *            terms of resource availability.
7495       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7496       */
7497      assign( rA, getIReg(rA_addr) );
7498
7499      if (mode64)
7500         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
7501      else
7502         putVSReg( XT, binop( Iop_64HLtoV128,
7503                              binop( Iop_32HLto64,
7504                                     mkU32( 0 ),
7505                                     mkexpr( rA ) ),
7506                                     mkU64( 0 ) ) );
7507      break;
7508   }
7509
7510   case 0xD3:                // mtvsrwa
7511   {
7512      UChar XT = ifieldRegXT( theInstr );
7513      UChar rA_addr = ifieldRegA(theInstr);
7514      IRTemp rA = newTemp( Ity_I32 );
7515      DIP("mtvsrwa vsr%d,r%u\n", XT, rA_addr);
7516      /*  XS = SX || S
7517       *  For SX=0, mtvsrwa is treated as a Floating-Point
7518       *            instruction in terms of resource availability.
7519       *  For SX=1, mtvsrwa is treated as a Vector instruction in
7520       *            terms of resource availability.
7521       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7522       */
7523      if (mode64)
7524         assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
7525      else
7526         assign( rA, getIReg(rA_addr) );
7527
7528      putVSReg( XT, binop( Iop_64HLtoV128,
7529                           unop( Iop_32Sto64, mkexpr( rA ) ),
7530                           mkU64( 0 ) ) );
7531      break;
7532   }
7533
7534   case 0xF3:                // mtvsrwz
7535      {
7536         UChar XT = ifieldRegXT( theInstr );
7537         UChar rA_addr = ifieldRegA(theInstr);
7538         IRTemp rA = newTemp( Ity_I32 );
7539         DIP("mtvsrwz vsr%d,r%u\n", rA_addr, XT);
7540         /*  XS = SX || S
7541          *  For SX=0, mtvsrwz is treated as a Floating-Point
7542          *            instruction in terms of resource availability.
7543          *  For SX=1, mtvsrwz is treated as a Vector instruction in
7544          *            terms of resource availability.
7545          * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7546          */
7547         if (mode64)
7548             assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
7549         else
7550             assign( rA, getIReg(rA_addr) );
7551
7552         putVSReg( XT, binop( Iop_64HLtoV128,
7553                              binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
7554                              mkU64( 0 ) ) );
7555         break;
7556      }
7557
7558   default:
7559      vex_printf("dis_proc_ctl(ppc)(opc2)\n");
7560      return False;
7561   }
7562   return True;
7563}
7564
7565
7566/*
7567  Cache Management Instructions
7568*/
7569static Bool dis_cache_manage ( UInt         theInstr,
7570                               DisResult*   dres,
7571                               const VexArchInfo* guest_archinfo )
7572{
7573   /* X-Form */
7574   UChar opc1    = ifieldOPC(theInstr);
7575   UChar b21to25 = ifieldRegDS(theInstr);
7576   UChar rA_addr = ifieldRegA(theInstr);
7577   UChar rB_addr = ifieldRegB(theInstr);
7578   UInt  opc2    = ifieldOPClo10(theInstr);
7579   UChar b0      = ifieldBIT0(theInstr);
7580   UInt  lineszB = guest_archinfo->ppc_icache_line_szB;
7581   Bool  is_dcbzl = False;
7582
7583   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
7584
7585   // Check for valid hint values for dcbt and dcbtst as currently described in
7586   // ISA 2.07.  If valid, then we simply set b21to25 to zero since we have no
7587   // means of modeling the hint anyway.
7588   if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) {
7589      if (b21to25 == 0x10 || b21to25 < 0x10)
7590         b21to25 = 0;
7591   }
7592   if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
7593      b21to25 = 0;
7594
7595   if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
7596      if (b21to25 == 1) {
7597         is_dcbzl = True;
7598         b21to25 = 0;
7599         if (!(guest_archinfo->ppc_dcbzl_szB)) {
7600            vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
7601            return False;
7602         }
7603      }
7604   }
7605
7606   if (opc1 != 0x1F || b0 != 0) {
7607      if (0) vex_printf("dis_cache_manage %d %d\n",
7608                        opc1, b0);
7609      vex_printf("dis_cache_manage(ppc)(opc1|b0)\n");
7610      return False;
7611   }
7612
7613   /* stay sane .. */
7614   vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
7615
7616   switch (opc2) {
7617//zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
7618//zz       vassert(0); /* AWAITING TEST CASE */
7619//zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
7620//zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
7621//zz       break;
7622
7623   case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
7624      DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
7625      /* nop as far as vex is concerned */
7626      break;
7627
7628   case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
7629      DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
7630      /* nop as far as vex is concerned */
7631      break;
7632
7633   case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
7634      DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
7635      /* nop as far as vex is concerned */
7636      break;
7637
7638   case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
7639      DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
7640      /* nop as far as vex is concerned */
7641      break;
7642
7643   case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
7644                 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
7645      /* Clear all bytes in cache block at (rA|0) + rB. */
7646      IRTemp  EA   = newTemp(ty);
7647      IRTemp  addr = newTemp(ty);
7648      IRExpr* irx_addr;
7649      UInt    i;
7650      UInt clearszB;
7651      if (is_dcbzl) {
7652          clearszB = guest_archinfo->ppc_dcbzl_szB;
7653          DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
7654      }
7655      else {
7656          clearszB = guest_archinfo->ppc_dcbz_szB;
7657          DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
7658      }
7659
7660      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7661
7662      if (mode64) {
7663         /* Round EA down to the start of the containing block. */
7664         assign( addr, binop( Iop_And64,
7665                              mkexpr(EA),
7666                              mkU64( ~((ULong)clearszB-1) )) );
7667
7668         for (i = 0; i < clearszB / 8; i++) {
7669            irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
7670            store( irx_addr, mkU64(0) );
7671         }
7672      } else {
7673         /* Round EA down to the start of the containing block. */
7674         assign( addr, binop( Iop_And32,
7675                              mkexpr(EA),
7676                              mkU32( ~(clearszB-1) )) );
7677
7678         for (i = 0; i < clearszB / 4; i++) {
7679            irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
7680            store( irx_addr, mkU32(0) );
7681         }
7682      }
7683      break;
7684   }
7685
7686   case 0x3D6: {
7687      // icbi (Instruction Cache Block Invalidate, PPC32 p431)
7688      /* Invalidate all translations containing code from the cache
7689         block at (rA|0) + rB. */
7690      IRTemp EA   = newTemp(ty);
7691      IRTemp addr = newTemp(ty);
7692      DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
7693      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7694
7695      /* Round EA down to the start of the containing block. */
7696      assign( addr, binop( mkSzOp(ty, Iop_And8),
7697                           mkexpr(EA),
7698                           mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
7699      putGST( PPC_GST_CMSTART, mkexpr(addr) );
7700      putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) );
7701
7702      /* be paranoid ... */
7703      stmt( IRStmt_MBE(Imbe_Fence) );
7704
7705      putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
7706      dres->jk_StopHere = Ijk_InvalICache;
7707      dres->whatNext    = Dis_StopHere;
7708      break;
7709   }
7710
7711   default:
7712      vex_printf("dis_cache_manage(ppc)(opc2)\n");
7713      return False;
7714   }
7715   return True;
7716}
7717
7718
7719/*------------------------------------------------------------*/
7720/*--- Floating Point Helpers                               ---*/
7721/*------------------------------------------------------------*/
7722
7723/* --------- Synthesise a 2-bit FPU rounding mode. --------- */
7724/* Produces a value in 0 .. 3, which is encoded as per the type
7725   IRRoundingMode.  PPCRoundingMode encoding is different to
7726   IRRoundingMode, so need to map it.
7727*/
7728static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
7729{
7730/*
7731   rounding mode | PPC | IR
7732   ------------------------
7733   to nearest    | 00  | 00
7734   to zero       | 01  | 11
7735   to +infinity  | 10  | 10
7736   to -infinity  | 11  | 01
7737*/
7738   IRTemp rm_PPC32 = newTemp(Ity_I32);
7739   assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
7740
7741   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7742   return binop( Iop_Xor32,
7743                 mkexpr(rm_PPC32),
7744                 binop( Iop_And32,
7745                        binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
7746                        mkU32(2) ));
7747}
7748
7749/* The DFP IR rounding modes were chosen such that the existing PPC to IR
7750 * mapping would still work with the extended three bit DFP rounding
7751 * mode designator.
7752
7753 *  rounding mode                     | PPC  |  IR
7754 *  -----------------------------------------------
7755 *  to nearest, ties to even          | 000  | 000
7756 *  to zero                           | 001  | 011
7757 *  to +infinity                      | 010  | 010
7758 *  to -infinity                      | 011  | 001
7759 *  to nearest, ties away from 0      | 100  | 100
7760 *  to nearest, ties toward 0         | 101  | 111
7761 *  to away from 0                    | 110  | 110
7762 *  to prepare for shorter precision  | 111  | 101
7763 */
7764static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
7765{
7766   IRTemp rm_PPC32 = newTemp( Ity_I32 );
7767   assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
7768
7769   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7770   return binop( Iop_Xor32,
7771                 mkexpr( rm_PPC32 ),
7772                 binop( Iop_And32,
7773                        binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
7774                        mkU32( 2 ) ) );
7775}
7776
7777#define NANmaskSingle   0x7F800000
7778#define NANmaskDouble   0x7FF00000
7779
7780static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
7781{
7782   IRTemp exp_zero  = newTemp(Ity_I8);
7783   IRTemp frac_mask = newTemp(Ity_I32);
7784   IRTemp frac_not_zero = newTemp(Ity_I8);
7785
7786   /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
7787    * The input value is always 64-bits, for single precision values, the
7788    * lower 32 bits must be zero.
7789    *
7790    * Single Pricision
7791    *  [62:54] exponent field is equal to 0xFF for NAN and Infinity.
7792    *  [53:32] fraction field is zero for Infinity and non-zero for NAN
7793    *  [31:0]  unused for single precision representation
7794    *
7795    * Double Pricision
7796    *  [62:51] exponent field is equal to 0xFF for NAN and Infinity.
7797    *  [50:0]  fraction field is zero for Infinity and non-zero for NAN
7798    *
7799    * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
7800    */
7801   assign( frac_mask, unop( Iop_Not32,
7802                            binop( Iop_Or32,
7803                                   mkU32( 0x80000000ULL ), Hi32Mask) ) );
7804
7805   assign( exp_zero,
7806           unop( Iop_1Sto8,
7807                 binop( Iop_CmpEQ32,
7808                        binop( Iop_And32,
7809                               unop( Iop_64HIto32,
7810                                     unop( Iop_ReinterpF64asI64,
7811                                           value ) ),
7812                               Hi32Mask ),
7813                        Hi32Mask ) ) );
7814   assign( frac_not_zero,
7815           binop( Iop_Or8,
7816                  unop( Iop_1Sto8,
7817                        binop( Iop_CmpNE32,
7818                               binop( Iop_And32,
7819                                      unop( Iop_64HIto32,
7820                                            unop( Iop_ReinterpF64asI64,
7821                                                  value ) ),
7822                                      mkexpr( frac_mask ) ),
7823                               mkU32( 0x0 ) ) ),
7824                  unop( Iop_1Sto8,
7825                        binop( Iop_CmpNE32,
7826                               binop( Iop_And32,
7827                                      unop( Iop_64to32,
7828                                            unop( Iop_ReinterpF64asI64,
7829                                                  value ) ),
7830                                      mkU32( 0xFFFFFFFF ) ),
7831                               mkU32( 0x0 ) ) ) ) );
7832   return unop( Iop_8Sto32,
7833                binop( Iop_And8,
7834                       mkexpr( exp_zero ),
7835                       mkexpr( frac_not_zero ) ) );
7836}
7837
7838static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
7839{
7840   /* This function will only complement the 64-bit floating point value if it
7841    * is not Nan.  NaN is not a signed value.  Need to do computations using
7842    * 32-bit operands to ensure it will run in 32-bit mode.
7843    */
7844   return  binop( Iop_32HLto64,
7845                  binop( Iop_Or32,
7846                         binop( Iop_And32,
7847                                nan_mask,
7848                                unop( Iop_64HIto32,
7849                                      unop( Iop_ReinterpF64asI64,
7850                                            value ) ) ),
7851                         binop( Iop_And32,
7852                                unop( Iop_Not32,
7853                                      nan_mask ),
7854                                unop( Iop_64HIto32,
7855                                      unop( Iop_ReinterpF64asI64,
7856                                            unop( Iop_NegF64,
7857                                                  value ) ) ) ) ),
7858                  unop( Iop_64to32,
7859                        unop( Iop_ReinterpF64asI64, value ) ) );
7860}
7861
7862/*------------------------------------------------------------*/
7863/*--- Floating Point Instruction Translation               ---*/
7864/*------------------------------------------------------------*/
7865
7866/*
7867  Floating Point Load Instructions
7868*/
7869static Bool dis_fp_load ( UInt theInstr )
7870{
7871   /* X-Form, D-Form */
7872   UChar opc1      = ifieldOPC(theInstr);
7873   UChar frD_addr  = ifieldRegDS(theInstr);
7874   UChar rA_addr   = ifieldRegA(theInstr);
7875   UChar rB_addr   = ifieldRegB(theInstr);
7876   UInt  opc2      = ifieldOPClo10(theInstr);
7877   UChar b0        = ifieldBIT0(theInstr);
7878   UInt  uimm16    = ifieldUIMM16(theInstr);
7879
7880   Int    simm16 = extend_s_16to32(uimm16);
7881   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
7882   IRTemp EA     = newTemp(ty);
7883   IRTemp rA     = newTemp(ty);
7884   IRTemp rB     = newTemp(ty);
7885   IRTemp iHi    = newTemp(Ity_I32);
7886   IRTemp iLo    = newTemp(Ity_I32);
7887
7888   assign( rA, getIReg(rA_addr) );
7889   assign( rB, getIReg(rB_addr) );
7890
7891   /* These are completely straightforward from a rounding and status
7892      bits perspective: no rounding involved and no funny status or CR
7893      bits affected. */
7894
7895   switch (opc1) {
7896   case 0x30: // lfs (Load Float Single, PPC32 p441)
7897      DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7898      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
7899      putFReg( frD_addr,
7900               unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7901      break;
7902
7903   case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
7904      if (rA_addr == 0)
7905         return False;
7906      DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7907      assign( EA, ea_rA_simm(rA_addr, simm16) );
7908      putFReg( frD_addr,
7909               unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7910      putIReg( rA_addr, mkexpr(EA) );
7911      break;
7912
7913   case 0x32: // lfd (Load Float Double, PPC32 p437)
7914      DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7915      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
7916      putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7917      break;
7918
7919   case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
7920      if (rA_addr == 0)
7921         return False;
7922      DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7923      assign( EA, ea_rA_simm(rA_addr, simm16) );
7924      putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7925      putIReg( rA_addr, mkexpr(EA) );
7926      break;
7927
7928   case 0x1F:
7929      if (b0 != 0) {
7930         vex_printf("dis_fp_load(ppc)(instr,b0)\n");
7931         return False;
7932      }
7933
7934      switch(opc2) {
7935      case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
7936         DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7937         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7938         putFReg( frD_addr, unop( Iop_F32toF64,
7939                                  load(Ity_F32, mkexpr(EA))) );
7940         break;
7941
7942      case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
7943         if (rA_addr == 0)
7944            return False;
7945         DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7946         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
7947         putFReg( frD_addr,
7948                  unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7949         putIReg( rA_addr, mkexpr(EA) );
7950         break;
7951
7952      case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
7953         DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7954         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7955         putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7956         break;
7957
7958      case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
7959         if (rA_addr == 0)
7960            return False;
7961         DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7962         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
7963         putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7964         putIReg( rA_addr, mkexpr(EA) );
7965         break;
7966
7967      case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
7968         DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7969         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7970         assign( iLo, load(Ity_I32, mkexpr(EA)) );
7971         assign( iHi, binop(Iop_Sub32,
7972                            mkU32(0),
7973                            binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
7974         putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
7975                                 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
7976         break;
7977
7978      case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
7979      {
7980         IRTemp dw = newTemp( Ity_I64 );
7981         DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7982         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7983         assign( iLo, load(Ity_I32, mkexpr(EA)) );
7984         assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
7985         putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
7986         break;
7987      }
7988
7989      default:
7990         vex_printf("dis_fp_load(ppc)(opc2)\n");
7991         return False;
7992      }
7993      break;
7994
7995   default:
7996      vex_printf("dis_fp_load(ppc)(opc1)\n");
7997      return False;
7998   }
7999   return True;
8000}
8001
8002
8003
8004/*
8005  Floating Point Store Instructions
8006*/
8007static Bool dis_fp_store ( UInt theInstr )
8008{
8009   /* X-Form, D-Form */
8010   UChar opc1      = ifieldOPC(theInstr);
8011   UChar frS_addr  = ifieldRegDS(theInstr);
8012   UChar rA_addr   = ifieldRegA(theInstr);
8013   UChar rB_addr   = ifieldRegB(theInstr);
8014   UInt  opc2      = ifieldOPClo10(theInstr);
8015   UChar b0        = ifieldBIT0(theInstr);
8016   Int   uimm16    = ifieldUIMM16(theInstr);
8017
8018   Int    simm16 = extend_s_16to32(uimm16);
8019   IRTemp frS    = newTemp(Ity_F64);
8020   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
8021   IRTemp EA     = newTemp(ty);
8022   IRTemp rA     = newTemp(ty);
8023   IRTemp rB     = newTemp(ty);
8024
8025   assign( frS, getFReg(frS_addr) );
8026   assign( rA,  getIReg(rA_addr) );
8027   assign( rB,  getIReg(rB_addr) );
8028
8029   /* These are straightforward from a status bits perspective: no
8030      funny status or CR bits affected.  For single precision stores,
8031      the values are truncated and denormalised (not rounded) to turn
8032      them into single precision values. */
8033
8034   switch (opc1) {
8035
8036   case 0x34: // stfs (Store Float Single, PPC32 p518)
8037      DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8038      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
8039      /* Use Iop_TruncF64asF32 to truncate and possible denormalise
8040         the value to be stored in the correct way, without any
8041         rounding. */
8042      store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8043      break;
8044
8045   case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
8046      if (rA_addr == 0)
8047         return False;
8048      DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8049      assign( EA, ea_rA_simm(rA_addr, simm16) );
8050      /* See comment for stfs */
8051      store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8052      putIReg( rA_addr, mkexpr(EA) );
8053      break;
8054
8055   case 0x36: // stfd (Store Float Double, PPC32 p513)
8056      DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8057      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
8058      store( mkexpr(EA), mkexpr(frS) );
8059      break;
8060
8061   case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
8062      if (rA_addr == 0)
8063         return False;
8064      DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8065      assign( EA, ea_rA_simm(rA_addr, simm16) );
8066      store( mkexpr(EA), mkexpr(frS) );
8067      putIReg( rA_addr, mkexpr(EA) );
8068      break;
8069
8070   case 0x1F:
8071      if (b0 != 0) {
8072         vex_printf("dis_fp_store(ppc)(instr,b0)\n");
8073         return False;
8074      }
8075      switch(opc2) {
8076      case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
8077         DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8078         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8079         /* See note for stfs */
8080         store( mkexpr(EA),
8081                unop(Iop_TruncF64asF32, mkexpr(frS)) );
8082         break;
8083
8084      case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
8085         if (rA_addr == 0)
8086            return False;
8087         DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8088         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
8089         /* See note for stfs */
8090         store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8091         putIReg( rA_addr, mkexpr(EA) );
8092         break;
8093
8094      case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
8095         DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8096         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8097         store( mkexpr(EA), mkexpr(frS) );
8098         break;
8099
8100      case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
8101         if (rA_addr == 0)
8102            return False;
8103         DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8104         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
8105         store( mkexpr(EA), mkexpr(frS) );
8106         putIReg( rA_addr, mkexpr(EA) );
8107         break;
8108
8109      case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
8110         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8111         DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8112         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8113         store( mkexpr(EA),
8114                unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
8115         break;
8116
8117      default:
8118         vex_printf("dis_fp_store(ppc)(opc2)\n");
8119         return False;
8120      }
8121      break;
8122
8123   default:
8124      vex_printf("dis_fp_store(ppc)(opc1)\n");
8125      return False;
8126   }
8127   return True;
8128}
8129
8130
8131
8132/*
8133  Floating Point Arith Instructions
8134*/
8135static Bool dis_fp_arith ( UInt theInstr )
8136{
8137   /* A-Form */
8138   UChar opc1     = ifieldOPC(theInstr);
8139   UChar frD_addr = ifieldRegDS(theInstr);
8140   UChar frA_addr = ifieldRegA(theInstr);
8141   UChar frB_addr = ifieldRegB(theInstr);
8142   UChar frC_addr = ifieldRegC(theInstr);
8143   UChar opc2     = ifieldOPClo5(theInstr);
8144   UChar flag_rC  = ifieldBIT0(theInstr);
8145
8146   IRTemp  frD = newTemp(Ity_F64);
8147   IRTemp  frA = newTemp(Ity_F64);
8148   IRTemp  frB = newTemp(Ity_F64);
8149   IRTemp  frC = newTemp(Ity_F64);
8150   IRExpr* rm  = get_IR_roundingmode();
8151
8152   /* By default, we will examine the results of the operation and set
8153      fpscr[FPRF] accordingly. */
8154   Bool set_FPRF = True;
8155
8156   /* By default, if flag_RC is set, we will clear cr1 after the
8157      operation.  In reality we should set cr1 to indicate the
8158      exception status of the operation, but since we're not
8159      simulating exceptions, the exception status will appear to be
8160      zero.  Hence cr1 should be cleared if this is a . form insn. */
8161   Bool clear_CR1 = True;
8162
8163   assign( frA, getFReg(frA_addr));
8164   assign( frB, getFReg(frB_addr));
8165   assign( frC, getFReg(frC_addr));
8166
8167   switch (opc1) {
8168   case 0x3B:
8169      switch (opc2) {
8170      case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
8171         if (frC_addr != 0)
8172            return False;
8173         DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8174             frD_addr, frA_addr, frB_addr);
8175         assign( frD, triop( Iop_DivF64r32,
8176                             rm, mkexpr(frA), mkexpr(frB) ));
8177         break;
8178
8179      case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
8180         if (frC_addr != 0)
8181            return False;
8182         DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8183             frD_addr, frA_addr, frB_addr);
8184         assign( frD, triop( Iop_SubF64r32,
8185                             rm, mkexpr(frA), mkexpr(frB) ));
8186         break;
8187
8188      case 0x15: // fadds (Floating Add Single, PPC32 p401)
8189         if (frC_addr != 0)
8190            return False;
8191         DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8192             frD_addr, frA_addr, frB_addr);
8193         assign( frD, triop( Iop_AddF64r32,
8194                             rm, mkexpr(frA), mkexpr(frB) ));
8195         break;
8196
8197      case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
8198         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
8199         if (frA_addr != 0 || frC_addr != 0)
8200            return False;
8201         DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
8202             frD_addr, frB_addr);
8203         // however illogically, on ppc970 this insn behaves identically
8204         // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
8205         assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
8206         break;
8207
8208      case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
8209         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8210         if (frA_addr != 0 || frC_addr != 0)
8211            return False;
8212         DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
8213             frD_addr, frB_addr);
8214         { IRExpr* ieee_one
8215              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
8216           assign( frD, triop( Iop_DivF64r32,
8217                               rm,
8218                               ieee_one, mkexpr(frB) ));
8219         }
8220         break;
8221
8222      case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
8223         if (frB_addr != 0)
8224            return False;
8225         DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8226             frD_addr, frA_addr, frC_addr);
8227         assign( frD, triop( Iop_MulF64r32,
8228                             rm, mkexpr(frA), mkexpr(frC) ));
8229         break;
8230
8231      case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
8232         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8233         // Undocumented instruction?
8234         if (frA_addr != 0 || frC_addr != 0)
8235            return False;
8236         DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
8237             frD_addr, frB_addr);
8238         assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
8239         break;
8240
8241      default:
8242         vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
8243         return False;
8244      }
8245      break;
8246
8247   case 0x3F:
8248      switch (opc2) {
8249      case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
8250         if (frC_addr != 0)
8251            return False;
8252         DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8253             frD_addr, frA_addr, frB_addr);
8254         assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
8255         break;
8256
8257      case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
8258         if (frC_addr != 0)
8259            return False;
8260         DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8261             frD_addr, frA_addr, frB_addr);
8262         assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
8263         break;
8264
8265      case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
8266         if (frC_addr != 0)
8267            return False;
8268         DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8269             frD_addr, frA_addr, frB_addr);
8270         assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
8271         break;
8272
8273      case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
8274         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
8275         if (frA_addr != 0 || frC_addr != 0)
8276            return False;
8277         DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
8278             frD_addr, frB_addr);
8279         assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
8280         break;
8281
8282      case 0x17: { // fsel (Floating Select, PPC32 p426)
8283         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8284         IRTemp cc    = newTemp(Ity_I32);
8285         IRTemp cc_b0 = newTemp(Ity_I32);
8286
8287         DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8288             frD_addr, frA_addr, frC_addr, frB_addr);
8289
8290         // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
8291         // => GT|EQ == (cc & 0x1 == 0)
8292         assign( cc, binop(Iop_CmpF64, mkexpr(frA),
8293                                       IRExpr_Const(IRConst_F64(0))) );
8294         assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
8295
8296         // frD = (frA >= 0.0) ? frC : frB
8297         //     = (cc_b0 == 0) ? frC : frB
8298         assign( frD,
8299                 IRExpr_ITE(
8300                    binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
8301                    mkexpr(frC),
8302                    mkexpr(frB) ));
8303
8304         /* One of the rare ones which don't mess with FPRF */
8305         set_FPRF = False;
8306         break;
8307      }
8308
8309      case 0x18: // fre (Floating Reciprocal Estimate)
8310         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8311         // Note: unclear whether this insn really exists or not
8312         // ppc970 doesn't have it, but POWER5 does
8313         if (frA_addr != 0 || frC_addr != 0)
8314            return False;
8315         DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
8316             frD_addr, frB_addr);
8317         { IRExpr* ieee_one
8318              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
8319           assign( frD, triop( Iop_DivF64,
8320                               rm,
8321                               ieee_one, mkexpr(frB) ));
8322         }
8323         break;
8324
8325      case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
8326         if (frB_addr != 0)
8327            vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
8328         DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8329             frD_addr, frA_addr, frC_addr);
8330         assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
8331         break;
8332
8333      case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
8334         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8335         if (frA_addr != 0 || frC_addr != 0)
8336            return False;
8337         DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
8338             frD_addr, frB_addr);
8339         assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
8340         break;
8341
8342      default:
8343         vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
8344         return False;
8345      }
8346      break;
8347
8348   default:
8349      vex_printf("dis_fp_arith(ppc)(opc1)\n");
8350      return False;
8351   }
8352
8353   putFReg( frD_addr, mkexpr(frD) );
8354
8355   if (set_FPRF) {
8356      // XXX XXX XXX FIXME
8357      // set FPRF from frD
8358   }
8359
8360   if (flag_rC && clear_CR1) {
8361      putCR321( 1, mkU8(0) );
8362      putCR0( 1, mkU8(0) );
8363   }
8364
8365   return True;
8366}
8367
8368
8369
8370/*
8371  Floating Point Mult-Add Instructions
8372*/
8373static Bool dis_fp_multadd ( UInt theInstr )
8374{
8375   /* A-Form */
8376   UChar opc1     = ifieldOPC(theInstr);
8377   UChar frD_addr = ifieldRegDS(theInstr);
8378   UChar frA_addr = ifieldRegA(theInstr);
8379   UChar frB_addr = ifieldRegB(theInstr);
8380   UChar frC_addr = ifieldRegC(theInstr);
8381   UChar opc2     = ifieldOPClo5(theInstr);
8382   UChar flag_rC  = ifieldBIT0(theInstr);
8383
8384   IRTemp  frD = newTemp(Ity_F64);
8385   IRTemp  frA = newTemp(Ity_F64);
8386   IRTemp  frB = newTemp(Ity_F64);
8387   IRTemp  frC = newTemp(Ity_F64);
8388   IRTemp  rmt = newTemp(Ity_I32);
8389   IRTemp  tmp = newTemp(Ity_F64);
8390   IRTemp  sign_tmp = newTemp(Ity_I64);
8391   IRTemp  nan_mask = newTemp(Ity_I32);
8392   IRExpr* rm;
8393
8394   /* By default, we will examine the results of the operation and set
8395      fpscr[FPRF] accordingly. */
8396   Bool set_FPRF = True;
8397
8398   /* By default, if flag_RC is set, we will clear cr1 after the
8399      operation.  In reality we should set cr1 to indicate the
8400      exception status of the operation, but since we're not
8401      simulating exceptions, the exception status will appear to be
8402      zero.  Hence cr1 should be cleared if this is a . form insn. */
8403   Bool clear_CR1 = True;
8404
8405   /* Bind the rounding mode expression to a temp; there's no
8406      point in creating gratuitous CSEs, as we know we'll need
8407      to use it twice. */
8408   assign( rmt, get_IR_roundingmode() );
8409   rm = mkexpr(rmt);
8410
8411   assign( frA, getFReg(frA_addr));
8412   assign( frB, getFReg(frB_addr));
8413   assign( frC, getFReg(frC_addr));
8414
8415   /* The rounding in this is all a bit dodgy.  The idea is to only do
8416      one rounding.  That clearly isn't achieveable without dedicated
8417      four-input IR primops, although in the single precision case we
8418      can sort-of simulate it by doing the inner multiply in double
8419      precision.
8420
8421      In the negated cases, the negation happens after rounding. */
8422
8423   switch (opc1) {
8424   case 0x3B:
8425      switch (opc2) {
8426      case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
8427         DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8428             frD_addr, frA_addr, frC_addr, frB_addr);
8429         assign( frD, qop( Iop_MSubF64r32, rm,
8430                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8431         break;
8432
8433      case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
8434         DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8435             frD_addr, frA_addr, frC_addr, frB_addr);
8436         assign( frD, qop( Iop_MAddF64r32, rm,
8437                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8438         break;
8439
8440      case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
8441      case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
8442
8443         if (opc2 == 0x1E) {
8444            DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8445                     frD_addr, frA_addr, frC_addr, frB_addr);
8446            assign( tmp, qop( Iop_MSubF64r32, rm,
8447                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8448         } else {
8449            DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8450                     frD_addr, frA_addr, frC_addr, frB_addr);
8451            assign( tmp, qop( Iop_MAddF64r32, rm,
8452                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8453         }
8454
8455         assign( nan_mask, Check_NaN( mkexpr( tmp ),
8456                                      mkU32( NANmaskSingle ) ) );
8457         assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
8458                                               mkexpr( nan_mask ) ) );
8459         assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
8460         break;
8461
8462      default:
8463         vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
8464         return False;
8465      }
8466      break;
8467
8468   case 0x3F:
8469      switch (opc2) {
8470      case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
8471         DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8472             frD_addr, frA_addr, frC_addr, frB_addr);
8473         assign( frD, qop( Iop_MSubF64, rm,
8474                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8475         break;
8476
8477      case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
8478         DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8479             frD_addr, frA_addr, frC_addr, frB_addr);
8480         assign( frD, qop( Iop_MAddF64, rm,
8481                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8482         break;
8483
8484      case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
8485      case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
8486
8487         if (opc2 == 0x1E) {
8488            DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8489                     frD_addr, frA_addr, frC_addr, frB_addr);
8490            assign( tmp, qop( Iop_MSubF64, rm,
8491                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8492         } else {
8493            DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8494                     frD_addr, frA_addr, frC_addr, frB_addr);
8495            assign( tmp, qop( Iop_MAddF64, rm,
8496                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8497         }
8498
8499         assign( nan_mask, Check_NaN( mkexpr( tmp ),
8500                                      mkU32( NANmaskDouble ) ) );
8501         assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
8502                                               mkexpr( nan_mask ) ) );
8503         assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
8504         break;
8505
8506      default:
8507         vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
8508         return False;
8509      }
8510      break;
8511
8512   default:
8513      vex_printf("dis_fp_multadd(ppc)(opc1)\n");
8514      return False;
8515   }
8516
8517   putFReg( frD_addr, mkexpr(frD) );
8518
8519   if (set_FPRF) {
8520      // XXX XXX XXX FIXME
8521      // set FPRF from frD
8522   }
8523
8524   if (flag_rC && clear_CR1) {
8525      putCR321( 1, mkU8(0) );
8526      putCR0( 1, mkU8(0) );
8527   }
8528
8529   return True;
8530}
8531
8532/*
8533 * fe_flag is set to 1 if any of the following conditions occurs:
8534 *  - The floating-point operand in register FRB is a Zero, a
8535 *    NaN, an Infinity, or a negative value.
8536 *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
8537 *  Otherwise fe_flag is set to 0.
8538 *
8539 * fg_flag is set to 1 if either of the following conditions occurs.
8540 *   - The floating-point operand in register FRB is a Zero, an
8541 *     Infinity, or a denormalized value.
8542 *  Otherwise fg_flag is set to 0.
8543 *
8544 */
8545static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
8546{
8547   // The following temps are for holding intermediate results
8548   IRTemp e_b = newTemp(Ity_I32);
8549   IRExpr * fe_flag,  * fg_flag;
8550   IRTemp frB_exp_shR = newTemp(Ity_I32);
8551   UInt bias = sp? 127 : 1023;
8552   IRExpr * frbNaN, * frbDenorm, * frBNeg;
8553   IRExpr * eb_LTE;
8554   IRTemp  frbZero_tmp = newTemp(Ity_I1);
8555   IRTemp  frbInf_tmp = newTemp(Ity_I1);
8556   *fe_flag_tmp = newTemp(Ity_I32);
8557   *fg_flag_tmp = newTemp(Ity_I32);
8558   assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
8559   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
8560
8561   //////////////////  fe_flag tests BEGIN //////////////////////
8562   /* We first do all tests that may result in setting fe_flag to '1'.
8563    * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
8564    * for details.)
8565    */
8566   frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
8567   assign( frbInf_tmp, is_Inf(frB_Int, sp) );
8568   assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
8569   {
8570      // Test_value = -970 for double precision
8571      UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
8572      eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
8573   }
8574   frBNeg = binop( Iop_CmpEQ32,
8575                   binop( Iop_Shr32,
8576                          sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
8577                          mkU8( 31 ) ),
8578                   mkU32( 1 ) );
8579   //////////////////  fe_flag tests END //////////////////////
8580
8581   //////////////////  fg_flag tests BEGIN //////////////////////
8582   /*
8583    * The following tests were already performed above in the fe_flag
8584    * tests.  So these conditions will result in both fe_ and fg_ flags
8585    * being set.
8586    *   - Test if FRB is Zero
8587    *   - Test if FRB is an Infinity
8588    */
8589
8590   /*
8591    * Test if FRB holds a denormalized value.  A denormalized value is one where
8592    * the exp is 0 and the fraction is non-zero.
8593    */
8594   if (sp) {
8595      IRTemp frac_part = newTemp(Ity_I32);
8596      assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
8597      frbDenorm
8598               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8599                         binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
8600   } else {
8601      IRExpr * hi32, * low32, * fraction_is_nonzero;
8602      IRTemp frac_part = newTemp(Ity_I64);
8603
8604      assign( frac_part, FP_FRAC_PART(frB_Int) );
8605      hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8606      low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8607      fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8608                                                mkU32( 0 ) );
8609      frbDenorm
8610               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8611                         fraction_is_nonzero );
8612   }
8613   //////////////////  fg_flag tests END //////////////////////
8614
8615   /////////////////////////
8616   fe_flag = mkOR1( mkexpr( frbZero_tmp ),
8617                    mkOR1( frbNaN,
8618                           mkOR1( mkexpr( frbInf_tmp ),
8619                                  mkOR1( frBNeg, eb_LTE ) ) ) );
8620
8621   fe_flag = unop(Iop_1Uto32, fe_flag);
8622
8623   fg_flag = mkOR1( mkexpr( frbZero_tmp ),
8624                    mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
8625   fg_flag = unop(Iop_1Uto32, fg_flag);
8626   assign (*fg_flag_tmp, fg_flag);
8627   assign (*fe_flag_tmp, fe_flag);
8628}
8629/*
8630 * fe_flag is set to 1 if any of the following conditions occurs:
8631 *  - The double-precision floating-point operand in register FRA is a NaN or an
8632 *    Infinity.
8633 *  - The double-precision floating-point operand in register FRB is a Zero, a
8634 *    NaN, or an Infinity.
8635 *  - e_b is less than or equal to -1022.
8636 *  - e_b is greater than or equal to 1021.
8637 *  - The double-precision floating-point operand in register FRA is not a zero
8638 *    and the difference, e_a - e_b, is greater than or equal to 1023.
8639 *  - The double-precision floating-point operand in register FRA is not a zero
8640 *    and the difference, e_a - e_b, is less than or equal to -1021.
8641 *  - The double-precision floating-point operand in register FRA is not a zero
8642 *    and e_a is less than or equal to -970
8643 *  Otherwise fe_flag is set to 0.
8644 *
8645 * fg_flag is set to 1 if either of the following conditions occurs.
8646 *   - The double-precision floating-point operand in register FRA is an Infinity.
8647 *   - The double-precision floating-point operand in register FRB is a Zero, an
8648 *     Infinity, or a denormalized value.
8649 *  Otherwise fg_flag is set to 0.
8650 *
8651 */
8652static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
8653{
8654   // The following temps are for holding intermediate results
8655   IRTemp e_a = newTemp(Ity_I32);
8656   IRTemp e_b = newTemp(Ity_I32);
8657   IRTemp frA_exp_shR = newTemp(Ity_I32);
8658   IRTemp frB_exp_shR = newTemp(Ity_I32);
8659
8660   UInt bias = sp? 127 : 1023;
8661   *fe_flag_tmp = newTemp(Ity_I32);
8662   *fg_flag_tmp = newTemp(Ity_I32);
8663
8664   /* The following variables hold boolean results from tests
8665    * that are OR'ed together for setting the fe_ and fg_ flags.
8666    * For some cases, the booleans are used more than once, so
8667    * I make those IRTemp's instead of IRExpr's.
8668    */
8669   IRExpr * fraNaN, * frbNaN, * frbDenorm;
8670   IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
8671   IRTemp  fraInf_tmp = newTemp(Ity_I1);
8672   IRTemp  frbZero_tmp = newTemp(Ity_I1);
8673   IRTemp  frbInf_tmp = newTemp(Ity_I1);
8674   IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
8675
8676/* The following are the flags that are set by OR'ing the results of
8677 * all the tests done for tdiv.  These flags are the input to the specified CR.
8678 */
8679   IRExpr * fe_flag, * fg_flag;
8680
8681   // Create temps that will be used throughout the following tests.
8682   assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
8683   assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
8684   /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
8685   assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
8686   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
8687
8688
8689   //////////////////  fe_flag tests BEGIN //////////////////////
8690   /* We first do all tests that may result in setting fe_flag to '1'. */
8691
8692   /*
8693    * Test if the double-precision floating-point operand in register FRA is
8694    * a NaN:
8695    */
8696   fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
8697   /*
8698    * Test if the double-precision floating-point operand in register FRA is
8699    * an Infinity.
8700    */
8701   assign(fraInf_tmp, is_Inf(frA_int, sp));
8702
8703   /*
8704    * Test if the double-precision floating-point operand in register FRB is
8705    * a NaN:
8706    */
8707   frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
8708   /*
8709    * Test if the double-precision floating-point operand in register FRB is
8710    * an Infinity.
8711    */
8712   assign( frbInf_tmp, is_Inf(frB_int, sp) );
8713   /*
8714    * Test if the double-precision floating-point operand in register FRB is
8715    * a Zero.
8716    */
8717   assign( frbZero_tmp, is_Zero(frB_int, sp) );
8718
8719   /*
8720    * Test if e_b <= -1022 for double precision;
8721    * or e_b <= -126 for single precision
8722    */
8723   {
8724      UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
8725      eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
8726   }
8727
8728   /*
8729    * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
8730    * or e_b >= -125 (125 < e_b) for single precision
8731    */
8732   {
8733      Int test_value = sp ? 125 : 1021;
8734      eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
8735   }
8736
8737   /*
8738    * Test if FRA != Zero and (e_a - e_b) >= bias
8739    */
8740   assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
8741   ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
8742                       binop( Iop_CmpLT32S, mkU32( bias ),
8743                              binop( Iop_Sub32, mkexpr( e_a ),
8744                                     mkexpr( e_b ) ) ) );
8745
8746   /*
8747    * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
8748    */
8749   {
8750      UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
8751
8752      ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
8753                          binop( Iop_CmpLE32S,
8754                                 binop( Iop_Sub32,
8755                                        mkexpr( e_a ),
8756                                        mkexpr( e_b ) ),
8757                                        mkU32( test_value ) ) );
8758   }
8759
8760   /*
8761    * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
8762    */
8763   {
8764      UInt test_value = 0xfffffc36;  //Int test_value = -970;
8765
8766      ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
8767                                                        mkexpr( e_a ),
8768                                                        mkU32( test_value ) ) );
8769   }
8770   //////////////////  fe_flag tests END //////////////////////
8771
8772   //////////////////  fg_flag tests BEGIN //////////////////////
8773   /*
8774    * The following tests were already performed above in the fe_flag
8775    * tests.  So these conditions will result in both fe_ and fg_ flags
8776    * being set.
8777    *   - Test if FRA is an Infinity
8778    *   - Test if FRB ix Zero
8779    *   - Test if FRB is an Infinity
8780    */
8781
8782   /*
8783    * Test if FRB holds a denormalized value.  A denormalized value is one where
8784    * the exp is 0 and the fraction is non-zero.
8785    */
8786   {
8787      IRExpr * fraction_is_nonzero;
8788
8789      if (sp) {
8790         fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
8791                                      mkU32( 0 ) );
8792      } else {
8793         IRExpr * hi32, * low32;
8794         IRTemp frac_part = newTemp(Ity_I64);
8795         assign( frac_part, FP_FRAC_PART(frB_int) );
8796
8797         hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8798         low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8799         fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8800                                      mkU32( 0 ) );
8801      }
8802      frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
8803                                 mkU32( 0x0 ) ), fraction_is_nonzero );
8804
8805   }
8806   //////////////////  fg_flag tests END //////////////////////
8807
8808   fe_flag
8809   = mkOR1(
8810            fraNaN,
8811            mkOR1(
8812                   mkexpr( fraInf_tmp ),
8813                   mkOR1(
8814                          mkexpr( frbZero_tmp ),
8815                          mkOR1(
8816                                 frbNaN,
8817                                 mkOR1(
8818                                        mkexpr( frbInf_tmp ),
8819                                        mkOR1( eb_LTE,
8820                                               mkOR1( eb_GTE,
8821                                                      mkOR1( ea_eb_GTE,
8822                                                             mkOR1( ea_eb_LTE,
8823                                                                    ea_LTE ) ) ) ) ) ) ) ) );
8824
8825   fe_flag = unop(Iop_1Uto32, fe_flag);
8826
8827   fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
8828                                                 mkOR1( mkexpr( frbInf_tmp ),
8829                                                        frbDenorm ) ) );
8830   fg_flag = unop(Iop_1Uto32, fg_flag);
8831   assign(*fe_flag_tmp, fe_flag);
8832   assign(*fg_flag_tmp, fg_flag);
8833}
8834
8835/* See description for _do_fp_tdiv() above. */
8836static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
8837{
8838   IRTemp  fe_flag, fg_flag;
8839   /////////////////////////
8840   /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8841    * where fl_flag == 1 on ppc64.
8842    */
8843   IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
8844   fe_flag = fg_flag = IRTemp_INVALID;
8845   _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
8846   return binop( Iop_Or32,
8847                 binop( Iop_Or32,
8848                        binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
8849                        binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8850                 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
8851}
8852
8853static Bool dis_fp_tests ( UInt theInstr )
8854{
8855   UChar opc1     = ifieldOPC(theInstr);
8856   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
8857   UChar frB_addr = ifieldRegB(theInstr);
8858   UChar b0       = ifieldBIT0(theInstr);
8859   UInt  opc2     = ifieldOPClo10(theInstr);
8860   IRTemp frB_I64     = newTemp(Ity_I64);
8861
8862   if (opc1 != 0x3F || b0 != 0 ){
8863      vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
8864      return False;
8865   }
8866   assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
8867
8868   switch (opc2) {
8869      case 0x080: // ftdiv
8870      {
8871         UChar frA_addr = ifieldRegA(theInstr);
8872         IRTemp frA_I64     = newTemp(Ity_I64);
8873         UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
8874         if (b21to22 != 0 ) {
8875            vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
8876            return False;
8877         }
8878
8879         assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
8880         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
8881
8882         DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
8883         break;
8884      }
8885      case 0x0A0: // ftsqrt
8886      {
8887         IRTemp flags = newTemp(Ity_I32);
8888         IRTemp  fe_flag, fg_flag;
8889         fe_flag = fg_flag = IRTemp_INVALID;
8890         UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
8891         if ( b18to22 != 0) {
8892            vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
8893            return False;
8894         }
8895         DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
8896         do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
8897         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8898          * where fl_flag == 1 on ppc64.
8899          */
8900         assign( flags,
8901                 binop( Iop_Or32,
8902                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
8903                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8904                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
8905         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
8906         break;
8907      }
8908
8909      default:
8910         vex_printf("dis_fp_tests(ppc)(opc2)\n");
8911         return False;
8912
8913   }
8914   return True;
8915}
8916
8917/*
8918  Floating Point Compare Instructions
8919*/
8920static Bool dis_fp_cmp ( UInt theInstr )
8921{
8922   /* X-Form */
8923   UChar opc1     = ifieldOPC(theInstr);
8924   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
8925   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
8926   UChar frA_addr = ifieldRegA(theInstr);
8927   UChar frB_addr = ifieldRegB(theInstr);
8928   UInt  opc2     = ifieldOPClo10(theInstr);
8929   UChar b0       = ifieldBIT0(theInstr);
8930
8931   IRTemp ccIR    = newTemp(Ity_I32);
8932   IRTemp ccPPC32 = newTemp(Ity_I32);
8933
8934   IRTemp frA     = newTemp(Ity_F64);
8935   IRTemp frB     = newTemp(Ity_F64);
8936
8937   if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
8938      vex_printf("dis_fp_cmp(ppc)(instr)\n");
8939      return False;
8940   }
8941
8942   assign( frA, getFReg(frA_addr));
8943   assign( frB, getFReg(frB_addr));
8944
8945   assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
8946
8947   /* Map compare result from IR to PPC32 */
8948   /*
8949     FP cmp result | PPC | IR
8950     --------------------------
8951     UN            | 0x1 | 0x45
8952     EQ            | 0x2 | 0x40
8953     GT            | 0x4 | 0x00
8954     LT            | 0x8 | 0x01
8955   */
8956
8957   // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
8958   //                    | ((ccIR ^ (ccIR>>6)) & 1)
8959   assign(
8960      ccPPC32,
8961      binop(
8962         Iop_Shl32,
8963         mkU32(1),
8964         unop(
8965            Iop_32to8,
8966            binop(
8967               Iop_Or32,
8968               binop(
8969                  Iop_And32,
8970                  unop(
8971                     Iop_Not32,
8972                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
8973                  ),
8974                  mkU32(2)
8975               ),
8976               binop(
8977                  Iop_And32,
8978                  binop(
8979                     Iop_Xor32,
8980                     mkexpr(ccIR),
8981                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
8982                  ),
8983                  mkU32(1)
8984               )
8985            )
8986         )
8987      )
8988   );
8989
8990   putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
8991
8992   /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
8993      putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
8994   */
8995   // XXX XXX XXX FIXME
8996   // Also write the result into FPRF (it's not entirely clear how)
8997
8998   /* Note: Differences between fcmpu and fcmpo are only in exception
8999      flag settings, which aren't supported anyway. */
9000   switch (opc2) {
9001   case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
9002      DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
9003      break;
9004   case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
9005      DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
9006      break;
9007   default:
9008      vex_printf("dis_fp_cmp(ppc)(opc2)\n");
9009      return False;
9010   }
9011   return True;
9012}
9013
9014
9015
9016/*
9017  Floating Point Rounding/Conversion Instructions
9018*/
9019static Bool dis_fp_round ( UInt theInstr )
9020{
9021   /* X-Form */
9022   UChar opc1     = ifieldOPC(theInstr);
9023   UChar b16to20  = ifieldRegA(theInstr);
9024   UChar frD_addr = ifieldRegDS(theInstr);
9025   UChar frB_addr = ifieldRegB(theInstr);
9026   UInt  opc2     = ifieldOPClo10(theInstr);
9027   UChar flag_rC  = ifieldBIT0(theInstr);
9028
9029   IRTemp  frD     = newTemp(Ity_F64);
9030   IRTemp  frB     = newTemp(Ity_F64);
9031   IRTemp  r_tmp32 = newTemp(Ity_I32);
9032   IRTemp  r_tmp64 = newTemp(Ity_I64);
9033   IRExpr* rm      = get_IR_roundingmode();
9034
9035   /* By default, we will examine the results of the operation and set
9036      fpscr[FPRF] accordingly. */
9037   Bool set_FPRF = True;
9038
9039   /* By default, if flag_RC is set, we will clear cr1 after the
9040      operation.  In reality we should set cr1 to indicate the
9041      exception status of the operation, but since we're not
9042      simulating exceptions, the exception status will appear to be
9043      zero.  Hence cr1 should be cleared if this is a . form insn. */
9044   Bool clear_CR1 = True;
9045   if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
9046      vex_printf("dis_fp_round(ppc)(instr)\n");
9047      return False;
9048   }
9049
9050   assign( frB, getFReg(frB_addr));
9051   if (opc1 == 0x3B) {
9052      /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
9053       * they're very similar to the other instructions handled here, but have
9054       * a different primary opcode.
9055       */
9056      switch (opc2) {
9057         case 0x34E: // fcfids (Float convert from signed DWord to single precision)
9058            DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9059            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9060            assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
9061                                                              mkexpr( r_tmp64 ) ) ) );
9062            goto putFR;
9063
9064         case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
9065            DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9066            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9067            assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
9068            goto putFR;
9069      }
9070   }
9071
9072
9073   switch (opc2) {
9074   case 0x00C: // frsp (Float Round to Single, PPC32 p423)
9075      DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9076      assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
9077      break;
9078
9079   case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
9080      DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9081      assign( r_tmp32,
9082              binop(Iop_F64toI32S, rm, mkexpr(frB)) );
9083      assign( frD, unop( Iop_ReinterpI64asF64,
9084                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
9085      /* FPRF is undefined after fctiw.  Leave unchanged. */
9086      set_FPRF = False;
9087      break;
9088
9089   case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
9090      DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9091      assign( r_tmp32,
9092              binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
9093      assign( frD, unop( Iop_ReinterpI64asF64,
9094                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
9095      /* FPRF is undefined after fctiwz.  Leave unchanged. */
9096      set_FPRF = False;
9097      break;
9098
9099   case 0x08F: case 0x08E: // fctiwu[z]
9100      DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
9101               flag_rC ? ".":"", frD_addr, frB_addr);
9102      assign( r_tmp32,
9103              binop( Iop_F64toI32U,
9104                     opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
9105                     mkexpr( frB ) ) );
9106      assign( frD, unop( Iop_ReinterpI64asF64,
9107                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
9108      /* FPRF is undefined after fctiwz.  Leave unchanged. */
9109      set_FPRF = False;
9110      break;
9111
9112
9113   case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
9114      DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9115      assign( r_tmp64,
9116              binop(Iop_F64toI64S, rm, mkexpr(frB)) );
9117      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
9118      /* FPRF is undefined after fctid.  Leave unchanged. */
9119      set_FPRF = False;
9120      break;
9121
9122   case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
9123      DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9124      assign( r_tmp64,
9125              binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
9126      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
9127      /* FPRF is undefined after fctidz.  Leave unchanged. */
9128      set_FPRF = False;
9129      break;
9130
9131   case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
9132   {
9133      DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
9134               flag_rC ? ".":"", frD_addr, frB_addr);
9135      assign( r_tmp64,
9136              binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
9137      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
9138      /* FPRF is undefined after fctidz.  Leave unchanged. */
9139      set_FPRF = False;
9140      break;
9141   }
9142   case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
9143      DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9144      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9145      assign( frD,
9146              binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
9147      break;
9148
9149   case 0x3CE: // fcfidu (Float convert from unsigned DWord)
9150      DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9151      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9152      assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
9153      break;
9154
9155   case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
9156      switch(opc2) {
9157      case 0x188: // frin (Floating Round to Integer Nearest)
9158         DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9159         assign( r_tmp64,
9160                 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
9161         break;
9162      case 0x1A8: // friz (Floating Round to Integer Toward Zero)
9163         DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9164         assign( r_tmp64,
9165                 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
9166         break;
9167      case 0x1C8: // frip (Floating Round to Integer Plus)
9168         DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9169         assign( r_tmp64,
9170                 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
9171         break;
9172      case 0x1E8: // frim (Floating Round to Integer Minus)
9173         DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9174         assign( r_tmp64,
9175                 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
9176         break;
9177      }
9178
9179      /* don't use the rounded integer if frB is outside -9e18..9e18 */
9180      /* F64 has only log10(2**52) significant digits anyway */
9181      /* need to preserve sign of zero */
9182      /*   frD = (fabs(frB) > 9e18) ? frB :
9183               (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
9184      assign(frD, IRExpr_ITE(
9185                     binop(Iop_CmpNE8,
9186                           unop(Iop_32to8,
9187                                binop(Iop_CmpF64,
9188                                      IRExpr_Const(IRConst_F64(9e18)),
9189                                      unop(Iop_AbsF64, mkexpr(frB)))),
9190                           mkU8(0)),
9191                     mkexpr(frB),
9192                     IRExpr_ITE(
9193                        binop(Iop_CmpNE32,
9194                              binop(Iop_Shr32,
9195                                    unop(Iop_64HIto32,
9196                                         unop(Iop_ReinterpF64asI64,
9197                                              mkexpr(frB))),
9198                                    mkU8(31)),
9199                              mkU32(0)),
9200                        unop(Iop_NegF64,
9201                             unop( Iop_AbsF64,
9202                                   binop(Iop_I64StoF64, mkU32(0),
9203                                         mkexpr(r_tmp64)) )),
9204                        binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
9205                     )
9206      ));
9207      break;
9208
9209   default:
9210      vex_printf("dis_fp_round(ppc)(opc2)\n");
9211      return False;
9212   }
9213putFR:
9214   putFReg( frD_addr, mkexpr(frD) );
9215
9216   if (set_FPRF) {
9217      // XXX XXX XXX FIXME
9218      // set FPRF from frD
9219   }
9220
9221   if (flag_rC && clear_CR1) {
9222      putCR321( 1, mkU8(0) );
9223      putCR0( 1, mkU8(0) );
9224   }
9225
9226   return True;
9227}
9228
9229/*
9230  Floating Point Pair Instructions
9231*/
9232static Bool dis_fp_pair ( UInt theInstr )
9233{
9234   /* X-Form/DS-Form */
9235   UChar  opc1         = ifieldOPC(theInstr);
9236   UChar  frT_hi_addr  = ifieldRegDS(theInstr);
9237   UChar  frT_lo_addr  = frT_hi_addr + 1;
9238   UChar  rA_addr      = ifieldRegA(theInstr);
9239   UChar  rB_addr      = ifieldRegB(theInstr);
9240   UInt  uimm16        = ifieldUIMM16(theInstr);
9241   Int    simm16       = extend_s_16to32(uimm16);
9242   UInt   opc2         = ifieldOPClo10(theInstr);
9243   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
9244   IRTemp EA_hi        = newTemp(ty);
9245   IRTemp EA_lo        = newTemp(ty);
9246   IRTemp frT_hi       = newTemp(Ity_F64);
9247   IRTemp frT_lo       = newTemp(Ity_F64);
9248   UChar b0            = ifieldBIT0(theInstr);
9249   Bool is_load        = 0;
9250
9251   if ((frT_hi_addr %2) != 0) {
9252      vex_printf("dis_fp_pair(ppc) : odd frT register\n");
9253      return False;
9254   }
9255
9256   switch (opc1) {
9257   case 0x1F: // register offset
9258      switch(opc2) {
9259      case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
9260         DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
9261         is_load = 1;
9262         break;
9263      case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
9264         DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
9265         break;
9266      default:
9267         vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
9268         return False;
9269      }
9270
9271      if (b0 != 0) {
9272         vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
9273         return False;
9274      }
9275      assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
9276      break;
9277   case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
9278      DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
9279      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
9280      is_load = 1;
9281      break;
9282   case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
9283      DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
9284      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
9285      break;
9286   default:   // immediate offset
9287      vex_printf("dis_fp_pair(ppc)(instr)\n");
9288      return False;
9289   }
9290
9291   if (mode64)
9292      assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
9293   else
9294      assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
9295
9296   assign( frT_hi, getFReg(frT_hi_addr) );
9297   assign( frT_lo, getFReg(frT_lo_addr) );
9298
9299   if (is_load) {
9300      putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) );
9301      putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) );
9302   } else {
9303      store( mkexpr(EA_hi), mkexpr(frT_hi) );
9304      store( mkexpr(EA_lo), mkexpr(frT_lo) );
9305   }
9306
9307   return True;
9308}
9309
9310
9311/*
9312  Floating Point Merge Instructions
9313*/
9314static Bool dis_fp_merge ( UInt theInstr )
9315{
9316   /* X-Form */
9317   UInt  opc2     = ifieldOPClo10(theInstr);
9318   UChar frD_addr = ifieldRegDS(theInstr);
9319   UChar frA_addr = ifieldRegA(theInstr);
9320   UChar frB_addr = ifieldRegB(theInstr);
9321
9322   IRTemp frD = newTemp(Ity_F64);
9323   IRTemp frA = newTemp(Ity_F64);
9324   IRTemp frB = newTemp(Ity_F64);
9325
9326   assign( frA, getFReg(frA_addr));
9327   assign( frB, getFReg(frB_addr));
9328
9329   switch (opc2) {
9330   case 0x3c6: // fmrgew floating merge even word
9331      DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
9332
9333      assign( frD, unop( Iop_ReinterpI64asF64,
9334                         binop( Iop_32HLto64,
9335                                unop( Iop_64HIto32,
9336                                      unop( Iop_ReinterpF64asI64,
9337                                            mkexpr(frA) ) ),
9338                                unop( Iop_64HIto32,
9339                                      unop( Iop_ReinterpF64asI64,
9340                                            mkexpr(frB) ) ) ) ) );
9341   break;
9342
9343   case 0x346: // fmrgow floating merge odd word
9344      DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
9345
9346      assign( frD, unop( Iop_ReinterpI64asF64,
9347                         binop( Iop_32HLto64,
9348                                unop( Iop_64to32,
9349                                      unop( Iop_ReinterpF64asI64,
9350                                            mkexpr(frA) ) ),
9351                                unop( Iop_64to32,
9352                                      unop( Iop_ReinterpF64asI64,
9353                                            mkexpr(frB) ) ) ) ) );
9354   break;
9355
9356   default:
9357      vex_printf("dis_fp_merge(ppc)(opc2)\n");
9358      return False;
9359   }
9360
9361   putFReg( frD_addr, mkexpr(frD) );
9362   return True;
9363}
9364
9365/*
9366  Floating Point Move Instructions
9367*/
9368static Bool dis_fp_move ( UInt theInstr )
9369{
9370   /* X-Form */
9371   UChar opc1     = ifieldOPC(theInstr);
9372   UChar frD_addr = ifieldRegDS(theInstr);
9373   UChar frA_addr = ifieldRegA(theInstr);
9374   UChar frB_addr = ifieldRegB(theInstr);
9375   UInt  opc2     = ifieldOPClo10(theInstr);
9376   UChar flag_rC  = ifieldBIT0(theInstr);
9377
9378   IRTemp frD = newTemp(Ity_F64);
9379   IRTemp frB = newTemp(Ity_F64);
9380   IRTemp itmpB = newTemp(Ity_F64);
9381   IRTemp frA;
9382   IRTemp signA;
9383   IRTemp hiD;
9384
9385   if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
9386      vex_printf("dis_fp_move(ppc)(instr)\n");
9387      return False;
9388   }
9389
9390   assign( frB, getFReg(frB_addr));
9391
9392   switch (opc2) {
9393   case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
9394      DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
9395          frB_addr);
9396      signA = newTemp(Ity_I32);
9397      hiD = newTemp(Ity_I32);
9398      itmpB = newTemp(Ity_I64);
9399      frA = newTemp(Ity_F64);
9400      assign( frA, getFReg(frA_addr) );
9401
9402      /* get A's sign bit */
9403      assign(signA, binop(Iop_And32,
9404                          unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
9405                                                  mkexpr(frA))),
9406                          mkU32(0x80000000)) );
9407
9408      assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
9409
9410      /* mask off B's sign bit and or in A's sign bit */
9411      assign(hiD, binop(Iop_Or32,
9412                        binop(Iop_And32,
9413                              unop(Iop_64HIto32,
9414                                   mkexpr(itmpB)),  /* frB's high 32 bits */
9415                              mkU32(0x7fffffff)),
9416                        mkexpr(signA)) );
9417
9418      /* combine hiD/loB into frD */
9419      assign( frD, unop(Iop_ReinterpI64asF64,
9420                        binop(Iop_32HLto64,
9421                              mkexpr(hiD),
9422                              unop(Iop_64to32,
9423                                   mkexpr(itmpB)))) );   /* frB's low 32 bits */
9424      break;
9425
9426   case 0x028: // fneg (Floating Negate, PPC32 p416)
9427      DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9428      assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
9429      break;
9430
9431   case 0x048: // fmr (Floating Move Register, PPC32 p410)
9432      DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9433      assign( frD, mkexpr(frB) );
9434      break;
9435
9436   case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
9437      DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9438      assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
9439      break;
9440
9441   case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
9442      DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9443      assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
9444      break;
9445
9446   default:
9447      vex_printf("dis_fp_move(ppc)(opc2)\n");
9448      return False;
9449   }
9450
9451   putFReg( frD_addr, mkexpr(frD) );
9452
9453   /* None of these change FPRF.  cr1 is set in the usual way though,
9454      if flag_rC is set. */
9455
9456   if (flag_rC) {
9457      putCR321( 1, mkU8(0) );
9458      putCR0( 1, mkU8(0) );
9459   }
9460
9461   return True;
9462}
9463
9464
9465
9466/*
9467  Floating Point Status/Control Register Instructions
9468*/
9469static Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
9470{
9471   /* Many forms - see each switch case */
9472   UChar opc1    = ifieldOPC(theInstr);
9473   UInt  opc2    = ifieldOPClo10(theInstr);
9474   UChar flag_rC = ifieldBIT0(theInstr);
9475
9476   if (opc1 != 0x3F) {
9477      vex_printf("dis_fp_scr(ppc)(instr)\n");
9478      return False;
9479   }
9480
9481   switch (opc2) {
9482   case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
9483      // Bit crbD of the FPSCR is set.
9484      UChar crbD    = ifieldRegDS(theInstr);
9485      UInt  b11to20 = IFIELD(theInstr, 11, 10);
9486
9487      if (b11to20 != 0) {
9488         vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
9489         return False;
9490      }
9491      DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
9492      putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
9493		     1ULL << ( 31 - crbD ) );
9494      break;
9495   }
9496
9497   case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
9498      UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
9499      UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
9500      UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
9501      UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
9502      IRTemp  tmp     = newTemp(Ity_I32);
9503      IRExpr* fpscr_all;
9504      if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
9505         vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
9506         return False;
9507      }
9508      DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
9509      vassert(crfD < 8);
9510      vassert(crfS < 8);
9511      fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9512      assign( tmp, binop(Iop_And32,
9513                         binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
9514                        mkU32(0xF)) );
9515      putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
9516      break;
9517   }
9518
9519   case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
9520      // Bit crbD of the FPSCR is cleared.
9521      UChar crbD    = ifieldRegDS(theInstr);
9522      UInt  b11to20 = IFIELD(theInstr, 11, 10);
9523
9524      if (b11to20 != 0) {
9525         vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
9526         return False;
9527      }
9528      DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
9529      putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
9530      break;
9531   }
9532
9533   case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
9534      UInt crfD     = IFIELD( theInstr, 23, 3 );
9535      UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
9536      UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
9537      UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
9538      UChar Wbit;
9539
9540      if (b16to22 != 0 || b11 != 0) {
9541         vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
9542         return False;
9543      }
9544      DIP("mtfsfi%s crf%u,%d\n", flag_rC ? ".":"", crfD, IMM);
9545      if (GX_level) {
9546         /* This implies that Decimal Floating Point is supported, and the
9547          * FPSCR must be managed as a 64-bit register.
9548          */
9549         Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9550      } else {
9551         Wbit = 0;
9552      }
9553      crfD = crfD + (8 * (1 - Wbit) );
9554      putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
9555      break;
9556   }
9557
9558   case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
9559      UChar   frD_addr  = ifieldRegDS(theInstr);
9560      UInt    b11to20   = IFIELD(theInstr, 11, 10);
9561      IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9562      IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR,
9563                                                 MASK_FPSCR_DRN );
9564
9565      if (b11to20 != 0) {
9566         vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
9567         return False;
9568      }
9569      DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
9570      putFReg( frD_addr,
9571          unop( Iop_ReinterpI64asF64,
9572                binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
9573      break;
9574   }
9575
9576   case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
9577      UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
9578      UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
9579      UChar frB_addr = ifieldRegB(theInstr);
9580      IRTemp frB   = newTemp(Ity_F64);
9581      IRTemp rB_64 = newTemp( Ity_I64 );
9582      Int i;
9583      ULong mask;
9584      UChar Wbit;
9585#define BFP_MASK_SEED 0x3000000000000000ULL
9586#define DFP_MASK_SEED 0x7000000000000000ULL
9587
9588      if (GX_level) {
9589         /* This implies that Decimal Floating Point is supported, and the
9590          * FPSCR must be managed as a 64-bit register.
9591          */
9592         Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9593      } else {
9594         Wbit = 0;
9595      }
9596
9597      if (b25 == 1) {
9598         /* new 64 bit move variant for power 6.  If L field (bit 25) is
9599          * a one do a full 64 bit move.  Note, the FPSCR is not really
9600          * properly modeled.  This instruciton only changes the value of
9601          * the rounding mode.  The HW exception bits do not get set in
9602          * the simulator.  1/12/09
9603          */
9604         DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
9605         mask = 0xFF;
9606
9607      } else {
9608         DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
9609         // Build 32bit mask from FM:
9610         mask = 0;
9611         for (i=0; i<8; i++) {
9612            if ((FM & (1<<(7-i))) == 1) {
9613               /* FPSCR field k is set to the contents of the corresponding
9614                * field of register FRB, where k = i+8x(1-W).  In the Power
9615                * ISA, register field numbering is from left to right, so field
9616                * 15 is the least significant field in a 64-bit register.  To
9617                * generate the mask, we set all the appropriate rounding mode
9618                * bits in the highest order nibble (field 0) and shift right
9619                * 'k x nibble length'.
9620                */
9621               if (Wbit)
9622                  mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
9623               else
9624                  mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
9625            }
9626         }
9627      }
9628      assign( frB, getFReg(frB_addr));
9629      assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
9630      putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
9631      break;
9632   }
9633
9634   default:
9635      vex_printf("dis_fp_scr(ppc)(opc2)\n");
9636      return False;
9637   }
9638   return True;
9639}
9640
9641/*------------------------------------------------------------*/
9642/*--- Decimal Floating Point (DFP)  Helper functions       ---*/
9643/*------------------------------------------------------------*/
9644#define DFP_LONG  1
9645#define DFP_EXTND 2
9646#define DFP_LONG_BIAS   398
9647#define DFP_LONG_ENCODED_FIELD_MASK  0x1F00
9648#define DFP_EXTND_BIAS  6176
9649#define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
9650#define DFP_LONG_EXP_MSK   0XFF
9651#define DFP_EXTND_EXP_MSK  0XFFF
9652
9653#define DFP_G_FIELD_LONG_MASK     0x7FFC0000  // upper 32-bits only
9654#define DFP_LONG_GFIELD_RT_SHIFT  (63 - 13 - 32) // adj for upper 32-bits
9655#define DFP_G_FIELD_EXTND_MASK    0x7FFFC000  // upper 32-bits only
9656#define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
9657#define DFP_T_FIELD_LONG_MASK     0x3FFFF  // mask for upper 32-bits
9658#define DFP_T_FIELD_EXTND_MASK    0x03FFFF // mask for upper 32-bits
9659#define DFP_LONG_EXP_MAX          369      // biased max
9660#define DFP_LONG_EXP_MIN          0        // biased min
9661#define DFP_EXTND_EXP_MAX         6111     // biased max
9662#define DFP_EXTND_EXP_MIN         0        // biased min
9663#define DFP_LONG_MAX_SIG_DIGITS   16
9664#define DFP_EXTND_MAX_SIG_DIGITS  34
9665#define MAX_DIGITS_IN_STRING      8
9666
9667
9668#define  AND(x, y) binop( Iop_And32, x, y )
9669#define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
9670#define   OR(x, y) binop( Iop_Or32,  x, y )
9671#define  OR3(x, y, z)    OR( x, OR( y, z ) )
9672#define  OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
9673#define  NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1,  mkexpr( x ) ) ) )
9674
9675#define  SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
9676#define  SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
9677
9678#define BITS5(_b4,_b3,_b2,_b1,_b0) \
9679   (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
9680    ((_b1) << 1) | ((_b0) << 0))
9681
9682static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
9683{
9684   IRTemp lmd_07_mask   = newTemp( Ity_I32 );
9685   IRTemp lmd_8_mask    = newTemp( Ity_I32 );
9686   IRTemp lmd_9_mask    = newTemp( Ity_I32 );
9687   IRTemp lmexp_00_mask = newTemp( Ity_I32 );
9688   IRTemp lmexp_01_mask = newTemp( Ity_I32 );
9689   IRTemp lmexp_10_mask = newTemp( Ity_I32 );
9690   IRTemp lmd_07_val    = newTemp( Ity_I32 );
9691   IRTemp lmd_8_val     = newTemp( Ity_I32 );
9692   IRTemp lmd_9_val     = newTemp( Ity_I32 );
9693
9694   /* The encodig is as follows:
9695    * lmd - left most digit
9696    * lme - left most 2-bits of the exponent
9697    *
9698    *    lmd
9699    *   0 - 7    (lmexp << 3) | lmd
9700    *     8      0b11000 (24 decimal) if lme=0b00;
9701    *            0b11010 (26 decimal) if lme=0b01;
9702    *            0b11100 (28 decimal) if lme=0b10;
9703    *     9      0b11001 (25 decimal) if lme=0b00;
9704    *            0b11011 (27 decimal) if lme=0b01;
9705    *            0b11101 (29 decimal) if lme=0b10;
9706    */
9707
9708   /* Generate the masks for each condition */
9709   assign( lmd_07_mask,
9710           unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
9711   assign( lmd_8_mask,
9712           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
9713   assign( lmd_9_mask,
9714           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
9715   assign( lmexp_00_mask,
9716           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
9717   assign( lmexp_01_mask,
9718           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
9719   assign( lmexp_10_mask,
9720           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
9721
9722   /* Generate the values for each LMD condition, assuming the condition
9723    * is TRUE.
9724    */
9725   assign( lmd_07_val,
9726           binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
9727   assign( lmd_8_val,
9728           binop( Iop_Or32,
9729                  binop( Iop_Or32,
9730                         binop( Iop_And32,
9731                                mkexpr( lmexp_00_mask ),
9732                                mkU32( 24 ) ),
9733                         binop( Iop_And32,
9734                                mkexpr( lmexp_01_mask ),
9735                                mkU32( 26 ) ) ),
9736                  binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
9737   assign( lmd_9_val,
9738           binop( Iop_Or32,
9739                  binop( Iop_Or32,
9740                         binop( Iop_And32,
9741                                mkexpr( lmexp_00_mask ),
9742                                mkU32( 25 ) ),
9743                         binop( Iop_And32,
9744                                mkexpr( lmexp_01_mask ),
9745                                mkU32( 27 ) ) ),
9746                  binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
9747
9748   /* generate the result from the possible LMD values */
9749   return binop( Iop_Or32,
9750                 binop( Iop_Or32,
9751                        binop( Iop_And32,
9752                               mkexpr( lmd_07_mask ),
9753                               mkexpr( lmd_07_val ) ),
9754                        binop( Iop_And32,
9755                               mkexpr( lmd_8_mask ),
9756                               mkexpr( lmd_8_val ) ) ),
9757                 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
9758}
9759
9760static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
9761{
9762   /* Extract the exponent and the left most digit of the mantissa
9763    * from the G field bits [0:4].
9764    */
9765   IRTemp lmd_07_mask   = newTemp( Ity_I32 );
9766   IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
9767   IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
9768   IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
9769   IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
9770   IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
9771   IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
9772
9773   IRTemp lmd_07_val = newTemp( Ity_I32 );
9774   IRTemp lmd_8_val  = newTemp( Ity_I32 );
9775   IRTemp lmd_9_val  = newTemp( Ity_I32 );
9776
9777   /* The left most digit (LMD) encoding is as follows:
9778    *    lmd
9779    *   0 - 7    (lmexp << 3) | lmd
9780    *     8      0b11000 (24 decimal) if lme=0b00;
9781    *            0b11010 (26 decimal) if lme=0b01;
9782    *            0b11100 (28 decimal) if lme=0b10
9783    *     9      0b11001 (25 decimal) if lme=0b00;
9784    *            0b11011 (27 decimal) if lme=0b01;
9785    *            0b11101 (29 decimal) if lme=0b10;
9786    */
9787
9788   /* Generate the masks for each condition of LMD and exponent bits */
9789   assign( lmd_07_mask,
9790           unop( Iop_1Sto32, binop( Iop_CmpLE32U,
9791                                    gfield_0_4,
9792                                    mkU32( BITS5(1,0,1,1,1) ) ) ) );
9793   assign( lmd_8_00_mask,
9794           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9795                                    gfield_0_4,
9796                                    mkU32( BITS5(1,1,0,0,0) ) ) ) );
9797   assign( lmd_8_01_mask,
9798           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9799                                    gfield_0_4,
9800                                    mkU32( BITS5(1,1,0,1,0) ) ) ) );
9801   assign( lmd_8_10_mask,
9802           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9803                                    gfield_0_4,
9804                                    mkU32( BITS5(1,1,1,0,0) ) ) ) );
9805   assign( lmd_9_00_mask,
9806           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9807                                    gfield_0_4,
9808                                    mkU32( BITS5(1,1,0,0,1) ) ) ) );
9809   assign( lmd_9_01_mask,
9810           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9811                                    gfield_0_4,
9812                                    mkU32( BITS5(1,1,0,1,1) ) ) ) );
9813   assign( lmd_9_10_mask,
9814           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9815                                    gfield_0_4,
9816                                    mkU32( BITS5(1,1,1,0,1) ) ) ) );
9817
9818   /* Generate the values for each LMD condition, assuming the condition
9819    * is TRUE.
9820    */
9821   assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
9822   assign( lmd_8_val, mkU32( 0x8 ) );
9823   assign( lmd_9_val, mkU32( 0x9 ) );
9824
9825   assign( *lmd,
9826           OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
9827                     AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
9828                     AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
9829                     OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
9830                          AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
9831                          AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
9832                          AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
9833                     ) ) );
9834}
9835
9836#define DIGIT1_SHR 4    // shift digit 1 to bottom 4 bits
9837#define DIGIT2_SHR 8    // shift digit 2 to bottom 4 bits
9838#define DIGIT3_SHR 12
9839#define DIGIT4_SHR 16
9840#define DIGIT5_SHR 20
9841#define DIGIT6_SHR 24
9842#define DIGIT7_SHR 28
9843
9844static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
9845{
9846   /* 60-bit BCD string stored in two 32-bit values.  Check that each,
9847    * digit is a valid BCD number, i.e. less then 9.
9848    */
9849   IRTemp valid = newTemp( Ity_I32 );
9850
9851   assign( valid,
9852           AND4( AND4 ( unop( Iop_1Sto32,
9853                              binop( Iop_CmpLE32U,
9854                                     binop( Iop_And32,
9855                                            bcd_l,
9856                                            mkU32 ( 0xF ) ),
9857                                      mkU32( 0x9 ) ) ),
9858                        unop( Iop_1Sto32,
9859                              binop( Iop_CmpLE32U,
9860                                     binop( Iop_And32,
9861                                            binop( Iop_Shr32,
9862                                                   bcd_l,
9863                                                   mkU8 ( DIGIT1_SHR ) ),
9864                                             mkU32 ( 0xF ) ),
9865                                      mkU32( 0x9 ) ) ),
9866                        unop( Iop_1Sto32,
9867                              binop( Iop_CmpLE32U,
9868                                     binop( Iop_And32,
9869                                            binop( Iop_Shr32,
9870                                                   bcd_l,
9871                                                   mkU8 ( DIGIT2_SHR ) ),
9872                                            mkU32 ( 0xF ) ),
9873                                      mkU32( 0x9 ) ) ),
9874                        unop( Iop_1Sto32,
9875                              binop( Iop_CmpLE32U,
9876                                     binop( Iop_And32,
9877                                            binop( Iop_Shr32,
9878                                                   bcd_l,
9879                                                   mkU8 ( DIGIT3_SHR ) ),
9880                                             mkU32 ( 0xF ) ),
9881                                      mkU32( 0x9 ) ) ) ),
9882                 AND4 ( unop( Iop_1Sto32,
9883                              binop( Iop_CmpLE32U,
9884                                     binop( Iop_And32,
9885                                            binop( Iop_Shr32,
9886                                                   bcd_l,
9887                                                   mkU8 ( DIGIT4_SHR ) ),
9888                                            mkU32 ( 0xF ) ),
9889                                     mkU32( 0x9 ) ) ),
9890                        unop( Iop_1Sto32,
9891                              binop( Iop_CmpLE32U,
9892                                     binop( Iop_And32,
9893                                            binop( Iop_Shr32,
9894                                                   bcd_l,
9895                                                   mkU8 ( DIGIT5_SHR ) ),
9896                                            mkU32 ( 0xF ) ),
9897                                     mkU32( 0x9 ) ) ),
9898                        unop( Iop_1Sto32,
9899                              binop( Iop_CmpLE32U,
9900                                     binop( Iop_And32,
9901                                            binop( Iop_Shr32,
9902                                                   bcd_l,
9903                                                   mkU8 ( DIGIT6_SHR ) ),
9904                                            mkU32 ( 0xF ) ),
9905                                     mkU32( 0x9 ) ) ),
9906                        unop( Iop_1Sto32,
9907                              binop( Iop_CmpLE32U,
9908                                     binop( Iop_And32,
9909                                            binop( Iop_Shr32,
9910                                                   bcd_l,
9911                                                   mkU8 ( DIGIT7_SHR ) ),
9912                                            mkU32 ( 0xF ) ),
9913                                     mkU32( 0x9 ) ) ) ),
9914                 AND4( unop( Iop_1Sto32,
9915                             binop( Iop_CmpLE32U,
9916                                    binop( Iop_And32,
9917                                           bcd_u,
9918                                           mkU32 ( 0xF ) ),
9919                                    mkU32( 0x9 ) ) ),
9920                       unop( Iop_1Sto32,
9921                             binop( Iop_CmpLE32U,
9922                                    binop( Iop_And32,
9923                                           binop( Iop_Shr32,
9924                                                  bcd_u,
9925                                                  mkU8 ( DIGIT1_SHR ) ),
9926                                           mkU32 ( 0xF ) ),
9927                                    mkU32( 0x9 ) ) ),
9928                       unop( Iop_1Sto32,
9929                             binop( Iop_CmpLE32U,
9930                                    binop( Iop_And32,
9931                                           binop( Iop_Shr32,
9932                                                  bcd_u,
9933                                                  mkU8 ( DIGIT2_SHR ) ),
9934                                           mkU32 ( 0xF ) ),
9935                                    mkU32( 0x9 ) ) ),
9936                       unop( Iop_1Sto32,
9937                             binop( Iop_CmpLE32U,
9938                                    binop( Iop_And32,
9939                                           binop( Iop_Shr32,
9940                                                  bcd_u,
9941                                                  mkU8 ( DIGIT3_SHR ) ),
9942                                           mkU32 ( 0xF ) ),
9943                                    mkU32( 0x9 ) ) ) ),
9944                 AND4( unop( Iop_1Sto32,
9945                             binop( Iop_CmpLE32U,
9946                                    binop( Iop_And32,
9947                                           binop( Iop_Shr32,
9948                                                  bcd_u,
9949                                                  mkU8 ( DIGIT4_SHR ) ),
9950                                           mkU32 ( 0xF ) ),
9951                                    mkU32( 0x9 ) ) ),
9952                       unop( Iop_1Sto32,
9953                             binop( Iop_CmpLE32U,
9954                                    binop( Iop_And32,
9955                                           binop( Iop_Shr32,
9956                                                  bcd_u,
9957                                                  mkU8 ( DIGIT5_SHR ) ),
9958                                           mkU32 ( 0xF ) ),
9959                                    mkU32( 0x9 ) ) ),
9960                       unop( Iop_1Sto32,
9961                             binop( Iop_CmpLE32U,
9962                                    binop( Iop_And32,
9963                                           binop( Iop_Shr32,
9964                                                  bcd_u,
9965                                                  mkU8 ( DIGIT6_SHR ) ),
9966                                           mkU32 ( 0xF ) ),
9967                                    mkU32( 0x9 ) ) ),
9968                       unop( Iop_1Sto32,
9969                             binop( Iop_CmpLE32U,
9970                                    binop( Iop_And32,
9971                                           binop( Iop_Shr32,
9972                                                  bcd_u,
9973                                                  mkU8 ( DIGIT7_SHR ) ),
9974                                           mkU32 ( 0xF ) ),
9975                                    mkU32( 0x9 ) ) ) ) ) );
9976
9977   return unop( Iop_Not32, mkexpr( valid ) );
9978}
9979#undef DIGIT1_SHR
9980#undef DIGIT2_SHR
9981#undef DIGIT3_SHR
9982#undef DIGIT4_SHR
9983#undef DIGIT5_SHR
9984#undef DIGIT6_SHR
9985#undef DIGIT7_SHR
9986
9987static IRExpr * Generate_neg_sign_mask( IRExpr * sign )
9988{
9989   return binop( Iop_Or32,
9990                 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
9991                 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
9992               );
9993}
9994
9995static IRExpr * Generate_pos_sign_mask( IRExpr * sign )
9996{
9997   return binop( Iop_Or32,
9998                 binop( Iop_Or32,
9999                        unop( Iop_1Sto32,
10000                              binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
10001                        unop( Iop_1Sto32,
10002                              binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
10003                 binop( Iop_Or32,
10004                        unop( Iop_1Sto32,
10005                              binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
10006                        unop( Iop_1Sto32,
10007                              binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
10008}
10009
10010static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
10011                                   IRExpr * neg_sign_mask )
10012{
10013   return binop( Iop_Or32,
10014                 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
10015                 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
10016}
10017
10018static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
10019                                   IRExpr * pos_sign_mask,
10020                                   IRExpr * neg_sign_mask )
10021/* first argument is all 1's if the BCD string had an invalid digit in it. */
10022{
10023   return binop( Iop_Or32,
10024                 invalid_bcd_mask,
10025                 unop( Iop_1Sto32,
10026                       binop( Iop_CmpEQ32,
10027                              binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
10028                              mkU32( 0x0 ) ) ) );
10029}
10030
10031static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
10032                                         IRTemp * top_12_l, IRTemp * mid_60_u,
10033                                         IRTemp * mid_60_l, IRTemp * low_60_u,
10034                                         IRTemp * low_60_l)
10035{
10036   IRTemp tmplow60 = newTemp( Ity_I64 );
10037   IRTemp tmpmid60 = newTemp( Ity_I64 );
10038   IRTemp tmptop12 = newTemp( Ity_I64 );
10039   IRTemp low_50   = newTemp( Ity_I64 );
10040   IRTemp mid_50   = newTemp( Ity_I64 );
10041   IRTemp top_10   = newTemp( Ity_I64 );
10042   IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
10043
10044   /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
10045
10046   /* low_50[49:0] = ((frBI64_lo[49:32]  << 14) | frBI64_lo[31:0]) */
10047   assign( low_50,
10048           binop( Iop_32HLto64,
10049                  binop( Iop_And32,
10050                         unop( Iop_64HIto32, frBI64_lo ),
10051                         mkU32( 0x3FFFF ) ),
10052                         unop( Iop_64to32, frBI64_lo ) ) );
10053
10054   /* Convert the 50 bit densely packed BCD string to a 60 bit
10055    * BCD string.
10056    */
10057   assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
10058   assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
10059   assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
10060
10061   /* mid_50[49:0] =  ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
10062    *                 ((frBI64_hi[17:0]  << 14) | frBI64_lo[63:50])
10063    */
10064   assign( mid_50,
10065           binop( Iop_32HLto64,
10066                  binop( Iop_Or32,
10067                         binop( Iop_Shl32,
10068                                binop( Iop_And32,
10069                                       unop( Iop_64HIto32, frBI64_hi ),
10070                                       mkU32( 0xF ) ),
10071                                mkU8( 14 ) ),
10072                         binop( Iop_Shr32,
10073                                unop( Iop_64to32, frBI64_hi ),
10074                                mkU8( 18 ) ) ),
10075                  binop( Iop_Or32,
10076                         binop( Iop_Shl32,
10077                                unop( Iop_64to32, frBI64_hi ),
10078                                mkU8( 14 ) ),
10079                         binop( Iop_Shr32,
10080                                unop( Iop_64HIto32, frBI64_lo ),
10081                                mkU8( 18 ) ) ) ) );
10082
10083   /* Convert the 50 bit densely packed BCD string to a 60 bit
10084    * BCD string.
10085    */
10086   assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
10087   assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
10088   assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
10089
10090   /* top_10[49:0] = frBI64_hi[45:36]) |  */
10091   assign( top_10,
10092           binop( Iop_32HLto64,
10093                  mkU32( 0 ),
10094                  binop( Iop_And32,
10095                         binop( Iop_Shr32,
10096                                unop( Iop_64HIto32, frBI64_hi ),
10097                                mkU8( 4 ) ),
10098                         mkU32( 0x3FF ) ) ) );
10099
10100   /* Convert the 10 bit densely packed BCD string to a 12 bit
10101    * BCD string.
10102    */
10103   assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
10104   assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
10105   assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
10106}
10107
10108static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
10109                         IRTemp * final_cnt, IRTemp * final_flag,
10110                         IRExpr * string )
10111{
10112   IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
10113   int digits = MAX_DIGITS_IN_STRING;
10114   int i;
10115
10116   cnt[start-1] = newTemp( Ity_I8 );
10117   flag[start-1] = newTemp( Ity_I8 );
10118   assign( cnt[start-1], init_cnt);
10119   assign( flag[start-1], init_flag);
10120
10121   for ( i = start; i <= digits; i++) {
10122      cnt[i] = newTemp( Ity_I8 );
10123      flag[i] = newTemp( Ity_I8 );
10124      assign( cnt[i],
10125              binop( Iop_Add8,
10126                     mkexpr( cnt[i-1] ),
10127                     binop(Iop_And8,
10128                           unop( Iop_1Uto8,
10129                                 binop(Iop_CmpEQ32,
10130                                       binop(Iop_And32,
10131                                             string,
10132                                             mkU32( 0xF <<
10133                                                    ( ( digits - i ) * 4) ) ),
10134                                       mkU32( 0 ) ) ),
10135                           binop( Iop_Xor8, /* complement flag */
10136                                  mkexpr( flag[i - 1] ),
10137                                  mkU8( 0xFF ) ) ) ) );
10138
10139      /* set flag to 1 if digit was not a zero */
10140      assign( flag[i],
10141              binop(Iop_Or8,
10142                    unop( Iop_1Sto8,
10143                          binop(Iop_CmpNE32,
10144                                binop(Iop_And32,
10145                                      string,
10146                                      mkU32( 0xF <<
10147                                             ( (digits - i) * 4) ) ),
10148                                mkU32( 0 ) ) ),
10149                    mkexpr( flag[i - 1] ) ) );
10150   }
10151
10152   *final_cnt = cnt[digits];
10153   *final_flag = flag[digits];
10154}
10155
10156static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
10157                                        IRExpr * low_32 )
10158{
10159   IRTemp num_lmd    = newTemp( Ity_I8 );
10160   IRTemp num_upper  = newTemp( Ity_I8 );
10161   IRTemp num_low    = newTemp( Ity_I8 );
10162   IRTemp lmd_flag   = newTemp( Ity_I8 );
10163   IRTemp upper_flag = newTemp( Ity_I8 );
10164   IRTemp low_flag   = newTemp( Ity_I8 );
10165
10166   assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
10167   assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
10168
10169   Count_zeros( 2,
10170                mkexpr( num_lmd ),
10171                mkexpr( lmd_flag ),
10172                &num_upper,
10173                &upper_flag,
10174                upper_28 );
10175
10176   Count_zeros( 1,
10177                mkexpr( num_upper ),
10178                mkexpr( upper_flag ),
10179                &num_low,
10180                &low_flag,
10181                low_32 );
10182
10183   return mkexpr( num_low );
10184}
10185
10186static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
10187                                         IRExpr * mid_60_u, IRExpr * mid_60_l,
10188                                         IRExpr * low_60_u, IRExpr * low_60_l)
10189{
10190   IRTemp num_lmd   = newTemp( Ity_I8 );
10191   IRTemp num_top   = newTemp( Ity_I8 );
10192   IRTemp num_mid_u = newTemp( Ity_I8 );
10193   IRTemp num_mid_l = newTemp( Ity_I8 );
10194   IRTemp num_low_u = newTemp( Ity_I8 );
10195   IRTemp num_low_l = newTemp( Ity_I8 );
10196
10197   IRTemp lmd_flag   = newTemp( Ity_I8 );
10198   IRTemp top_flag   = newTemp( Ity_I8 );
10199   IRTemp mid_u_flag = newTemp( Ity_I8 );
10200   IRTemp mid_l_flag = newTemp( Ity_I8 );
10201   IRTemp low_u_flag = newTemp( Ity_I8 );
10202   IRTemp low_l_flag = newTemp( Ity_I8 );
10203
10204   /* Check the LMD, digit 16, to see if it is zero. */
10205   assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
10206
10207   assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
10208
10209   Count_zeros( 6,
10210                mkexpr( num_lmd ),
10211                mkexpr( lmd_flag ),
10212                &num_top,
10213                &top_flag,
10214                top_12_l );
10215
10216   Count_zeros( 1,
10217                mkexpr( num_top ),
10218                mkexpr( top_flag ),
10219                &num_mid_u,
10220                &mid_u_flag,
10221                binop( Iop_Or32,
10222                       binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
10223                       binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
10224
10225   Count_zeros( 2,
10226                mkexpr( num_mid_u ),
10227                mkexpr( mid_u_flag ),
10228                &num_mid_l,
10229                &mid_l_flag,
10230                mid_60_l );
10231
10232   Count_zeros( 1,
10233                mkexpr( num_mid_l ),
10234                mkexpr( mid_l_flag ),
10235                &num_low_u,
10236                &low_u_flag,
10237                binop( Iop_Or32,
10238                       binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
10239                       binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
10240
10241   Count_zeros( 2,
10242                mkexpr( num_low_u ),
10243                mkexpr( low_u_flag ),
10244                &num_low_l,
10245                &low_l_flag,
10246                low_60_l );
10247
10248   return mkexpr( num_low_l );
10249}
10250
10251static IRExpr * Check_unordered(IRExpr * val)
10252{
10253   IRTemp gfield0to5 = newTemp( Ity_I32 );
10254
10255   /* Extract G[0:4] */
10256   assign( gfield0to5,
10257           binop( Iop_And32,
10258                  binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
10259                  mkU32( 0x1F ) ) );
10260
10261   /* Check for unordered, return all 1'x if true */
10262   return binop( Iop_Or32, /* QNaN check */
10263                 unop( Iop_1Sto32,
10264                       binop( Iop_CmpEQ32,
10265                              mkexpr( gfield0to5 ),
10266                              mkU32( 0x1E ) ) ),
10267                              unop( Iop_1Sto32, /* SNaN check */
10268                                    binop( Iop_CmpEQ32,
10269                                           mkexpr( gfield0to5 ),
10270                                           mkU32( 0x1F ) ) ) );
10271}
10272
10273#undef AND
10274#undef AND4
10275#undef OR
10276#undef OR3
10277#undef OR4
10278#undef NOT
10279#undef SHR
10280#undef SHL
10281#undef BITS5
10282
10283/*------------------------------------------------------------*/
10284/*--- Decimal Floating Point (DFP) instruction translation ---*/
10285/*------------------------------------------------------------*/
10286
10287/* DFP Arithmetic instructions */
10288static Bool dis_dfp_arith(UInt theInstr)
10289{
10290   UInt opc2 = ifieldOPClo10( theInstr );
10291   UChar frS_addr = ifieldRegDS( theInstr );
10292   UChar frA_addr = ifieldRegA( theInstr );
10293   UChar frB_addr = ifieldRegB( theInstr );
10294   UChar flag_rC = ifieldBIT0( theInstr );
10295
10296   IRTemp frA = newTemp( Ity_D64 );
10297   IRTemp frB = newTemp( Ity_D64 );
10298   IRTemp frS = newTemp( Ity_D64 );
10299   IRExpr* round = get_IR_roundingmode_DFP();
10300
10301   /* By default, if flag_RC is set, we will clear cr1 after the
10302    * operation.  In reality we should set cr1 to indicate the
10303    * exception status of the operation, but since we're not
10304    * simulating exceptions, the exception status will appear to be
10305    * zero.  Hence cr1 should be cleared if this is a . form insn.
10306    */
10307   Bool clear_CR1 = True;
10308
10309   assign( frA, getDReg( frA_addr ) );
10310   assign( frB, getDReg( frB_addr ) );
10311
10312   switch (opc2) {
10313   case 0x2: // dadd
10314      DIP( "dadd%s fr%u,fr%u,fr%u\n",
10315           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10316      assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10317      break;
10318   case 0x202: // dsub
10319      DIP( "dsub%s fr%u,fr%u,fr%u\n",
10320           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10321      assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10322      break;
10323   case 0x22: // dmul
10324      DIP( "dmul%s fr%u,fr%u,fr%u\n",
10325           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10326      assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10327      break;
10328   case 0x222: // ddiv
10329      DIP( "ddiv%s fr%u,fr%u,fr%u\n",
10330           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10331      assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10332      break;
10333   }
10334
10335   putDReg( frS_addr, mkexpr( frS ) );
10336
10337   if (flag_rC && clear_CR1) {
10338      putCR321( 1, mkU8( 0 ) );
10339      putCR0( 1, mkU8( 0 ) );
10340   }
10341
10342   return True;
10343}
10344
10345/* Quad DFP Arithmetic instructions */
10346static Bool dis_dfp_arithq(UInt theInstr)
10347{
10348   UInt opc2 = ifieldOPClo10( theInstr );
10349   UChar frS_addr = ifieldRegDS( theInstr );
10350   UChar frA_addr = ifieldRegA( theInstr );
10351   UChar frB_addr = ifieldRegB( theInstr );
10352   UChar flag_rC = ifieldBIT0( theInstr );
10353
10354   IRTemp frA = newTemp( Ity_D128 );
10355   IRTemp frB = newTemp( Ity_D128 );
10356   IRTemp frS = newTemp( Ity_D128 );
10357   IRExpr* round = get_IR_roundingmode_DFP();
10358
10359   /* By default, if flag_RC is set, we will clear cr1 after the
10360    * operation.  In reality we should set cr1 to indicate the
10361    * exception status of the operation, but since we're not
10362    * simulating exceptions, the exception status will appear to be
10363    * zero.  Hence cr1 should be cleared if this is a . form insn.
10364    */
10365   Bool clear_CR1 = True;
10366
10367   assign( frA, getDReg_pair( frA_addr ) );
10368   assign( frB, getDReg_pair( frB_addr ) );
10369
10370   switch (opc2) {
10371   case 0x2: // daddq
10372      DIP( "daddq%s fr%u,fr%u,fr%u\n",
10373           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10374      assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10375      break;
10376   case 0x202: // dsubq
10377      DIP( "dsubq%s fr%u,fr%u,fr%u\n",
10378           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10379      assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10380      break;
10381   case 0x22: // dmulq
10382      DIP( "dmulq%s fr%u,fr%u,fr%u\n",
10383           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10384      assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10385      break;
10386   case 0x222: // ddivq
10387      DIP( "ddivq%s fr%u,fr%u,fr%u\n",
10388           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10389      assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10390      break;
10391   }
10392
10393   putDReg_pair( frS_addr, mkexpr( frS ) );
10394
10395   if (flag_rC && clear_CR1) {
10396      putCR321( 1, mkU8( 0 ) );
10397      putCR0( 1, mkU8( 0 ) );
10398   }
10399
10400   return True;
10401}
10402
10403/* DFP 64-bit logical shift instructions  */
10404static Bool dis_dfp_shift(UInt theInstr) {
10405   UInt opc2       = ifieldOPClo9( theInstr );
10406   UChar frS_addr  = ifieldRegDS( theInstr );
10407   UChar frA_addr  = ifieldRegA( theInstr );
10408   UChar shift_val = IFIELD(theInstr, 10, 6);
10409   UChar flag_rC   = ifieldBIT0( theInstr );
10410
10411   IRTemp frA = newTemp( Ity_D64 );
10412   IRTemp frS = newTemp( Ity_D64 );
10413   Bool clear_CR1 = True;
10414
10415   assign( frA, getDReg( frA_addr ) );
10416
10417   switch (opc2) {
10418   case 0x42: // dscli
10419      DIP( "dscli%s fr%u,fr%u,%u\n",
10420           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10421      assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
10422      break;
10423   case 0x62: // dscri
10424      DIP( "dscri%s fr%u,fr%u,%u\n",
10425           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10426      assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
10427      break;
10428   }
10429
10430   putDReg( frS_addr, mkexpr( frS ) );
10431
10432   if (flag_rC && clear_CR1) {
10433      putCR321( 1, mkU8( 0 ) );
10434      putCR0( 1, mkU8( 0 ) );
10435   }
10436
10437   return True;
10438}
10439
10440/* Quad DFP  logical shift instructions  */
10441static Bool dis_dfp_shiftq(UInt theInstr) {
10442   UInt opc2       = ifieldOPClo9( theInstr );
10443   UChar frS_addr  = ifieldRegDS( theInstr );
10444   UChar frA_addr  = ifieldRegA( theInstr );
10445   UChar shift_val = IFIELD(theInstr, 10, 6);
10446   UChar flag_rC   = ifieldBIT0( theInstr );
10447
10448   IRTemp frA = newTemp( Ity_D128 );
10449   IRTemp frS = newTemp( Ity_D128 );
10450   Bool clear_CR1 = True;
10451
10452   assign( frA, getDReg_pair( frA_addr ) );
10453
10454   switch (opc2) {
10455   case 0x42: // dscliq
10456      DIP( "dscliq%s fr%u,fr%u,%u\n",
10457           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10458      assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
10459      break;
10460   case 0x62: // dscriq
10461      DIP( "dscriq%s fr%u,fr%u,%u\n",
10462           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10463      assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
10464      break;
10465   }
10466
10467   putDReg_pair( frS_addr, mkexpr( frS ) );
10468
10469   if (flag_rC && clear_CR1) {
10470      putCR321( 1, mkU8( 0 ) );
10471      putCR0( 1, mkU8( 0 ) );
10472   }
10473
10474   return True;
10475}
10476
10477/* DFP 64-bit format conversion instructions */
10478static Bool dis_dfp_fmt_conv(UInt theInstr) {
10479   UInt opc2      = ifieldOPClo10( theInstr );
10480   UChar frS_addr = ifieldRegDS( theInstr );
10481   UChar frB_addr = ifieldRegB( theInstr );
10482   IRExpr* round  = get_IR_roundingmode_DFP();
10483   UChar flag_rC  = ifieldBIT0( theInstr );
10484   IRTemp frB;
10485   IRTemp frS;
10486   Bool clear_CR1 = True;
10487
10488   switch (opc2) {
10489   case 0x102: //dctdp
10490      DIP( "dctdp%s fr%u,fr%u\n",
10491           flag_rC ? ".":"", frS_addr, frB_addr );
10492
10493      frB = newTemp( Ity_D32 );
10494      frS = newTemp( Ity_D64 );
10495      assign( frB, getDReg32( frB_addr ) );
10496      assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
10497      putDReg( frS_addr, mkexpr( frS ) );
10498      break;
10499   case 0x302: // drsp
10500      DIP( "drsp%s fr%u,fr%u\n",
10501           flag_rC ? ".":"", frS_addr, frB_addr );
10502      frB = newTemp( Ity_D64 );
10503      frS = newTemp( Ity_D32 );
10504      assign( frB, getDReg( frB_addr ) );
10505      assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
10506      putDReg32( frS_addr, mkexpr( frS ) );
10507      break;
10508   case 0x122: // dctfix
10509      {
10510         IRTemp tmp = newTemp( Ity_I64 );
10511
10512         DIP( "dctfix%s fr%u,fr%u\n",
10513              flag_rC ? ".":"", frS_addr, frB_addr );
10514         frB = newTemp( Ity_D64 );
10515         frS = newTemp( Ity_D64 );
10516         assign( frB, getDReg( frB_addr ) );
10517         assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
10518         assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10519         putDReg( frS_addr, mkexpr( frS ) );
10520      }
10521      break;
10522   case 0x322: // dcffix
10523      DIP( "dcffix%s fr%u,fr%u\n",
10524           flag_rC ? ".":"", frS_addr, frB_addr );
10525      frB = newTemp( Ity_D64 );
10526      frS = newTemp( Ity_D64 );
10527      assign( frB, getDReg( frB_addr ) );
10528      assign( frS, binop( Iop_I64StoD64,
10529                          round,
10530                          unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
10531      putDReg( frS_addr, mkexpr( frS ) );
10532      break;
10533   }
10534
10535   if (flag_rC && clear_CR1) {
10536      putCR321( 1, mkU8( 0 ) );
10537      putCR0( 1, mkU8( 0 ) );
10538   }
10539
10540   return True;
10541}
10542
10543/* Quad DFP format conversion instructions */
10544static Bool dis_dfp_fmt_convq(UInt theInstr) {
10545   UInt opc2      = ifieldOPClo10( theInstr );
10546   UChar frS_addr = ifieldRegDS( theInstr );
10547   UChar frB_addr = ifieldRegB( theInstr );
10548   IRExpr* round  = get_IR_roundingmode_DFP();
10549   IRTemp frB64   = newTemp( Ity_D64 );
10550   IRTemp frB128  = newTemp( Ity_D128 );
10551   IRTemp frS64   = newTemp( Ity_D64 );
10552   IRTemp frS128  = newTemp( Ity_D128 );
10553   UChar flag_rC  = ifieldBIT0( theInstr );
10554   Bool clear_CR1 = True;
10555
10556   switch (opc2) {
10557   case 0x102: // dctqpq
10558      DIP( "dctqpq%s fr%u,fr%u\n",
10559           flag_rC ? ".":"", frS_addr, frB_addr );
10560      assign( frB64, getDReg( frB_addr ) );
10561      assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
10562      putDReg_pair( frS_addr, mkexpr( frS128 ) );
10563      break;
10564   case 0x122: // dctfixq
10565      {
10566         IRTemp tmp = newTemp( Ity_I64 );
10567
10568         DIP( "dctfixq%s fr%u,fr%u\n",
10569              flag_rC ? ".":"", frS_addr, frB_addr );
10570         assign( frB128, getDReg_pair( frB_addr ) );
10571         assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
10572         assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10573         putDReg( frS_addr, mkexpr( frS64 ) );
10574      }
10575      break;
10576   case 0x302: //drdpq
10577      DIP( "drdpq%s fr%u,fr%u\n",
10578           flag_rC ? ".":"", frS_addr, frB_addr );
10579      assign( frB128, getDReg_pair( frB_addr ) );
10580      assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
10581      putDReg( frS_addr, mkexpr( frS64 ) );
10582      break;
10583   case 0x322: // dcffixq
10584     {
10585      /* Have to introduce an IOP for this instruction so it will work
10586       * on POWER 6 because emulating the instruction requires a POWER 7
10587       * DFP instruction in the emulation code.
10588       */
10589      DIP( "dcffixq%s fr%u,fr%u\n",
10590           flag_rC ? ".":"", frS_addr, frB_addr );
10591      assign( frB64, getDReg( frB_addr ) );
10592      assign( frS128, unop( Iop_I64StoD128,
10593                            unop( Iop_ReinterpD64asI64,
10594                                  mkexpr( frB64 ) ) ) );
10595      putDReg_pair( frS_addr, mkexpr( frS128 ) );
10596      break;
10597     }
10598   }
10599
10600   if (flag_rC && clear_CR1) {
10601      putCR321( 1, mkU8( 0 ) );
10602      putCR0( 1, mkU8( 0 ) );
10603   }
10604
10605   return True;
10606}
10607
10608static Bool dis_dfp_round( UInt theInstr ) {
10609   UChar frS_addr = ifieldRegDS(theInstr);
10610   UChar R        = IFIELD(theInstr, 16, 1);
10611   UChar RMC      = IFIELD(theInstr, 9, 2);
10612   UChar frB_addr = ifieldRegB( theInstr );
10613   UChar flag_rC  = ifieldBIT0( theInstr );
10614   IRTemp frB     = newTemp( Ity_D64 );
10615   IRTemp frS     = newTemp( Ity_D64 );
10616   UInt opc2      = ifieldOPClo8( theInstr );
10617   Bool clear_CR1 = True;
10618
10619   switch (opc2) {
10620   /* drintn, is the same as drintx.  The only difference is this
10621    * instruction does not generate an exception for an inexact operation.
10622    * Currently not supporting inexact exceptions.
10623    */
10624   case 0x63: // drintx
10625   case 0xE3: // drintn
10626      DIP( "drintx/drintn%s fr%u,fr%u\n",
10627           flag_rC ? ".":"", frS_addr, frB_addr );
10628
10629      /* NOTE, this instruction takes a DFP value and rounds to the
10630       * neares floating point integer value, i.e. fractional part
10631       * is zero.  The result is a floating point number.
10632       */
10633      /* pass the value of R and RMC in the same field */
10634      assign( frB, getDReg( frB_addr ) );
10635      assign( frS, binop( Iop_RoundD64toInt,
10636                          mkU32( ( R << 3 ) | RMC ),
10637                          mkexpr( frB ) ) );
10638      putDReg( frS_addr, mkexpr( frS ) );
10639      break;
10640   default:
10641      vex_printf("dis_dfp_round(ppc)(opc2)\n");
10642      return False;
10643   }
10644
10645   if (flag_rC && clear_CR1) {
10646      putCR321( 1, mkU8( 0 ) );
10647      putCR0( 1, mkU8( 0 ) );
10648   }
10649
10650   return True;
10651}
10652
10653static Bool dis_dfp_roundq(UInt theInstr) {
10654   UChar frS_addr = ifieldRegDS( theInstr );
10655   UChar frB_addr = ifieldRegB( theInstr );
10656   UChar R = IFIELD(theInstr, 16, 1);
10657   UChar RMC = IFIELD(theInstr, 9, 2);
10658   UChar flag_rC = ifieldBIT0( theInstr );
10659   IRTemp frB = newTemp( Ity_D128 );
10660   IRTemp frS = newTemp( Ity_D128 );
10661   Bool clear_CR1 = True;
10662   UInt opc2 = ifieldOPClo8( theInstr );
10663
10664   switch (opc2) {
10665   /* drintnq, is the same as drintxq.  The only difference is this
10666    * instruction does not generate an exception for an inexact operation.
10667    * Currently not supporting inexact exceptions.
10668    */
10669   case 0x63: // drintxq
10670   case 0xE3: // drintnq
10671      DIP( "drintxq/drintnq%s fr%u,fr%u\n",
10672           flag_rC ? ".":"", frS_addr, frB_addr );
10673
10674      /* pass the value of R and RMC in the same field */
10675      assign( frB, getDReg_pair( frB_addr ) );
10676      assign( frS, binop( Iop_RoundD128toInt,
10677                          mkU32( ( R << 3 ) | RMC ),
10678                          mkexpr( frB ) ) );
10679      putDReg_pair( frS_addr, mkexpr( frS ) );
10680      break;
10681   default:
10682      vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
10683      return False;
10684   }
10685
10686   if (flag_rC && clear_CR1) {
10687      putCR321( 1, mkU8( 0 ) );
10688      putCR0( 1, mkU8( 0 ) );
10689   }
10690
10691   return True;
10692}
10693
10694static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
10695   UInt opc2 = ifieldOPClo8( theInstr );
10696   UChar frS_addr = ifieldRegDS( theInstr );
10697   UChar frA_addr = ifieldRegA( theInstr );
10698   UChar frB_addr = ifieldRegB( theInstr );
10699   UChar flag_rC = ifieldBIT0( theInstr );
10700   UInt TE_value = IFIELD(theInstr, 16, 4);
10701   UInt TE_sign  = IFIELD(theInstr, 20, 1);
10702   UInt RMC = IFIELD(theInstr, 9, 2);
10703   IRTemp frA = newTemp( Ity_D64 );
10704   IRTemp frB = newTemp( Ity_D64 );
10705   IRTemp frS = newTemp( Ity_D64 );
10706   Bool clear_CR1 = True;
10707
10708   assign( frB, getDReg( frB_addr ) );
10709
10710   switch (opc2) {
10711   case 0x43: // dquai
10712      DIP( "dquai%s fr%u,fr%u,fr%u\n",
10713           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10714      IRTemp TE_I64 = newTemp( Ity_I64 );
10715
10716      /* Generate a reference DFP value frA with the desired exponent
10717       * given by TE using significand from frB.  Need to add the bias
10718       * 398 to TE.  TE is stored as a 2's complement number.
10719       */
10720      if (TE_sign == 1) {
10721         /* Take 2's complement of the 5-bit value and subtract from bias.
10722          *  Bias is adjusted for the +1 required when taking 2's complement.
10723          */
10724         assign( TE_I64,
10725                 unop( Iop_32Uto64,
10726                       binop( Iop_Sub32, mkU32( 397 ),
10727                              binop( Iop_And32, mkU32( 0xF ),
10728                                     unop( Iop_Not32, mkU32( TE_value ) )
10729                                     ) ) ) );
10730
10731      } else {
10732          assign( TE_I64,
10733                  unop( Iop_32Uto64,
10734                        binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
10735                        ) );
10736      }
10737
10738      assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
10739                          unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
10740
10741      assign( frS, triop( Iop_QuantizeD64,
10742                          mkU32( RMC ),
10743                          mkexpr( frA ),
10744                          mkexpr( frB ) ) );
10745      break;
10746
10747   case 0x3: // dqua
10748      DIP( "dqua%s fr%u,fr%u,fr%u\n",
10749           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10750      assign( frA, getDReg( frA_addr ) );
10751      assign( frS, triop( Iop_QuantizeD64,
10752                          mkU32( RMC ),
10753                          mkexpr( frA ),
10754                          mkexpr( frB ) ) );
10755      break;
10756   case 0x23: // drrnd
10757      {
10758         IRTemp tmp = newTemp( Ity_I8 );
10759
10760         DIP( "drrnd%s fr%u,fr%u,fr%u\n",
10761              flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10762         assign( frA, getDReg( frA_addr ) );
10763         /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
10764         assign( tmp, unop( Iop_32to8,
10765                            unop( Iop_64to32,
10766                                  unop( Iop_ReinterpD64asI64,
10767                                        mkexpr( frA ) ) ) ) );
10768         assign( frS, triop( Iop_SignificanceRoundD64,
10769                             mkU32( RMC ),
10770                             mkexpr( tmp ),
10771                             mkexpr( frB ) ) );
10772      }
10773      break;
10774   default:
10775      vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
10776      return False;
10777   }
10778   putDReg( frS_addr, mkexpr( frS ) );
10779
10780   if (flag_rC && clear_CR1) {
10781      putCR321( 1, mkU8( 0 ) );
10782      putCR0( 1, mkU8( 0 ) );
10783   }
10784
10785   return True;
10786}
10787
10788static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
10789   UInt opc2 = ifieldOPClo8( theInstr );
10790   UChar frS_addr = ifieldRegDS( theInstr );
10791   UChar frA_addr = ifieldRegA( theInstr );
10792   UChar frB_addr = ifieldRegB( theInstr );
10793   UChar flag_rC = ifieldBIT0( theInstr );
10794   UInt TE_value = IFIELD(theInstr, 16, 4);
10795   UInt TE_sign  = IFIELD(theInstr, 20, 1);
10796   UInt RMC = IFIELD(theInstr, 9, 2);
10797   IRTemp frA = newTemp( Ity_D128 );
10798   IRTemp frB = newTemp( Ity_D128 );
10799   IRTemp frS = newTemp( Ity_D128 );
10800   Bool clear_CR1 = True;
10801
10802   assign( frB, getDReg_pair( frB_addr ) );
10803
10804   switch (opc2) {
10805   case 0x43: // dquaiq
10806      DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10807           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10808      IRTemp TE_I64 = newTemp( Ity_I64 );
10809
10810      /* Generate a reference DFP value frA with the desired exponent
10811       * given by TE using significand of 1.  Need to add the bias
10812       * 6176 to TE.
10813       */
10814      if (TE_sign == 1) {
10815         /* Take 2's complement of the 5-bit value and subtract from bias.
10816          *  Bias adjusted for the +1 required when taking 2's complement.
10817          */
10818         assign( TE_I64,
10819                 unop( Iop_32Uto64,
10820                       binop( Iop_Sub32, mkU32( 6175 ),
10821                              binop( Iop_And32, mkU32( 0xF ),
10822                                     unop( Iop_Not32, mkU32( TE_value ) )
10823                                     ) ) ) );
10824
10825      } else {
10826         assign( TE_I64,
10827                 unop( Iop_32Uto64,
10828                       binop( Iop_Add32,
10829                             mkU32( 6176 ),
10830                             mkU32( TE_value ) ) ) );
10831      }
10832
10833      assign( frA,
10834              binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
10835                     unop( Iop_D64toD128,
10836                           unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
10837      assign( frS, triop( Iop_QuantizeD128,
10838                          mkU32( RMC ),
10839                          mkexpr( frA ),
10840                          mkexpr( frB ) ) );
10841      break;
10842   case 0x3: // dquaq
10843      DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10844           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10845      assign( frA, getDReg_pair( frA_addr ) );
10846      assign( frS, triop( Iop_QuantizeD128,
10847                          mkU32( RMC ),
10848                          mkexpr( frA ),
10849                          mkexpr( frB ) ) );
10850      break;
10851   case 0x23: // drrndq
10852      {
10853         IRTemp tmp = newTemp( Ity_I8 );
10854
10855         DIP( "drrndq%s fr%u,fr%u,fr%u\n",
10856              flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10857         assign( frA, getDReg_pair( frA_addr ) );
10858         assign( tmp, unop( Iop_32to8,
10859                            unop( Iop_64to32,
10860                                  unop( Iop_ReinterpD64asI64,
10861                                        unop( Iop_D128HItoD64,
10862                                              mkexpr( frA ) ) ) ) ) );
10863         assign( frS, triop( Iop_SignificanceRoundD128,
10864                             mkU32( RMC ),
10865                             mkexpr( tmp ),
10866                             mkexpr( frB ) ) );
10867      }
10868      break;
10869   default:
10870      vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
10871      return False;
10872   }
10873   putDReg_pair( frS_addr, mkexpr( frS ) );
10874
10875   if (flag_rC && clear_CR1) {
10876      putCR321( 1, mkU8( 0 ) );
10877      putCR0( 1, mkU8( 0 ) );
10878   }
10879
10880   return True;
10881}
10882
10883static Bool dis_dfp_extract_insert(UInt theInstr) {
10884   UInt opc2 = ifieldOPClo10( theInstr );
10885   UChar frS_addr = ifieldRegDS( theInstr );
10886   UChar frA_addr = ifieldRegA( theInstr );
10887   UChar frB_addr = ifieldRegB( theInstr );
10888   UChar flag_rC = ifieldBIT0( theInstr );
10889   Bool clear_CR1 = True;
10890
10891   IRTemp frA = newTemp( Ity_D64 );
10892   IRTemp frB = newTemp( Ity_D64 );
10893   IRTemp frS = newTemp( Ity_D64 );
10894   IRTemp tmp = newTemp( Ity_I64 );
10895
10896   assign( frA, getDReg( frA_addr ) );
10897   assign( frB, getDReg( frB_addr ) );
10898
10899   switch (opc2) {
10900   case 0x162: // dxex
10901      DIP( "dxex%s fr%u,fr%u,fr%u\n",
10902           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10903      assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
10904      assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10905      break;
10906   case 0x362: // diex
10907      DIP( "diex%s fr%u,fr%u,fr%u\n",
10908           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10909      assign( frS, binop( Iop_InsertExpD64,
10910                          unop( Iop_ReinterpD64asI64,
10911                                mkexpr( frA ) ),
10912                          mkexpr( frB ) ) );
10913      break;
10914   default:
10915      vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
10916      return False;
10917   }
10918
10919   putDReg( frS_addr, mkexpr( frS ) );
10920
10921   if (flag_rC && clear_CR1) {
10922      putCR321( 1, mkU8( 0 ) );
10923      putCR0( 1, mkU8( 0 ) );
10924   }
10925
10926   return True;
10927}
10928
10929static Bool dis_dfp_extract_insertq(UInt theInstr) {
10930   UInt opc2 = ifieldOPClo10( theInstr );
10931   UChar frS_addr = ifieldRegDS( theInstr );
10932   UChar frA_addr = ifieldRegA( theInstr );
10933   UChar frB_addr = ifieldRegB( theInstr );
10934   UChar flag_rC = ifieldBIT0( theInstr );
10935
10936   IRTemp frA   = newTemp( Ity_D64 );
10937   IRTemp frB   = newTemp( Ity_D128 );
10938   IRTemp frS64 = newTemp( Ity_D64 );
10939   IRTemp frS   = newTemp( Ity_D128 );
10940   IRTemp tmp   = newTemp( Ity_I64 );
10941   Bool clear_CR1 = True;
10942
10943   assign( frB, getDReg_pair( frB_addr ) );
10944
10945   switch (opc2) {
10946   case 0x162:  // dxexq
10947      DIP( "dxexq%s fr%u,fr%u\n",
10948           flag_rC ? ".":"", frS_addr,  frB_addr );
10949      /* Instruction actually returns a 64-bit result.  So as to be
10950       * consistent and not have to add a new struct, the emulation returns
10951       * the 64-bit result in the upper and lower register.
10952       */
10953      assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
10954      assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10955      putDReg( frS_addr, mkexpr( frS64 ) );
10956      break;
10957   case 0x362:  // diexq
10958      DIP( "diexq%s fr%u,fr%u,fr%u\n",
10959           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10960      assign( frA, getDReg( frA_addr ) );
10961      assign( frS, binop( Iop_InsertExpD128,
10962                          unop( Iop_ReinterpD64asI64, mkexpr( frA ) ),
10963                          mkexpr( frB ) ) );
10964      putDReg_pair( frS_addr, mkexpr( frS ) );
10965      break;
10966   default:
10967      vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
10968      return False;
10969   }
10970
10971   if (flag_rC && clear_CR1) {
10972      putCR321( 1, mkU8( 0 ) );
10973      putCR0( 1, mkU8( 0 ) );
10974   }
10975
10976   return True;
10977}
10978
10979/* DFP 64-bit comparison instructions */
10980static Bool dis_dfp_compare(UInt theInstr) {
10981   /* X-Form */
10982   UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
10983   UChar frA_addr = ifieldRegA( theInstr );
10984   UChar frB_addr = ifieldRegB( theInstr );
10985   UInt opc1 = ifieldOPC( theInstr );
10986   IRTemp frA;
10987   IRTemp frB;
10988
10989   IRTemp ccIR = newTemp( Ity_I32 );
10990   IRTemp ccPPC32 = newTemp( Ity_I32 );
10991
10992
10993   /* Note: Differences between dcmpu and dcmpo are only in exception
10994    flag settings, which aren't supported anyway. */
10995   switch (opc1) {
10996   case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
10997      DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
10998      frA = newTemp( Ity_D64 );
10999      frB = newTemp( Ity_D64 );
11000
11001      assign( frA, getDReg( frA_addr ) );
11002      assign( frB, getDReg( frB_addr ) );
11003
11004      assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
11005      break;
11006   case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
11007      DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
11008      frA = newTemp( Ity_D128 );
11009      frB = newTemp( Ity_D128 );
11010
11011      assign( frA, getDReg_pair( frA_addr ) );
11012      assign( frB, getDReg_pair( frB_addr ) );
11013      assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
11014      break;
11015   default:
11016      vex_printf("dis_dfp_compare(ppc)(opc2)\n");
11017      return False;
11018   }
11019
11020   /* Map compare result from IR to PPC32 */
11021   /*
11022    FP cmp result | PPC | IR
11023    --------------------------
11024    UN            | 0x1 | 0x45
11025    EQ            | 0x2 | 0x40
11026    GT            | 0x4 | 0x00
11027    LT            | 0x8 | 0x01
11028    */
11029
11030   assign( ccPPC32,
11031           binop( Iop_Shl32,
11032                  mkU32( 1 ),
11033                  unop( Iop_32to8,
11034                        binop( Iop_Or32,
11035                               binop( Iop_And32,
11036                                      unop( Iop_Not32,
11037                                            binop( Iop_Shr32,
11038                                                   mkexpr( ccIR ),
11039                                                   mkU8( 5 ) ) ),
11040                                      mkU32( 2 ) ),
11041                               binop( Iop_And32,
11042                                      binop( Iop_Xor32,
11043                                             mkexpr( ccIR ),
11044                                             binop( Iop_Shr32,
11045                                                    mkexpr( ccIR ),
11046                                                    mkU8( 6 ) ) ),
11047                                      mkU32( 1 ) ) ) ) ) );
11048
11049   putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
11050   return True;
11051}
11052
11053/* Test class/group/exponent/significance instructions. */
11054static Bool dis_dfp_exponent_test ( UInt theInstr )
11055{
11056   UChar frA_addr   = ifieldRegA( theInstr );
11057   UChar frB_addr   = ifieldRegB( theInstr );
11058   UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );
11059   IRTemp frA       = newTemp( Ity_D64 );
11060   IRTemp frB       = newTemp( Ity_D64 );
11061   IRTemp frA128    = newTemp( Ity_D128 );
11062   IRTemp frB128    = newTemp( Ity_D128 );
11063   UInt opc1        = ifieldOPC( theInstr );
11064   IRTemp gfield_A  = newTemp( Ity_I32 );
11065   IRTemp gfield_B  = newTemp( Ity_I32 );
11066   IRTemp gfield_mask   = newTemp( Ity_I32 );
11067   IRTemp exponent_A    = newTemp( Ity_I32 );
11068   IRTemp exponent_B    = newTemp( Ity_I32 );
11069   IRTemp A_NaN_true    = newTemp( Ity_I32 );
11070   IRTemp B_NaN_true    = newTemp( Ity_I32 );
11071   IRTemp A_inf_true    = newTemp( Ity_I32 );
11072   IRTemp B_inf_true    = newTemp( Ity_I32 );
11073   IRTemp A_equals_B    = newTemp( Ity_I32 );
11074   IRTemp finite_number = newTemp( Ity_I32 );
11075   IRTemp cc0 = newTemp( Ity_I32 );
11076   IRTemp cc1 = newTemp( Ity_I32 );
11077   IRTemp cc2 = newTemp( Ity_I32 );
11078   IRTemp cc3 = newTemp( Ity_I32 );
11079
11080   /* The dtstex and dtstexg instructions only differ in the size of the
11081    * exponent field.  The following switch statement takes care of the size
11082    * specific setup.  Once the value of the exponents, the G-field shift
11083    * and mask is setup the remaining code is identical.
11084    */
11085   switch (opc1) {
11086   case 0x3b: // dtstex       Extended instruction setup
11087      DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
11088      assign( frA, getDReg( frA_addr ) );
11089      assign( frB, getDReg( frB_addr ) );
11090      assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
11091      assign(exponent_A, unop( Iop_64to32,
11092                               unop( Iop_ExtractExpD64,
11093                                     mkexpr( frA ) ) ) );
11094      assign(exponent_B, unop( Iop_64to32,
11095                               unop( Iop_ExtractExpD64,
11096                                     mkexpr( frB ) ) ) );
11097      break;
11098
11099   case 0x3F: //  dtstexq      Quad instruction setup
11100      DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
11101      assign( frA128, getDReg_pair( frA_addr ) );
11102      assign( frB128, getDReg_pair( frB_addr ) );
11103      assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
11104      assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
11105      assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
11106      assign( exponent_A, unop( Iop_64to32,
11107                                unop( Iop_ExtractExpD128,
11108                                      mkexpr( frA128 ) ) ) );
11109      assign( exponent_B, unop( Iop_64to32,
11110                                unop( Iop_ExtractExpD128,
11111                                      mkexpr( frB128 ) ) ) );
11112      break;
11113   default:
11114      vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
11115      return False;
11116   }
11117
11118   /* Extract the Gfield */
11119   assign( gfield_A, binop( Iop_And32,
11120                            mkexpr( gfield_mask ),
11121                            unop( Iop_64HIto32,
11122                                  unop( Iop_ReinterpD64asI64,
11123                                        mkexpr(frA) ) ) ) );
11124
11125   assign( gfield_B, binop( Iop_And32,
11126                            mkexpr( gfield_mask ),
11127                            unop( Iop_64HIto32,
11128                                  unop( Iop_ReinterpD64asI64,
11129                                        mkexpr(frB) ) ) ) );
11130
11131   /* check for NAN */
11132   assign( A_NaN_true, binop(Iop_Or32,
11133                             unop( Iop_1Sto32,
11134                                   binop( Iop_CmpEQ32,
11135                                          mkexpr( gfield_A ),
11136                                          mkU32( 0x7C000000 ) ) ),
11137                             unop( Iop_1Sto32,
11138                                   binop( Iop_CmpEQ32,
11139                                          mkexpr( gfield_A ),
11140                                          mkU32( 0x7E000000 ) )
11141                                   ) ) );
11142   assign( B_NaN_true, binop(Iop_Or32,
11143                             unop( Iop_1Sto32,
11144                                   binop( Iop_CmpEQ32,
11145                                          mkexpr( gfield_B ),
11146                                          mkU32( 0x7C000000 ) ) ),
11147                             unop( Iop_1Sto32,
11148                                   binop( Iop_CmpEQ32,
11149                                          mkexpr( gfield_B ),
11150                                          mkU32( 0x7E000000 ) )
11151                             ) ) );
11152
11153   /* check for infinity */
11154   assign( A_inf_true,
11155           unop( Iop_1Sto32,
11156                 binop( Iop_CmpEQ32,
11157                        mkexpr( gfield_A ),
11158                        mkU32( 0x78000000 ) ) ) );
11159
11160   assign( B_inf_true,
11161           unop( Iop_1Sto32,
11162                 binop( Iop_CmpEQ32,
11163                        mkexpr( gfield_B ),
11164                        mkU32( 0x78000000 ) ) ) );
11165
11166   assign( finite_number,
11167           unop( Iop_Not32,
11168                 binop( Iop_Or32,
11169                        binop( Iop_Or32,
11170                               mkexpr( A_NaN_true ),
11171                               mkexpr( B_NaN_true ) ),
11172                        binop( Iop_Or32,
11173                               mkexpr( A_inf_true ),
11174                               mkexpr( B_inf_true ) ) ) ) );
11175
11176   /* Calculate the condition code bits
11177    * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
11178    * regardless of the value of the comparisons and cc3 is 1.  Otherwise,
11179    * cc0, cc1 and cc0 reflect the results of the comparisons.
11180    */
11181   assign( A_equals_B,
11182           binop( Iop_Or32,
11183                  unop( Iop_1Uto32,
11184                  binop( Iop_CmpEQ32,
11185                         mkexpr( exponent_A ),
11186                         mkexpr( exponent_B ) ) ),
11187                  binop( Iop_Or32,
11188                         binop( Iop_And32,
11189                                mkexpr( A_inf_true ),
11190                                mkexpr( B_inf_true ) ),
11191                         binop( Iop_And32,
11192                                mkexpr( A_NaN_true ),
11193                                mkexpr( B_NaN_true ) ) ) ) );
11194
11195   assign( cc0, binop( Iop_And32,
11196                       mkexpr( finite_number ),
11197                       binop( Iop_Shl32,
11198                              unop( Iop_1Uto32,
11199                                    binop( Iop_CmpLT32U,
11200                                           mkexpr( exponent_A ),
11201                                           mkexpr( exponent_B ) ) ),
11202                                           mkU8( 3 ) ) ) );
11203
11204   assign( cc1, binop( Iop_And32,
11205                       mkexpr( finite_number ),
11206                       binop( Iop_Shl32,
11207                              unop( Iop_1Uto32,
11208                                    binop( Iop_CmpLT32U,
11209                                           mkexpr( exponent_B ),
11210                                           mkexpr( exponent_A ) ) ),
11211                                           mkU8( 2 ) ) ) );
11212
11213   assign( cc2, binop( Iop_Shl32,
11214                       binop( Iop_And32,
11215                              mkexpr( A_equals_B ),
11216                              mkU32( 1 ) ),
11217                              mkU8( 1 ) ) );
11218
11219   assign( cc3, binop( Iop_And32,
11220                       unop( Iop_Not32, mkexpr( A_equals_B ) ),
11221                       binop( Iop_And32,
11222                              mkU32( 0x1 ),
11223                              binop( Iop_Or32,
11224                                     binop( Iop_Or32,
11225                                            mkexpr ( A_inf_true ),
11226                                            mkexpr ( B_inf_true ) ),
11227                                            binop( Iop_Or32,
11228                                                   mkexpr ( A_NaN_true ),
11229                                                   mkexpr ( B_NaN_true ) ) )
11230                              ) ) );
11231
11232   /* store the condition code */
11233   putGST_field( PPC_GST_CR,
11234                 binop( Iop_Or32,
11235                        mkexpr( cc0 ),
11236                        binop( Iop_Or32,
11237                               mkexpr( cc1 ),
11238                               binop( Iop_Or32,
11239                                      mkexpr( cc2 ),
11240                                      mkexpr( cc3 ) ) ) ),
11241                 crfD );
11242   return True;
11243}
11244
11245/* Test class/group/exponent/significance instructions. */
11246static Bool dis_dfp_class_test ( UInt theInstr )
11247{
11248   UChar frA_addr   = ifieldRegA( theInstr );
11249   IRTemp frA       = newTemp( Ity_D64 );
11250   IRTemp abs_frA   = newTemp( Ity_D64 );
11251   IRTemp frAI64_hi = newTemp( Ity_I64 );
11252   IRTemp frAI64_lo = newTemp( Ity_I64 );
11253   UInt opc1        = ifieldOPC( theInstr );
11254   UInt opc2        = ifieldOPClo9( theInstr );
11255   UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );  // AKA BF
11256   UInt DCM         = IFIELD( theInstr, 10, 6 );
11257   IRTemp DCM_calc  = newTemp( Ity_I32 );
11258   UInt max_exp     = 0;
11259   UInt min_exp     = 0;
11260   IRTemp min_subnormalD64  = newTemp( Ity_D64 );
11261   IRTemp min_subnormalD128 = newTemp( Ity_D128 );
11262   IRTemp significand64  = newTemp( Ity_D64 );
11263   IRTemp significand128 = newTemp( Ity_D128 );
11264   IRTemp exp_min_normal = newTemp( Ity_I64 );
11265   IRTemp exponent       = newTemp( Ity_I32 );
11266
11267   IRTemp infinity_true  = newTemp( Ity_I32 );
11268   IRTemp SNaN_true      = newTemp( Ity_I32 );
11269   IRTemp QNaN_true      = newTemp( Ity_I32 );
11270   IRTemp subnormal_true = newTemp( Ity_I32 );
11271   IRTemp normal_true    = newTemp( Ity_I32 );
11272   IRTemp extreme_true   = newTemp( Ity_I32 );
11273   IRTemp lmd            = newTemp( Ity_I32 );
11274   IRTemp lmd_zero_true  = newTemp( Ity_I32 );
11275   IRTemp zero_true      = newTemp( Ity_I32 );
11276   IRTemp sign           = newTemp( Ity_I32 );
11277   IRTemp field          = newTemp( Ity_I32 );
11278   IRTemp ccIR_zero      = newTemp( Ity_I32 );
11279   IRTemp ccIR_subnormal = newTemp( Ity_I32 );
11280
11281   /* UInt size     = DFP_LONG;  JRS:unused */
11282   IRTemp gfield = newTemp( Ity_I32 );
11283   IRTemp gfield_0_4_shift  = newTemp( Ity_I8 );
11284   IRTemp gfield_mask       = newTemp( Ity_I32 );
11285   IRTemp dcm0 = newTemp( Ity_I32 );
11286   IRTemp dcm1 = newTemp( Ity_I32 );
11287   IRTemp dcm2 = newTemp( Ity_I32 );
11288   IRTemp dcm3 = newTemp( Ity_I32 );
11289   IRTemp dcm4 = newTemp( Ity_I32 );
11290   IRTemp dcm5 = newTemp( Ity_I32 );
11291
11292   /* The only difference between the dtstdc and dtstdcq instructions is
11293    * size of the T and G fields.  The calculation of the 4 bit field
11294    * is the same.  Setup the parameters and values that are DFP size
11295    * specific.  The rest of the code is independent of the DFP size.
11296    *
11297    * The Io_CmpD64 is used below.  The instruction sets the ccIR values.
11298    * The interpretation of the ccIR values is as follows:
11299    *
11300    *    DFP cmp result | IR
11301    * --------------------------
11302    *	 UN             | 0x45
11303    *	 EQ             | 0x40
11304    *	 GT             | 0x00
11305    *	 LT             | 0x01
11306    */
11307
11308   assign( frA, getDReg( frA_addr ) );
11309   assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
11310
11311   assign( abs_frA, unop( Iop_ReinterpI64asD64,
11312                          binop( Iop_And64,
11313                                 unop( Iop_ReinterpD64asI64,
11314                                       mkexpr( frA ) ),
11315                                 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
11316   assign( gfield_0_4_shift, mkU8( 31 - 5 ) );  // G-field[0:4]
11317   switch (opc1) {
11318   case 0x3b: // dtstdc, dtstdg
11319      DIP("dtstd%s %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
11320               crfD, frA_addr, DCM);
11321      /* setup the parameters for the long format of the two instructions */
11322      assign( frAI64_lo, mkU64( 0 ) );
11323      assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
11324      max_exp = DFP_LONG_EXP_MAX;
11325      min_exp = DFP_LONG_EXP_MIN;
11326
11327      assign( exponent, unop( Iop_64to32,
11328                              unop( Iop_ExtractExpD64,
11329                                    mkexpr( frA ) ) ) );
11330      assign( significand64,
11331              unop( Iop_ReinterpI64asD64,
11332                    mkU64( 0x2234000000000001ULL ) ) );  // dfp 1.0
11333      assign( exp_min_normal,mkU64( 398 - 383 ) );
11334      assign( min_subnormalD64,
11335              binop( Iop_InsertExpD64,
11336                     mkexpr( exp_min_normal ),
11337                     mkexpr( significand64 ) ) );
11338
11339      assign( ccIR_subnormal,
11340              binop( Iop_CmpD64,
11341                     mkexpr( abs_frA ),
11342                     mkexpr( min_subnormalD64 ) ) );
11343
11344      /* compare absolute value of frA with zero */
11345      assign( ccIR_zero,
11346              binop( Iop_CmpD64,
11347                     mkexpr( abs_frA ),
11348                     unop( Iop_ReinterpI64asD64,
11349                           mkU64( 0x2238000000000000ULL ) ) ) );
11350
11351      /* size = DFP_LONG; JRS: unused */
11352      break;
11353
11354   case 0x3F:   // dtstdcq, dtstdgq
11355      DIP("dtstd%sq %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
11356               crfD, frA_addr, DCM);
11357      /* setup the parameters for the extended format of the
11358       * two instructions
11359       */
11360      assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
11361                               getDReg( frA_addr+1 ) ) );
11362
11363      assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
11364      max_exp = DFP_EXTND_EXP_MAX;
11365      min_exp = DFP_EXTND_EXP_MIN;
11366      assign( exponent, unop( Iop_64to32,
11367                              unop( Iop_ExtractExpD128,
11368                                    getDReg_pair( frA_addr) ) ) );
11369
11370      /* create quand exponent for minimum normal number */
11371      assign( exp_min_normal, mkU64( 6176 - 6143 ) );
11372      assign( significand128,
11373              unop( Iop_D64toD128,
11374                    unop( Iop_ReinterpI64asD64,
11375                          mkU64( 0x2234000000000001ULL ) ) ) );  // dfp 1.0
11376
11377      assign( min_subnormalD128,
11378              binop( Iop_InsertExpD128,
11379                     mkexpr( exp_min_normal ),
11380                     mkexpr( significand128 ) ) );
11381
11382      assign( ccIR_subnormal,
11383              binop( Iop_CmpD128,
11384                     binop( Iop_D64HLtoD128,
11385                            unop( Iop_ReinterpI64asD64,
11386                                  binop( Iop_And64,
11387                                         unop( Iop_ReinterpD64asI64,
11388                                               mkexpr( frA ) ),
11389                                         mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
11390                            getDReg( frA_addr+1 ) ),
11391                     mkexpr( min_subnormalD128 ) ) );
11392      assign( ccIR_zero,
11393              binop( Iop_CmpD128,
11394                     binop( Iop_D64HLtoD128,
11395                            mkexpr( abs_frA ),
11396                            getDReg( frA_addr+1 ) ),
11397                     unop( Iop_D64toD128,
11398                           unop( Iop_ReinterpI64asD64,
11399                                 mkU64( 0x0ULL ) ) ) ) );
11400
11401      /* size = DFP_EXTND; JRS:unused */
11402      break;
11403   default:
11404      vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
11405      return False;
11406   }
11407
11408   /* The G-field is in the upper 32-bits.  The I64 logical operations
11409    * do not seem to be supported in 32-bit mode so keep things as 32-bit
11410    * operations.
11411    */
11412   assign( gfield, binop( Iop_And32,
11413                          mkexpr( gfield_mask ),
11414                          unop( Iop_64HIto32,
11415                                mkexpr(frAI64_hi) ) ) );
11416
11417   /* There is a lot of code that is the same to do the class and group
11418    * instructions.  Later there is an if statement to handle the specific
11419    * instruction.
11420    *
11421    * Will be using I32 values, compares, shifts and logical operations for
11422    * this code as the 64-bit compare, shifts, logical operations are not
11423    * supported in 32-bit mode.
11424    */
11425
11426   /* Check the bits for Infinity, QNaN or Signaling NaN */
11427   assign( infinity_true,
11428           unop( Iop_1Sto32,
11429                 binop( Iop_CmpEQ32,
11430                        binop( Iop_And32,
11431                               mkU32( 0x7C000000 ),
11432                               mkexpr( gfield ) ),
11433                        mkU32( 0x78000000 ) ) ) );
11434
11435   assign( SNaN_true,
11436           unop( Iop_1Sto32,
11437                 binop( Iop_CmpEQ32,
11438                        binop( Iop_And32,
11439                               mkU32( 0x7E000000 ),
11440                               mkexpr( gfield ) ),
11441                        mkU32( 0x7E000000 ) ) ) );
11442
11443   assign( QNaN_true,
11444           binop( Iop_And32,
11445                  unop( Iop_1Sto32,
11446                       binop( Iop_CmpEQ32,
11447                              binop( Iop_And32,
11448                                     mkU32( 0x7E000000 ),
11449                                     mkexpr( gfield ) ),
11450                              mkU32( 0x7C000000 ) ) ),
11451                  unop( Iop_Not32,
11452                        mkexpr( SNaN_true ) ) ) );
11453
11454   assign( zero_true,
11455           binop( Iop_And32,
11456                  unop(Iop_1Sto32,
11457                       binop( Iop_CmpEQ32,
11458                              mkexpr( ccIR_zero ),
11459                              mkU32( 0x40 ) ) ),  // ccIR code for Equal
11460                  unop( Iop_Not32,
11461                        binop( Iop_Or32,
11462                               mkexpr( infinity_true ),
11463                               binop( Iop_Or32,
11464                                      mkexpr( QNaN_true ),
11465                                      mkexpr( SNaN_true ) ) ) ) ) );
11466
11467   /* Do compare of frA the minimum normal value.  Comparison is size
11468    * depenent and was done above to get the ccIR value.
11469    */
11470   assign( subnormal_true,
11471           binop( Iop_And32,
11472                  binop( Iop_Or32,
11473                         unop( Iop_1Sto32,
11474                               binop( Iop_CmpEQ32,
11475                                      mkexpr( ccIR_subnormal ),
11476                                      mkU32( 0x40 ) ) ), // ccIR code for Equal
11477                         unop( Iop_1Sto32,
11478                               binop( Iop_CmpEQ32,
11479                                      mkexpr( ccIR_subnormal ),
11480                                      mkU32( 0x1 ) ) ) ), // ccIR code for LT
11481           unop( Iop_Not32,
11482                 binop( Iop_Or32,
11483                        binop( Iop_Or32,
11484                               mkexpr( infinity_true ),
11485                               mkexpr( zero_true) ),
11486                        binop( Iop_Or32,
11487                               mkexpr( QNaN_true ),
11488                               mkexpr( SNaN_true ) ) ) ) ) );
11489
11490   /* Normal number is not subnormal, infinity, NaN or Zero */
11491   assign( normal_true,
11492           unop( Iop_Not32,
11493                 binop( Iop_Or32,
11494                        binop( Iop_Or32,
11495                               mkexpr( infinity_true ),
11496                               mkexpr( zero_true ) ),
11497                        binop( Iop_Or32,
11498                               mkexpr( subnormal_true ),
11499                               binop( Iop_Or32,
11500                                      mkexpr( QNaN_true ),
11501                                      mkexpr( SNaN_true ) ) ) ) ) );
11502
11503   /* Calculate the DCM bit field based on the tests for the specific
11504    * instruction
11505    */
11506   if (opc2 == 0xC2) {    // dtstdc, dtstdcq
11507      /* DCM[0:5] Bit   Data Class definition
11508       *   0   Zero
11509       *   1   Subnormal
11510       *   2   Normal
11511       *   3   Infinity
11512       *   4   Quiet NaN
11513       *   5   Signaling NaN
11514       */
11515
11516      assign( dcm0, binop( Iop_Shl32,
11517                           mkexpr( zero_true ),
11518                           mkU8( 5 ) ) );
11519      assign( dcm1, binop( Iop_Shl32,
11520                           binop( Iop_And32,
11521                                  mkexpr( subnormal_true ),
11522                                  mkU32( 1 ) ),
11523                           mkU8( 4 ) ) );
11524      assign( dcm2, binop( Iop_Shl32,
11525                           binop( Iop_And32,
11526                                  mkexpr( normal_true ),
11527                                  mkU32( 1 ) ),
11528                           mkU8( 3 ) ) );
11529      assign( dcm3, binop( Iop_Shl32,
11530                           binop( Iop_And32,
11531                                  mkexpr( infinity_true),
11532                                  mkU32( 1 ) ),
11533                           mkU8( 2 ) ) );
11534      assign( dcm4, binop( Iop_Shl32,
11535                           binop( Iop_And32,
11536                                  mkexpr( QNaN_true ),
11537                                  mkU32( 1 ) ),
11538                           mkU8( 1 ) ) );
11539      assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
11540
11541   } else if (opc2 == 0xE2) {   // dtstdg, dtstdgq
11542      /* check if the exponent is extreme */
11543      assign( extreme_true, binop( Iop_Or32,
11544                                   unop( Iop_1Sto32,
11545                                         binop( Iop_CmpEQ32,
11546                                                mkexpr( exponent ),
11547                                                mkU32( max_exp ) ) ),
11548                                   unop( Iop_1Sto32,
11549                                         binop( Iop_CmpEQ32,
11550                                                mkexpr( exponent ),
11551                                                mkU32( min_exp ) ) ) ) );
11552
11553      /* Check if LMD is zero */
11554      Get_lmd( &lmd, binop( Iop_Shr32,
11555                            mkexpr( gfield ), mkU8( 31 - 5 ) ) );
11556
11557      assign( lmd_zero_true, unop( Iop_1Sto32,
11558                                   binop( Iop_CmpEQ32,
11559                                          mkexpr( lmd ),
11560                                          mkU32( 0 ) ) ) );
11561
11562      /* DCM[0:5] Bit   Data Class definition
11563       *  0   Zero with non-extreme exponent
11564       *  1   Zero with extreme exponent
11565       *  2   Subnormal or (Normal with extreme exponent)
11566       *  3   Normal with non-extreme exponent and
11567       *      leftmost zero digit in significand
11568       *  4   Normal with non-extreme exponent and
11569       *      leftmost nonzero digit in significand
11570       *  5   Special symbol (Infinity, QNaN, or SNaN)
11571       */
11572      assign( dcm0, binop( Iop_Shl32,
11573                           binop( Iop_And32,
11574                                  binop( Iop_And32,
11575                                         unop( Iop_Not32,
11576                                               mkexpr( extreme_true ) ),
11577                                         mkexpr( zero_true ) ),
11578                                  mkU32( 0x1 ) ),
11579                           mkU8( 5 ) ) );
11580
11581      assign( dcm1, binop( Iop_Shl32,
11582                           binop( Iop_And32,
11583                                  binop( Iop_And32,
11584                                         mkexpr( extreme_true ),
11585                                         mkexpr( zero_true ) ),
11586                                  mkU32( 0x1 ) ),
11587                           mkU8( 4 ) ) );
11588
11589      assign( dcm2, binop( Iop_Shl32,
11590                           binop( Iop_And32,
11591                                  binop( Iop_Or32,
11592                                         binop( Iop_And32,
11593                                                mkexpr( extreme_true ),
11594                                                mkexpr( normal_true ) ),
11595                                         mkexpr( subnormal_true ) ),
11596                                  mkU32( 0x1 ) ),
11597                           mkU8( 3 ) ) );
11598
11599      assign( dcm3, binop( Iop_Shl32,
11600                           binop( Iop_And32,
11601                                  binop( Iop_And32,
11602                                         binop( Iop_And32,
11603                                                unop( Iop_Not32,
11604                                                      mkexpr( extreme_true ) ),
11605                                                      mkexpr( normal_true ) ),
11606                                         unop( Iop_1Sto32,
11607                                               binop( Iop_CmpEQ32,
11608                                                      mkexpr( lmd ),
11609                                                      mkU32( 0 ) ) ) ),
11610                                  mkU32( 0x1 ) ),
11611                           mkU8( 2 ) ) );
11612
11613      assign( dcm4, binop( Iop_Shl32,
11614                           binop( Iop_And32,
11615                                  binop( Iop_And32,
11616                                         binop( Iop_And32,
11617                                                unop( Iop_Not32,
11618                                                      mkexpr( extreme_true ) ),
11619                                                mkexpr( normal_true ) ),
11620                                          unop( Iop_1Sto32,
11621                                                binop( Iop_CmpNE32,
11622                                                       mkexpr( lmd ),
11623                                                       mkU32( 0 ) ) ) ),
11624                                  mkU32( 0x1 ) ),
11625                           mkU8( 1 ) ) );
11626
11627      assign( dcm5, binop( Iop_And32,
11628                           binop( Iop_Or32,
11629                                  mkexpr( SNaN_true),
11630                                  binop( Iop_Or32,
11631                                         mkexpr( QNaN_true),
11632                                         mkexpr( infinity_true) ) ),
11633                           mkU32( 0x1 ) ) );
11634   }
11635
11636   /* create DCM field */
11637   assign( DCM_calc,
11638           binop( Iop_Or32,
11639                  mkexpr( dcm0 ),
11640                  binop( Iop_Or32,
11641                         mkexpr( dcm1 ),
11642                         binop( Iop_Or32,
11643                                mkexpr( dcm2 ),
11644                                binop( Iop_Or32,
11645                                       mkexpr( dcm3 ),
11646                                       binop( Iop_Or32,
11647                                              mkexpr( dcm4 ),
11648                                              mkexpr( dcm5 ) ) ) ) ) ) );
11649
11650   /* Get the sign of the DFP number, ignore sign for QNaN */
11651   assign( sign,
11652           unop( Iop_1Uto32,
11653                 binop( Iop_CmpEQ32,
11654                        binop( Iop_Shr32,
11655                               unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
11656                               mkU8( 63 - 32 ) ),
11657                        mkU32( 1 ) ) ) );
11658
11659   /* This instruction generates a four bit field to be stored in the
11660    * condition code register.  The condition code register consists of 7
11661    * fields.  The field to be written to is specified by the BF (AKA crfD)
11662    * field.
11663    *
11664    * The field layout is as follows:
11665    *
11666    *      Field          Meaning
11667    *      0000           Operand positive with no match
11668    *      0100           Operand positive with at least one match
11669    *      0001           Operand negative with no match
11670    *      0101           Operand negative with at least one match
11671    */
11672   assign( field, binop( Iop_Or32,
11673                         binop( Iop_Shl32,
11674                                mkexpr( sign ),
11675                                mkU8( 3 ) ),
11676                                binop( Iop_Shl32,
11677                                       unop( Iop_1Uto32,
11678                                             binop( Iop_CmpNE32,
11679                                                    binop( Iop_And32,
11680                                                           mkU32( DCM ),
11681                                                           mkexpr( DCM_calc ) ),
11682                                                     mkU32( 0 ) ) ),
11683                                       mkU8( 1 ) ) ) );
11684
11685   putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
11686   return True;
11687}
11688
11689static Bool dis_dfp_bcd(UInt theInstr) {
11690   UInt opc2        = ifieldOPClo10( theInstr );
11691   ULong sp         = IFIELD(theInstr, 19, 2);
11692   ULong s          = IFIELD(theInstr, 20, 1);
11693   UChar frT_addr   = ifieldRegDS( theInstr );
11694   UChar frB_addr   = ifieldRegB( theInstr );
11695   IRTemp frB       = newTemp( Ity_D64 );
11696   IRTemp frBI64    = newTemp( Ity_I64 );
11697   IRTemp result    = newTemp( Ity_I64 );
11698   IRTemp resultD64 = newTemp( Ity_D64 );
11699   IRTemp bcd64     = newTemp( Ity_I64 );
11700   IRTemp bcd_u     = newTemp( Ity_I32 );
11701   IRTemp bcd_l     = newTemp( Ity_I32 );
11702   IRTemp dbcd_u    = newTemp( Ity_I32 );
11703   IRTemp dbcd_l    = newTemp( Ity_I32 );
11704   IRTemp lmd       = newTemp( Ity_I32 );
11705
11706   assign( frB, getDReg( frB_addr ) );
11707   assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
11708
11709   switch ( opc2 ) {
11710   case 0x142: // ddedpd   DFP Decode DPD to BCD
11711      DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
11712
11713         assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
11714         assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
11715         assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
11716
11717      if ( ( sp == 0 ) || ( sp == 1 ) ) {
11718         /* Unsigned BCD string */
11719         Get_lmd( &lmd,
11720                  binop( Iop_Shr32,
11721                         unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11722                         mkU8( 31 - 5 ) ) ); // G-field[0:4]
11723
11724         assign( result,
11725                 binop( Iop_32HLto64,
11726                        binop( Iop_Or32,
11727                               binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
11728                               mkexpr( bcd_u ) ),
11729                        mkexpr( bcd_l ) ) );
11730
11731      } else {
11732         /* Signed BCD string, the cases for sp 2 and 3 only differ in how
11733          * the positive and negative values are encoded in the least
11734          * significant bits.
11735          */
11736         IRTemp sign = newTemp( Ity_I32 );
11737
11738         if (sp == 2) {
11739            /* Positive sign = 0xC, negative sign = 0xD */
11740
11741            assign( sign,
11742                    binop( Iop_Or32,
11743                           binop( Iop_Shr32,
11744                                  unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11745                                  mkU8( 31 ) ),
11746                           mkU32( 0xC ) ) );
11747
11748         } else if ( sp == 3 ) {
11749            /* Positive sign = 0xF, negative sign = 0xD */
11750            IRTemp tmp32 = newTemp( Ity_I32 );
11751
11752            /* Complement sign bit then OR into bit position 1 */
11753            assign( tmp32,
11754                    binop( Iop_Xor32,
11755                           binop( Iop_Shr32,
11756                                  unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11757                                  mkU8( 30 ) ),
11758                           mkU32( 0x2 ) ) );
11759
11760            assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
11761
11762         } else {
11763            vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
11764         }
11765
11766         /* Put sign in bottom 4 bits, move most significant 4-bits from
11767          * bcd_l to bcd_u.
11768          */
11769         assign( result,
11770                 binop( Iop_32HLto64,
11771                        binop( Iop_Or32,
11772                               binop( Iop_Shr32,
11773                                      mkexpr( bcd_l ),
11774                                      mkU8( 28 ) ),
11775                               binop( Iop_Shl32,
11776                                      mkexpr( bcd_u ),
11777                                      mkU8( 4 ) ) ),
11778                        binop( Iop_Or32,
11779                                      mkexpr( sign ),
11780                               binop( Iop_Shl32,
11781                                      mkexpr( bcd_l ),
11782                                      mkU8( 4 ) ) ) ) );
11783      }
11784
11785      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
11786      break;
11787
11788   case 0x342: // denbcd   DFP Encode BCD to DPD
11789   {
11790      IRTemp valid_mask   = newTemp( Ity_I32 );
11791      IRTemp invalid_mask = newTemp( Ity_I32 );
11792      IRTemp without_lmd  = newTemp( Ity_I64 );
11793      IRTemp tmp64        = newTemp( Ity_I64 );
11794      IRTemp dbcd64       = newTemp( Ity_I64 );
11795      IRTemp left_exp     = newTemp( Ity_I32 );
11796      IRTemp g0_4         = newTemp( Ity_I32 );
11797
11798      DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
11799
11800      if ( s == 0 ) {
11801         /* Unsigned BCD string */
11802         assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
11803         assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
11804         assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
11805
11806         assign( lmd,
11807                 binop( Iop_Shr32,
11808                        binop( Iop_And32,
11809                               unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11810                               mkU32( 0xF0000000 ) ),
11811                        mkU8( 28 ) ) );
11812
11813         assign( invalid_mask,
11814                 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11815                                  unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
11816         assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
11817
11818         assign( without_lmd,
11819                 unop( Iop_ReinterpD64asI64,
11820                       binop( Iop_InsertExpD64,
11821                              mkU64( DFP_LONG_BIAS ),
11822                              unop( Iop_ReinterpI64asD64,
11823                                    binop( Iop_32HLto64,
11824                                           mkexpr( dbcd_u ),
11825                                           mkexpr( dbcd_l ) ) ) ) ) );
11826         assign( left_exp,
11827                 binop( Iop_Shr32,
11828                        binop( Iop_And32,
11829                               unop( Iop_64HIto32, mkexpr( without_lmd ) ),
11830                               mkU32( 0x60000000 ) ),
11831                        mkU8( 29 ) ) );
11832
11833         assign( g0_4,
11834                 binop( Iop_Shl32,
11835                        Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
11836                        mkU8( 26 ) ) );
11837
11838         assign( tmp64,
11839                 binop( Iop_32HLto64,
11840                        binop( Iop_Or32,
11841                               binop( Iop_And32,
11842                                      unop( Iop_64HIto32,
11843                                            mkexpr( without_lmd ) ),
11844                                      mkU32( 0x83FFFFFF ) ),
11845                               mkexpr( g0_4 ) ),
11846                        unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
11847
11848      } else if ( s == 1 ) {
11849         IRTemp sign = newTemp( Ity_I32 );
11850         IRTemp sign_bit = newTemp( Ity_I32 );
11851         IRTemp pos_sign_mask = newTemp( Ity_I32 );
11852         IRTemp neg_sign_mask = newTemp( Ity_I32 );
11853         IRTemp tmp = newTemp( Ity_I64 );
11854
11855         /* Signed BCD string, least significant 4 bits are sign bits
11856          * positive sign = 0xC, negative sign = 0xD
11857          */
11858         assign( tmp, unop( Iop_BCDtoDPB,
11859                            binop( Iop_32HLto64,
11860                                   binop( Iop_Shr32,
11861                                          unop( Iop_64HIto32,
11862                                                mkexpr( frBI64 ) ),
11863                                                mkU8( 4 ) ),
11864                                   binop( Iop_Or32,
11865                                          binop( Iop_Shr32,
11866                                                 unop( Iop_64to32,
11867                                                       mkexpr( frBI64 ) ),
11868                                                  mkU8( 4 ) ),
11869                                          binop( Iop_Shl32,
11870                                                 unop( Iop_64HIto32,
11871                                                       mkexpr( frBI64 ) ),
11872                                                       mkU8( 28 ) ) ) ) ) );
11873
11874         assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
11875         assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
11876
11877         /* Get the sign of the BCD string. */
11878         assign( sign,
11879                 binop( Iop_And32,
11880                        unop( Iop_64to32, mkexpr( frBI64 ) ),
11881                        mkU32( 0xF ) ) );
11882
11883         assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
11884         assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
11885         assign( sign_bit,
11886                 Generate_sign_bit( mkexpr( pos_sign_mask ),
11887                                    mkexpr( neg_sign_mask ) ) );
11888
11889         /* Check for invalid sign and BCD digit.  Don't check the bottom
11890          * four bits of bcd_l as that is the sign value.
11891          */
11892         assign( invalid_mask,
11893                 Generate_inv_mask(
11894                                   bcd_digit_inval( unop( Iop_64HIto32,
11895                                                          mkexpr( frBI64 ) ),
11896                                                    binop( Iop_Shr32,
11897                                                           unop( Iop_64to32,
11898                                                                 mkexpr( frBI64 ) ),
11899                                                           mkU8( 4 ) ) ),
11900                                   mkexpr( pos_sign_mask ),
11901                                   mkexpr( neg_sign_mask ) ) );
11902
11903         assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
11904
11905         /* Generate the result assuming the sign value was valid. */
11906         assign( tmp64,
11907                 unop( Iop_ReinterpD64asI64,
11908                       binop( Iop_InsertExpD64,
11909                              mkU64( DFP_LONG_BIAS ),
11910                              unop( Iop_ReinterpI64asD64,
11911                                    binop( Iop_32HLto64,
11912                                           binop( Iop_Or32,
11913                                                  mkexpr( dbcd_u ),
11914                                                  mkexpr( sign_bit ) ),
11915                                           mkexpr( dbcd_l ) ) ) ) ) );
11916      }
11917
11918      /* Generate the value to store depending on the validity of the
11919       * sign value and the validity of the BCD digits.
11920       */
11921      assign( resultD64,
11922              unop( Iop_ReinterpI64asD64,
11923                    binop( Iop_32HLto64,
11924                           binop( Iop_Or32,
11925                                  binop( Iop_And32,
11926                                         mkexpr( valid_mask ),
11927                                         unop( Iop_64HIto32,
11928                                               mkexpr( tmp64 ) ) ),
11929                                  binop( Iop_And32,
11930                                         mkU32( 0x7C000000 ),
11931                                         mkexpr( invalid_mask ) ) ),
11932                           binop( Iop_Or32,
11933                                  binop( Iop_And32,
11934                                         mkexpr( valid_mask ),
11935                                         unop( Iop_64to32, mkexpr( tmp64 ) ) ),
11936                                  binop( Iop_And32,
11937                                         mkU32( 0x0 ),
11938                                         mkexpr( invalid_mask ) ) ) ) ) );
11939      putDReg( frT_addr, mkexpr( resultD64 ) );
11940   }
11941   break;
11942   default:
11943      vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
11944      return False;
11945   }
11946   return True;
11947}
11948
11949static Bool dis_dfp_bcdq( UInt theInstr )
11950{
11951   UInt opc2        = ifieldOPClo10( theInstr );
11952   ULong sp         = IFIELD(theInstr, 19, 2);
11953   ULong s          = IFIELD(theInstr, 20, 1);
11954   IRTemp frB_hi    = newTemp( Ity_D64 );
11955   IRTemp frB_lo    = newTemp( Ity_D64 );
11956   IRTemp frBI64_hi = newTemp( Ity_I64 );
11957   IRTemp frBI64_lo = newTemp( Ity_I64 );
11958   UChar frT_addr   = ifieldRegDS( theInstr );
11959   UChar frB_addr   = ifieldRegB( theInstr );
11960
11961   IRTemp lmd       = newTemp( Ity_I32 );
11962   IRTemp result_hi = newTemp( Ity_I64 );
11963   IRTemp result_lo = newTemp( Ity_I64 );
11964
11965   assign( frB_hi, getDReg( frB_addr ) );
11966   assign( frB_lo, getDReg( frB_addr + 1 ) );
11967   assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
11968   assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
11969
11970   switch ( opc2 ) {
11971   case 0x142: // ddedpdq   DFP Decode DPD to BCD
11972   {
11973      IRTemp low_60_u = newTemp( Ity_I32 );
11974      IRTemp low_60_l = newTemp( Ity_I32 );
11975      IRTemp mid_60_u = newTemp( Ity_I32 );
11976      IRTemp mid_60_l = newTemp( Ity_I32 );
11977      IRTemp top_12_l = newTemp( Ity_I32 );
11978
11979      DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
11980
11981      /* Note, instruction only stores the lower 32 BCD digits in
11982       * the result
11983       */
11984      Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
11985                                   mkexpr( frBI64_lo ),
11986                                   &top_12_l,
11987                                   &mid_60_u,
11988                                   &mid_60_l,
11989                                   &low_60_u,
11990                                   &low_60_l );
11991
11992      if ( ( sp == 0 ) || ( sp == 1 ) ) {
11993         /* Unsigned BCD string */
11994         assign( result_hi,
11995                 binop( Iop_32HLto64,
11996                        binop( Iop_Or32,
11997                               binop( Iop_Shl32,
11998                                      mkexpr( top_12_l ),
11999                                      mkU8( 24 ) ),
12000                               binop( Iop_Shr32,
12001                                      mkexpr( mid_60_u ),
12002                                      mkU8( 4 ) ) ),
12003                        binop( Iop_Or32,
12004                               binop( Iop_Shl32,
12005                                      mkexpr( mid_60_u ),
12006                                      mkU8( 28 ) ),
12007                               binop( Iop_Shr32,
12008                                      mkexpr( mid_60_l ),
12009                                      mkU8( 4 ) ) ) ) );
12010
12011         assign( result_lo,
12012                 binop( Iop_32HLto64,
12013                        binop( Iop_Or32,
12014                               binop( Iop_Shl32,
12015                                      mkexpr( mid_60_l ),
12016                                      mkU8( 28 ) ),
12017                               mkexpr( low_60_u ) ),
12018                        mkexpr( low_60_l ) ) );
12019
12020      } else {
12021         /* Signed BCD string, the cases for sp 2 and 3 only differ in how
12022          * the positive and negative values are encoded in the least
12023          * significant bits.
12024          */
12025         IRTemp sign = newTemp( Ity_I32 );
12026
12027         if ( sp == 2 ) {
12028            /* Positive sign = 0xC, negative sign = 0xD */
12029            assign( sign,
12030                    binop( Iop_Or32,
12031                           binop( Iop_Shr32,
12032                                  unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12033                                  mkU8( 31 ) ),
12034                           mkU32( 0xC ) ) );
12035
12036         } else if ( sp == 3 ) {
12037            IRTemp tmp32 = newTemp( Ity_I32 );
12038
12039            /* Positive sign = 0xF, negative sign = 0xD.
12040             * Need to complement sign bit then OR into bit position 1.
12041             */
12042            assign( tmp32,
12043                    binop( Iop_Xor32,
12044                           binop( Iop_Shr32,
12045                                  unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12046                                  mkU8( 30 ) ),
12047                           mkU32( 0x2 ) ) );
12048
12049            assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
12050
12051         } else {
12052            vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
12053         }
12054
12055         assign( result_hi,
12056                 binop( Iop_32HLto64,
12057                        binop( Iop_Or32,
12058                               binop( Iop_Shl32,
12059                                      mkexpr( top_12_l ),
12060                                      mkU8( 28 ) ),
12061                               mkexpr( mid_60_u ) ),
12062                        mkexpr( mid_60_l ) ) );
12063
12064         assign( result_lo,
12065                 binop( Iop_32HLto64,
12066                        binop( Iop_Or32,
12067                               binop( Iop_Shl32,
12068                                      mkexpr( low_60_u ),
12069                                      mkU8( 4 ) ),
12070                               binop( Iop_Shr32,
12071                                      mkexpr( low_60_l ),
12072                                      mkU8( 28 ) ) ),
12073                        binop( Iop_Or32,
12074                               binop( Iop_Shl32,
12075                                      mkexpr( low_60_l ),
12076                                      mkU8( 4 ) ),
12077                               mkexpr( sign ) ) ) );
12078      }
12079
12080      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
12081      putDReg( frT_addr + 1,
12082               unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
12083   }
12084   break;
12085   case 0x342: // denbcdq   DFP Encode BCD to DPD
12086   {
12087      IRTemp valid_mask      = newTemp( Ity_I32 );
12088      IRTemp invalid_mask    = newTemp( Ity_I32 );
12089      IRTemp result128       = newTemp( Ity_D128 );
12090      IRTemp dfp_significand = newTemp( Ity_D128 );
12091      IRTemp tmp_hi          = newTemp( Ity_I64 );
12092      IRTemp tmp_lo          = newTemp( Ity_I64 );
12093      IRTemp dbcd_top_l      = newTemp( Ity_I32 );
12094      IRTemp dbcd_mid_u      = newTemp( Ity_I32 );
12095      IRTemp dbcd_mid_l      = newTemp( Ity_I32 );
12096      IRTemp dbcd_low_u      = newTemp( Ity_I32 );
12097      IRTemp dbcd_low_l      = newTemp( Ity_I32 );
12098      IRTemp bcd_top_8       = newTemp( Ity_I64 );
12099      IRTemp bcd_mid_60      = newTemp( Ity_I64 );
12100      IRTemp bcd_low_60      = newTemp( Ity_I64 );
12101      IRTemp sign_bit        = newTemp( Ity_I32 );
12102      IRTemp tmptop10        = newTemp( Ity_I64 );
12103      IRTemp tmpmid50        = newTemp( Ity_I64 );
12104      IRTemp tmplow50        = newTemp( Ity_I64 );
12105      IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
12106
12107      DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
12108
12109      if ( s == 0 ) {
12110         /* Unsigned BCD string */
12111         assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
12112
12113         assign( bcd_top_8,
12114                 binop( Iop_32HLto64,
12115                        mkU32( 0 ),
12116                        binop( Iop_And32,
12117                               binop( Iop_Shr32,
12118                                      unop( Iop_64HIto32,
12119                                            mkexpr( frBI64_hi ) ),
12120                                      mkU8( 24 ) ),
12121                               mkU32( 0xFF ) ) ) );
12122         assign( bcd_mid_60,
12123                 binop( Iop_32HLto64,
12124                        binop( Iop_Or32,
12125                               binop( Iop_Shr32,
12126                                      unop( Iop_64to32,
12127                                            mkexpr( frBI64_hi ) ),
12128                                      mkU8( 28 ) ),
12129                               binop( Iop_Shl32,
12130                                      unop( Iop_64HIto32,
12131                                            mkexpr( frBI64_hi ) ),
12132                                      mkU8( 4 ) ) ),
12133                        binop( Iop_Or32,
12134                               binop( Iop_Shl32,
12135                                      unop( Iop_64to32,
12136                                            mkexpr( frBI64_hi ) ),
12137                                      mkU8( 4 ) ),
12138                               binop( Iop_Shr32,
12139                                      unop( Iop_64HIto32,
12140                                            mkexpr( frBI64_lo ) ),
12141                                      mkU8( 28 ) ) ) ) );
12142
12143         /* Note, the various helper functions ignores top 4-bits */
12144         assign( bcd_low_60, mkexpr( frBI64_lo ) );
12145
12146         assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
12147         assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
12148
12149         assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
12150         assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
12151         assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
12152
12153         assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
12154         assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
12155         assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
12156
12157         /* The entire BCD string fits in lower 110-bits.  The LMD = 0,
12158          * value is not part of the final result. Only the right most
12159          * BCD digits are stored.
12160          */
12161         assign( lmd, mkU32( 0 ) );
12162
12163         assign( invalid_mask,
12164                 binop( Iop_Or32,
12165                        bcd_digit_inval( mkU32( 0 ),
12166                                         unop( Iop_64to32,
12167                                               mkexpr( bcd_top_8 ) ) ),
12168                        binop( Iop_Or32,
12169                               bcd_digit_inval( unop( Iop_64HIto32,
12170                                                      mkexpr( bcd_mid_60 ) ),
12171                                                unop( Iop_64to32,
12172                                                      mkexpr( bcd_mid_60 ) ) ),
12173                               bcd_digit_inval( unop( Iop_64HIto32,
12174                                                      mkexpr( bcd_low_60 ) ),
12175                                                unop( Iop_64to32,
12176                                                      mkexpr( bcd_low_60 ) )
12177                                                ) ) ) );
12178
12179      } else if ( s == 1 ) {
12180         IRTemp sign          = newTemp( Ity_I32 );
12181         IRTemp zero          = newTemp( Ity_I32 );
12182         IRTemp pos_sign_mask = newTemp( Ity_I32 );
12183         IRTemp neg_sign_mask = newTemp( Ity_I32 );
12184
12185         /* The sign of the BCD string is stored in lower 4 bits */
12186         assign( sign,
12187                 binop( Iop_And32,
12188                        unop( Iop_64to32, mkexpr( frBI64_lo ) ),
12189                        mkU32( 0xF ) ) );
12190         assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
12191         assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
12192         assign( sign_bit,
12193                 Generate_sign_bit( mkexpr( pos_sign_mask ),
12194                                    mkexpr( neg_sign_mask ) ) );
12195
12196         /* Generate the value assuminig the sign and BCD digits are vaild */
12197         assign( bcd_top_8,
12198                 binop( Iop_32HLto64,
12199                        mkU32( 0x0 ),
12200                        binop( Iop_Shr32,
12201                               unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12202                               mkU8( 28 ) ) ) );
12203
12204         /* The various helper routines ignore the upper 4-bits */
12205         assign( bcd_mid_60, mkexpr( frBI64_hi ) );
12206
12207         /* Remove bottom four sign bits */
12208         assign( bcd_low_60,
12209                 binop( Iop_32HLto64,
12210                        binop( Iop_Shr32,
12211                               unop( Iop_64HIto32,
12212                                     mkexpr( frBI64_lo ) ),
12213                               mkU8( 4 ) ),
12214                               binop( Iop_Or32,
12215                                      binop( Iop_Shl32,
12216                                             unop( Iop_64HIto32,
12217                                                   mkexpr( frBI64_lo ) ),
12218                                             mkU8( 28 ) ),
12219                                      binop( Iop_Shr32,
12220                                             unop( Iop_64to32,
12221                                                   mkexpr( frBI64_lo ) ),
12222                                             mkU8( 4 ) ) ) ) );
12223         assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
12224         assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
12225
12226         assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
12227         assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
12228         assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
12229
12230         assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
12231         assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
12232         assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
12233
12234         /* The entire BCD string fits in lower 110-bits.  The LMD value
12235          * is not stored in the final result for the DFP Long instruction.
12236          */
12237         assign( lmd, mkU32( 0 ) );
12238
12239         /* Check for invalid sign and invalid BCD digit.  Don't check the
12240          *  bottom four bits of frBI64_lo as that is the sign value.
12241          */
12242         assign( zero, mkU32( 0 ) );
12243         assign( inval_bcd_digit_mask,
12244                 binop( Iop_Or32,
12245                        bcd_digit_inval( mkexpr( zero ),
12246                                         unop( Iop_64to32,
12247                                               mkexpr( bcd_top_8 ) ) ),
12248                        binop( Iop_Or32,
12249                               bcd_digit_inval( unop( Iop_64HIto32,
12250                                                     mkexpr( bcd_mid_60 ) ),
12251                                               unop( Iop_64to32,
12252                                                     mkexpr( bcd_mid_60 ) ) ),
12253                               bcd_digit_inval( unop( Iop_64HIto32,
12254                                                     mkexpr( frBI64_lo ) ),
12255                                               binop( Iop_Shr32,
12256                                                      unop( Iop_64to32,
12257                                                            mkexpr( frBI64_lo ) ),
12258                                                        mkU8( 4 ) ) ) ) ) );
12259         assign( invalid_mask,
12260                 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
12261                                    mkexpr( pos_sign_mask ),
12262                                    mkexpr( neg_sign_mask ) ) );
12263
12264      }
12265
12266      assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
12267
12268      /* Calculate the value of the result assuming sign and BCD digits
12269       * are all valid.
12270       */
12271      assign( dfp_significand,
12272              binop( Iop_D64HLtoD128,
12273                     unop( Iop_ReinterpI64asD64,
12274                           binop( Iop_32HLto64,
12275                                  binop( Iop_Or32,
12276                                         mkexpr( sign_bit ),
12277                                         mkexpr( dbcd_top_l ) ),
12278                                  binop( Iop_Or32,
12279                                         binop( Iop_Shl32,
12280                                                mkexpr( dbcd_mid_u ),
12281                                                mkU8( 18 ) ),
12282                                         binop( Iop_Shr32,
12283                                                mkexpr( dbcd_mid_l ),
12284                                                mkU8( 14 ) ) ) ) ),
12285                     unop( Iop_ReinterpI64asD64,
12286                           binop( Iop_32HLto64,
12287                                  binop( Iop_Or32,
12288                                         mkexpr( dbcd_low_u ),
12289                                         binop( Iop_Shl32,
12290                                                mkexpr( dbcd_mid_l ),
12291                                                mkU8( 18 ) ) ),
12292                                  mkexpr( dbcd_low_l ) ) ) ) );
12293
12294      /* Break the result back down to 32-bit chunks and replace chunks.
12295       * If there was an invalid BCD digit or invalid sign value, replace
12296       * the calculated result with the invalid bit string.
12297       */
12298      assign( result128,
12299              binop( Iop_InsertExpD128,
12300                     mkU64( DFP_EXTND_BIAS ),
12301                     mkexpr( dfp_significand ) ) );
12302
12303      assign( tmp_hi,
12304              unop( Iop_ReinterpD64asI64,
12305                    unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
12306
12307      assign( tmp_lo,
12308              unop( Iop_ReinterpD64asI64,
12309                    unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
12310
12311      assign( result_hi,
12312              binop( Iop_32HLto64,
12313                     binop( Iop_Or32,
12314                            binop( Iop_And32,
12315                                   mkexpr( valid_mask ),
12316                                   unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
12317                            binop( Iop_And32,
12318                                   mkU32( 0x7C000000 ),
12319                                   mkexpr( invalid_mask ) ) ),
12320                     binop( Iop_Or32,
12321                            binop( Iop_And32,
12322                                   mkexpr( valid_mask ),
12323                                   unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
12324                            binop( Iop_And32,
12325                                   mkU32( 0x0 ),
12326                                   mkexpr( invalid_mask ) ) ) ) );
12327
12328      assign( result_lo,
12329              binop( Iop_32HLto64,
12330                     binop( Iop_Or32,
12331                            binop( Iop_And32,
12332                                   mkexpr( valid_mask ),
12333                                   unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
12334                            binop( Iop_And32,
12335                                   mkU32( 0x0 ),
12336                                   mkexpr( invalid_mask ) ) ),
12337                     binop( Iop_Or32,
12338                            binop( Iop_And32,
12339                                   mkexpr( valid_mask ),
12340                                   unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
12341                            binop( Iop_And32,
12342                                   mkU32( 0x0 ),
12343                                   mkexpr( invalid_mask ) ) ) ) );
12344
12345      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
12346      putDReg( frT_addr + 1,
12347               unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
12348
12349   }
12350   break;
12351   default:
12352      vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
12353      break;
12354   }
12355   return True;
12356}
12357
12358static Bool dis_dfp_significant_digits( UInt theInstr )
12359{
12360   UChar frA_addr = ifieldRegA( theInstr );
12361   UChar frB_addr = ifieldRegB( theInstr );
12362   IRTemp frA     = newTemp( Ity_D64 );
12363   UInt opc1      = ifieldOPC( theInstr );
12364   IRTemp B_sig   = newTemp( Ity_I8 );
12365   IRTemp K       = newTemp( Ity_I8 );
12366   IRTemp lmd_B   = newTemp( Ity_I32 );
12367   IRTemp field   = newTemp( Ity_I32 );
12368   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
12369   IRTemp Unordered_true     = newTemp( Ity_I32 );
12370   IRTemp Eq_true_mask       = newTemp( Ity_I32 );
12371   IRTemp Lt_true_mask       = newTemp( Ity_I32 );
12372   IRTemp Gt_true_mask       = newTemp( Ity_I32 );
12373   IRTemp KisZero_true_mask  = newTemp( Ity_I32 );
12374   IRTemp KisZero_false_mask = newTemp( Ity_I32 );
12375
12376   /* Get the reference singificance stored in frA */
12377   assign( frA, getDReg( frA_addr ) );
12378
12379   /* Convert from 64 bit to 8 bits in two steps.  The Iop_64to8 is not
12380    * supported in 32-bit mode.
12381    */
12382   assign( K, unop( Iop_32to8,
12383                    binop( Iop_And32,
12384                           unop( Iop_64to32,
12385                                 unop( Iop_ReinterpD64asI64,
12386                                       mkexpr( frA ) ) ),
12387                           mkU32( 0x3F ) ) ) );
12388
12389   switch ( opc1 ) {
12390   case 0x3b: // dtstsf   DFP Test Significance
12391   {
12392      IRTemp frB     = newTemp( Ity_D64 );
12393      IRTemp frBI64  = newTemp( Ity_I64 );
12394      IRTemp B_bcd_u = newTemp( Ity_I32 );
12395      IRTemp B_bcd_l = newTemp( Ity_I32 );
12396      IRTemp tmp64   = newTemp( Ity_I64 );
12397
12398      DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
12399
12400      assign( frB, getDReg( frB_addr ) );
12401      assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
12402
12403      /* Get the BCD string for the value stored in a series of I32 values.
12404       * Count the number of leading zeros.  Subtract the number of leading
12405       * zeros from 16 (maximum number of significant digits in DFP
12406       * Long).
12407       */
12408      Get_lmd( &lmd_B,
12409               binop( Iop_Shr32,
12410                      unop( Iop_64HIto32, mkexpr( frBI64 ) ),
12411                      mkU8( 31 - 5 ) ) ); // G-field[0:4]
12412
12413      assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
12414      assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
12415      assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
12416
12417      assign( B_sig,
12418              binop( Iop_Sub8,
12419                     mkU8( DFP_LONG_MAX_SIG_DIGITS ),
12420                     Count_leading_zeros_60( mkexpr( lmd_B ),
12421                                             mkexpr( B_bcd_u ),
12422                                             mkexpr( B_bcd_l ) ) ) );
12423      assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) );
12424   }
12425   break;
12426   case 0x3F: // dtstsfq     DFP Test Significance
12427   {
12428      IRTemp frB_hi     = newTemp( Ity_D64 );
12429      IRTemp frB_lo     = newTemp( Ity_D64 );
12430      IRTemp frBI64_hi  = newTemp( Ity_I64 );
12431      IRTemp frBI64_lo  = newTemp( Ity_I64 );
12432      IRTemp B_low_60_u = newTemp( Ity_I32 );
12433      IRTemp B_low_60_l = newTemp( Ity_I32 );
12434      IRTemp B_mid_60_u = newTemp( Ity_I32 );
12435      IRTemp B_mid_60_l = newTemp( Ity_I32 );
12436      IRTemp B_top_12_l = newTemp( Ity_I32 );
12437
12438      DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
12439
12440      assign( frB_hi, getDReg( frB_addr ) );
12441      assign( frB_lo, getDReg( frB_addr + 1 ) );
12442
12443      assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
12444      assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
12445
12446      /* Get the BCD string for the value stored in a series of I32 values.
12447       * Count the number of leading zeros.  Subtract the number of leading
12448       * zeros from 32 (maximum number of significant digits in DFP
12449       * extended).
12450       */
12451      Get_lmd( &lmd_B,
12452               binop( Iop_Shr32,
12453                      unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12454                      mkU8( 31 - 5 ) ) ); // G-field[0:4]
12455
12456      Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
12457                                   mkexpr( frBI64_lo ),
12458                                   &B_top_12_l,
12459                                   &B_mid_60_u,
12460                                   &B_mid_60_l,
12461                                   &B_low_60_u,
12462                                   &B_low_60_l );
12463
12464      assign( B_sig,
12465              binop( Iop_Sub8,
12466                     mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
12467                     Count_leading_zeros_128( mkexpr( lmd_B ),
12468                                              mkexpr( B_top_12_l ),
12469                                              mkexpr( B_mid_60_u ),
12470                                              mkexpr( B_mid_60_l ),
12471                                              mkexpr( B_low_60_u ),
12472                                              mkexpr( B_low_60_l ) ) ) );
12473
12474      assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) );
12475   }
12476   break;
12477   }
12478
12479   /* Compare (16 - cnt[0]) against K and set the condition code field
12480    * accordingly.
12481    *
12482    * The field layout is as follows:
12483    *
12484    * bit[3:0]    Description
12485    *    3     K != 0 and K < Number of significant digits if FRB
12486    *    2     K != 0 and K > Number of significant digits if FRB OR K = 0
12487    *    1     K != 0 and K = Number of significant digits if FRB
12488    *    0     K ? Number of significant digits if FRB
12489    */
12490   assign( Eq_true_mask,
12491           unop( Iop_1Sto32,
12492                 binop( Iop_CmpEQ32,
12493                        unop( Iop_8Uto32, mkexpr( K ) ),
12494                        unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
12495   assign( Lt_true_mask,
12496           unop( Iop_1Sto32,
12497                 binop( Iop_CmpLT32U,
12498                        unop( Iop_8Uto32, mkexpr( K ) ),
12499                        unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
12500   assign( Gt_true_mask,
12501           unop( Iop_1Sto32,
12502                 binop( Iop_CmpLT32U,
12503                        unop( Iop_8Uto32, mkexpr( B_sig ) ),
12504                        unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
12505
12506   assign( KisZero_true_mask,
12507           unop( Iop_1Sto32,
12508                 binop( Iop_CmpEQ32,
12509                        unop( Iop_8Uto32, mkexpr( K ) ),
12510                        mkU32( 0 ) ) ) );
12511   assign( KisZero_false_mask,
12512           unop( Iop_1Sto32,
12513                 binop( Iop_CmpNE32,
12514                        unop( Iop_8Uto32, mkexpr( K ) ),
12515                        mkU32( 0 ) ) ) );
12516
12517   assign( field,
12518           binop( Iop_Or32,
12519                  binop( Iop_And32,
12520                         mkexpr( KisZero_false_mask ),
12521                         binop( Iop_Or32,
12522                                binop( Iop_And32,
12523                                       mkexpr( Lt_true_mask ),
12524                                       mkU32( 0x8 ) ),
12525                                binop( Iop_Or32,
12526                                       binop( Iop_And32,
12527                                              mkexpr( Gt_true_mask ),
12528                                              mkU32( 0x4 ) ),
12529                                       binop( Iop_And32,
12530                                              mkexpr( Eq_true_mask ),
12531                                              mkU32( 0x2 ) ) ) ) ),
12532                  binop( Iop_And32,
12533                         mkexpr( KisZero_true_mask ),
12534                         mkU32( 0x4 ) ) ) );
12535
12536   putGST_field( PPC_GST_CR,
12537                 binop( Iop_Or32,
12538                        binop( Iop_And32,
12539                               mkexpr( Unordered_true ),
12540                               mkU32( 0x1 ) ),
12541                        binop( Iop_And32,
12542                               unop( Iop_Not32, mkexpr( Unordered_true ) ),
12543                               mkexpr( field ) ) ),
12544                 crfD );
12545
12546   return True;
12547}
12548
12549/*------------------------------------------------------------*/
12550/*--- AltiVec Instruction Translation                      ---*/
12551/*------------------------------------------------------------*/
12552
12553/*
12554  Altivec Cache Control Instructions (Data Streams)
12555*/
12556static Bool dis_av_datastream ( UInt theInstr )
12557{
12558   /* X-Form */
12559   UChar opc1     = ifieldOPC(theInstr);
12560   UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
12561   UChar flag_A   = flag_T;
12562   UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
12563   UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
12564   UChar rA_addr  = ifieldRegA(theInstr);
12565   UChar rB_addr  = ifieldRegB(theInstr);
12566   UInt  opc2     = ifieldOPClo10(theInstr);
12567   UChar b0       = ifieldBIT0(theInstr);
12568
12569   if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
12570      vex_printf("dis_av_datastream(ppc)(instr)\n");
12571      return False;
12572   }
12573
12574   switch (opc2) {
12575   case 0x156: // dst (Data Stream Touch, AV p115)
12576      DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
12577                                rA_addr, rB_addr, STRM);
12578      break;
12579
12580   case 0x176: // dstst (Data Stream Touch for Store, AV p117)
12581      DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
12582                                  rA_addr, rB_addr, STRM);
12583      break;
12584
12585   case 0x336: // dss (Data Stream Stop, AV p114)
12586      if (rA_addr != 0 || rB_addr != 0) {
12587         vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
12588         return False;
12589      }
12590      if (flag_A == 0) {
12591         DIP("dss %d\n", STRM);
12592      } else {
12593         DIP("dssall\n");
12594      }
12595      break;
12596
12597   default:
12598      vex_printf("dis_av_datastream(ppc)(opc2)\n");
12599      return False;
12600   }
12601   return True;
12602}
12603
12604/*
12605  AltiVec Processor Control Instructions
12606*/
12607static Bool dis_av_procctl ( UInt theInstr )
12608{
12609   /* VX-Form */
12610   UChar opc1    = ifieldOPC(theInstr);
12611   UChar vD_addr = ifieldRegDS(theInstr);
12612   UChar vA_addr = ifieldRegA(theInstr);
12613   UChar vB_addr = ifieldRegB(theInstr);
12614   UInt  opc2    = IFIELD( theInstr, 0, 11 );
12615
12616   if (opc1 != 0x4) {
12617      vex_printf("dis_av_procctl(ppc)(instr)\n");
12618      return False;
12619   }
12620
12621   switch (opc2) {
12622   case 0x604: // mfvscr (Move from VSCR, AV p129)
12623      if (vA_addr != 0 || vB_addr != 0) {
12624         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
12625         return False;
12626      }
12627      DIP("mfvscr v%d\n", vD_addr);
12628      putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
12629      break;
12630
12631   case 0x644: { // mtvscr (Move to VSCR, AV p130)
12632      IRTemp vB = newTemp(Ity_V128);
12633      if (vD_addr != 0 || vA_addr != 0) {
12634         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
12635         return False;
12636      }
12637      DIP("mtvscr v%d\n", vB_addr);
12638      assign( vB, getVReg(vB_addr));
12639      putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
12640      break;
12641   }
12642   default:
12643      vex_printf("dis_av_procctl(ppc)(opc2)\n");
12644      return False;
12645   }
12646   return True;
12647}
12648
12649/*
12650 * VSX scalar and vector convert instructions
12651 */
12652static Bool
12653dis_vx_conv ( UInt theInstr, UInt opc2 )
12654{
12655   /* XX2-Form */
12656   UChar opc1 = ifieldOPC( theInstr );
12657   UChar XT = ifieldRegXT( theInstr );
12658   UChar XB = ifieldRegXB( theInstr );
12659   IRTemp xB, xB2;
12660   IRTemp b3, b2, b1, b0;
12661   xB = xB2 = IRTemp_INVALID;
12662
12663   if (opc1 != 0x3C) {
12664      vex_printf( "dis_vx_conv(ppc)(instr)\n" );
12665      return False;
12666   }
12667
12668   /* Create and assign temps only as needed for the given instruction. */
12669   switch (opc2) {
12670      // scalar double-precision floating point argument
12671      case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
12672         xB = newTemp(Ity_F64);
12673         assign( xB,
12674                 unop( Iop_ReinterpI64asF64,
12675                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12676         break;
12677      // vector double-precision floating point arguments
12678      case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
12679
12680         xB = newTemp(Ity_F64);
12681         xB2 = newTemp(Ity_F64);
12682         assign( xB,
12683                 unop( Iop_ReinterpI64asF64,
12684                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12685         assign( xB2,
12686                 unop( Iop_ReinterpI64asF64,
12687                       unop( Iop_V128to64, getVSReg( XB ) ) ) );
12688         break;
12689      // vector single precision or [un]signed integer word arguments
12690      case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
12691      case 0x1f0: case 0x1d0:
12692         b3 = b2 = b1 = b0 = IRTemp_INVALID;
12693         breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
12694         break;
12695         // vector [un]signed integer doubleword argument
12696      case 0x3f0: case 0x370: case 0x3d0: case 0x350:
12697         xB = newTemp(Ity_I64);
12698         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12699         xB2 = newTemp(Ity_I64);
12700         assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
12701         break;
12702      // scalar [un]signed integer doubleword argument
12703      case 0x250: case 0x270: case 0x2D0: case 0x2F0:
12704         xB = newTemp(Ity_I64);
12705         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12706         break;
12707      // scalar single precision argument
12708      case 0x292: // xscvspdp
12709         xB  = newTemp(Ity_I32);
12710
12711         assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
12712                                                  unop( Iop_V128HIto64,
12713                                                        getVSReg( XB ) ) ) ) );
12714         break;
12715      case 0x296: // xscvspdpn (non signaling version of xscvpdp)
12716         xB = newTemp(Ity_I32);
12717         assign( xB,
12718                 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12719         break;
12720
12721      /* Certain instructions have their complete implementation in the main switch statement
12722       * that follows this one; thus we have a "do nothing" case for those instructions here.
12723       */
12724      case 0x170: case 0x150:
12725         break; // do nothing
12726
12727      default:
12728         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
12729         return False;
12730   }
12731
12732
12733   switch (opc2) {
12734      case 0x2B0:
12735         // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
12736         //             to Signed Integer Doubleword format with Saturate)
12737         DIP("xscvdpsxds v%u,v%u\n", XT, XB);
12738         putVSReg( XT,
12739                   binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
12740                                                 mkU32( Irrm_ZERO ),
12741                                                 mkexpr( xB ) ), mkU64( 0 ) ) );
12742         break;
12743      case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
12744                  //             Convert to Signed Integer Word format with Saturate)
12745         DIP("xscvdpsxws v%u,v%u\n", XT, XB);
12746         putVSReg( XT,
12747                   binop( Iop_64HLtoV128,
12748                          unop( Iop_32Sto64,
12749                                binop( Iop_F64toI32S,
12750                                       mkU32( Irrm_ZERO ),
12751                                       mkexpr( xB ) ) ),
12752                                       mkU64( 0ULL ) ) );
12753         break;
12754      case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
12755                  //             to Unsigned Integer Doubleword format with Saturate)
12756         DIP("xscvdpuxds v%u,v%u\n", XT, XB);
12757         putVSReg( XT,
12758                   binop( Iop_64HLtoV128,
12759                          binop( Iop_F64toI64U,
12760                                 mkU32( Irrm_ZERO ),
12761                                 mkexpr( xB ) ),
12762                                 mkU64( 0ULL ) ) );
12763         break;
12764      case 0x270:
12765         // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
12766         //             to Single-Precision format)
12767         DIP("xscvsxdsp v%u,v%u\n", XT, XB);
12768         putVSReg( XT,
12769                   binop( Iop_64HLtoV128,
12770                          unop( Iop_ReinterpF64asI64,
12771                                binop( Iop_RoundF64toF32,
12772                                       get_IR_roundingmode(),
12773                                       binop( Iop_I64StoF64,
12774                                              get_IR_roundingmode(),
12775                                              mkexpr( xB ) ) ) ),
12776                          mkU64( 0 ) ) );
12777         break;
12778      case 0x2F0:
12779         // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
12780         //            Double-Precision format)
12781         DIP("xscvsxddp v%u,v%u\n", XT, XB);
12782         putVSReg( XT,
12783                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
12784                                                binop( Iop_I64StoF64, get_IR_roundingmode(),
12785                                                       mkexpr( xB ) ) ),
12786                                                       mkU64( 0 ) ) );
12787         break;
12788      case 0x250:
12789         // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
12790         //            Doubleword to Singel-Precision format)
12791         DIP("xscvuxdsp v%u,v%u\n", XT, XB);
12792         putVSReg( XT,
12793                   binop( Iop_64HLtoV128,
12794                          unop( Iop_ReinterpF64asI64,
12795                                binop( Iop_RoundF64toF32,
12796                                       get_IR_roundingmode(),
12797                                       binop( Iop_I64UtoF64,
12798                                              get_IR_roundingmode(),
12799                                              mkexpr( xB ) ) ) ),
12800                          mkU64( 0 ) ) );
12801         break;
12802      case 0x2D0:
12803         // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
12804         //            Double-Precision format)
12805         DIP("xscvuxddp v%u,v%u\n", XT, XB);
12806         putVSReg( XT,
12807                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
12808                                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
12809                                                       mkexpr( xB ) ) ),
12810                                                       mkU64( 0 ) ) );
12811         break;
12812      case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
12813                  //             to Signed Integer Word format with Saturate)
12814      {
12815         IRTemp hiResult_32 = newTemp(Ity_I32);
12816         IRTemp loResult_32 = newTemp(Ity_I32);
12817         IRExpr* rmZero = mkU32(Irrm_ZERO);
12818
12819         DIP("xvcvdpsxws v%u,v%u\n",  XT, XB);
12820         assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
12821         assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
12822         putVSReg( XT,
12823                   binop( Iop_64HLtoV128,
12824                          unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
12825                          unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
12826         break;
12827      }
12828      case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
12829         //  (VSX Vector truncate Single-Precision to integer and
12830         //   Convert to [Un]signed Integer Word format with Saturate)
12831      {
12832         IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
12833         IRTemp tempResult = newTemp(Ity_V128);
12834         IRTemp res0 = newTemp(Ity_I32);
12835         IRTemp res1 = newTemp(Ity_I32);
12836         IRTemp res2 = newTemp(Ity_I32);
12837         IRTemp res3 = newTemp(Ity_I32);
12838         IRTemp hi64 = newTemp(Ity_I64);
12839         IRTemp lo64 = newTemp(Ity_I64);
12840         Bool un_signed = (opc2 == 0x110);
12841         IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
12842
12843         DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", XT, XB);
12844         /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
12845          * then result is set to 0x80000000.  */
12846         assign(tempResult, unop(op, getVSReg(XB)));
12847         assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
12848         assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
12849         assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
12850         assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
12851         assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
12852         assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
12853
12854         b3_result = IRExpr_ITE(is_NaN_32(b3),
12855                                // then: result is 0x{8|0}80000000
12856                                mkU32(un_signed ? 0x00000000 : 0x80000000),
12857                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12858                                mkexpr(res3));
12859         b2_result = IRExpr_ITE(is_NaN_32(b2),
12860                                // then: result is 0x{8|0}80000000
12861                                mkU32(un_signed ? 0x00000000 : 0x80000000),
12862                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12863                                mkexpr(res2));
12864         b1_result = IRExpr_ITE(is_NaN_32(b1),
12865                                // then: result is 0x{8|0}80000000
12866                                mkU32(un_signed ? 0x00000000 : 0x80000000),
12867                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12868                                mkexpr(res1));
12869         b0_result = IRExpr_ITE(is_NaN_32(b0),
12870                                // then: result is 0x{8|0}80000000
12871                                mkU32(un_signed ? 0x00000000 : 0x80000000),
12872                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12873                                mkexpr(res0));
12874
12875         putVSReg( XT,
12876                   binop( Iop_64HLtoV128,
12877                          binop( Iop_32HLto64, b3_result, b2_result ),
12878                          binop( Iop_32HLto64, b1_result, b0_result ) ) );
12879         break;
12880      }
12881      case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
12882                  //           Convert to Single-Precision format
12883         DIP("xscvdpsp v%u,v%u\n", XT, XB);
12884         putVSReg( XT,
12885                   binop( Iop_64HLtoV128,
12886                          binop( Iop_32HLto64,
12887                                 unop( Iop_ReinterpF32asI32,
12888                                       unop( Iop_TruncF64asF32,
12889                                             binop( Iop_RoundF64toF32,
12890                                                    get_IR_roundingmode(),
12891                                                    mkexpr( xB ) ) ) ),
12892                                 mkU32( 0 ) ),
12893                          mkU64( 0ULL ) ) );
12894         break;
12895      case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
12896                              vector Single-Precision non-signalling */
12897         DIP("xscvdpspn v%u,v%u\n", XT, XB);
12898         putVSReg( XT,
12899                   binop( Iop_64HLtoV128,
12900                          binop( Iop_32HLto64,
12901                                 unop( Iop_ReinterpF32asI32,
12902                                       unop( Iop_TruncF64asF32,
12903                                             mkexpr( xB ) ) ),
12904                                 mkU32( 0 ) ),
12905                          mkU64( 0ULL ) ) );
12906         break;
12907      case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
12908                  //             and Convert to Unsigned Integer Word format with Saturate)
12909         DIP("xscvdpuxws v%u,v%u\n", XT, XB);
12910         putVSReg( XT,
12911                   binop( Iop_64HLtoV128,
12912                          binop( Iop_32HLto64,
12913                                 mkU32( 0 ),
12914                                 binop( Iop_F64toI32U,
12915                                        mkU32( Irrm_ZERO ),
12916                                        mkexpr( xB ) ) ),
12917                          mkU64( 0ULL ) ) );
12918         break;
12919      case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
12920         DIP("xscvspdp v%u,v%u\n", XT, XB);
12921         putVSReg( XT,
12922                   binop( Iop_64HLtoV128,
12923                          unop( Iop_ReinterpF64asI64,
12924                                unop( Iop_F32toF64,
12925                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
12926                          mkU64( 0ULL ) ) );
12927         break;
12928      case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
12929         DIP("xscvspdpn v%u,v%u\n", XT, XB);
12930         putVSReg( XT,
12931                   binop( Iop_64HLtoV128,
12932                          unop( Iop_ReinterpF64asI64,
12933                                unop( Iop_F32toF64,
12934                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
12935                                      mkU64( 0ULL ) ) );
12936         break;
12937      case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
12938                  //           and Convert to Single-Precision format)
12939         DIP("xvcvdpsp v%u,v%u\n", XT, XB);
12940         putVSReg( XT,
12941                   binop( Iop_64HLtoV128,
12942                          binop( Iop_32HLto64,
12943                                 unop( Iop_ReinterpF32asI32,
12944                                       unop( Iop_TruncF64asF32,
12945                                             binop( Iop_RoundF64toF32,
12946                                                    get_IR_roundingmode(),
12947                                                    mkexpr( xB ) ) ) ),
12948                                 mkU32( 0 ) ),
12949                          binop( Iop_32HLto64,
12950                                 unop( Iop_ReinterpF32asI32,
12951                                       unop( Iop_TruncF64asF32,
12952                                             binop( Iop_RoundF64toF32,
12953                                                    get_IR_roundingmode(),
12954                                                    mkexpr( xB2 ) ) ) ),
12955                                 mkU32( 0 ) ) ) );
12956         break;
12957      case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
12958                  //             and Convert to Unsigned Integer Doubleword format
12959                  //             with Saturate)
12960         DIP("xvcvdpuxds v%u,v%u\n", XT, XB);
12961         putVSReg( XT,
12962                   binop( Iop_64HLtoV128,
12963                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
12964                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
12965         break;
12966      case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
12967                  //             Convert to Unsigned Integer Word format with Saturate)
12968         DIP("xvcvdpuxws v%u,v%u\n", XT, XB);
12969         putVSReg( XT,
12970                   binop( Iop_64HLtoV128,
12971                          binop( Iop_32HLto64,
12972                                 binop( Iop_F64toI32U,
12973                                        mkU32( Irrm_ZERO ),
12974                                        mkexpr( xB ) ),
12975                                 mkU32( 0 ) ),
12976                          binop( Iop_32HLto64,
12977                                 binop( Iop_F64toI32U,
12978                                        mkU32( Irrm_ZERO ),
12979                                        mkexpr( xB2 ) ),
12980                                 mkU32( 0 ) ) ) );
12981         break;
12982      case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
12983         DIP("xvcvspdp v%u,v%u\n", XT, XB);
12984         putVSReg( XT,
12985                   binop( Iop_64HLtoV128,
12986                          unop( Iop_ReinterpF64asI64,
12987                                unop( Iop_F32toF64,
12988                                      unop( Iop_ReinterpI32asF32,
12989                                            handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
12990                          unop( Iop_ReinterpF64asI64,
12991                                unop( Iop_F32toF64,
12992                                      unop( Iop_ReinterpI32asF32,
12993                                            handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
12994         break;
12995      case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
12996                  //           Convert to Signed Integer Doubleword format with Saturate)
12997         DIP("xvcvspsxds v%u,v%u\n", XT, XB);
12998         putVSReg( XT,
12999                   binop( Iop_64HLtoV128,
13000                          binop( Iop_F64toI64S,
13001                                 mkU32( Irrm_ZERO ),
13002                                 unop( Iop_F32toF64,
13003                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
13004                          binop( Iop_F64toI64S,
13005                                 mkU32( Irrm_ZERO ),
13006                                 unop( Iop_F32toF64,
13007                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
13008         break;
13009      case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
13010                  //            Convert to Unsigned Integer Doubleword format with Saturate)
13011         DIP("xvcvspuxds v%u,v%u\n", XT, XB);
13012         putVSReg( XT,
13013                   binop( Iop_64HLtoV128,
13014                          binop( Iop_F64toI64U,
13015                                 mkU32( Irrm_ZERO ),
13016                                 unop( Iop_F32toF64,
13017                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
13018                          binop( Iop_F64toI64U,
13019                                 mkU32( Irrm_ZERO ),
13020                                 unop( Iop_F32toF64,
13021                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
13022         break;
13023      case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
13024                  //             Convert to Signed Integer Doubleword format with Saturate)
13025         DIP("xvcvdpsxds v%u,v%u\n", XT, XB);
13026         putVSReg( XT,
13027                   binop( Iop_64HLtoV128,
13028                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
13029                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
13030         break;
13031      case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
13032                  //            to Double-Precision format)
13033         DIP("xvcvsxddp v%u,v%u\n", XT, XB);
13034         putVSReg( XT,
13035                   binop( Iop_64HLtoV128,
13036                          unop( Iop_ReinterpF64asI64,
13037                                binop( Iop_I64StoF64,
13038                                       get_IR_roundingmode(),
13039                                       mkexpr( xB ) ) ),
13040                          unop( Iop_ReinterpF64asI64,
13041                                binop( Iop_I64StoF64,
13042                                       get_IR_roundingmode(),
13043                                       mkexpr( xB2 ) ) ) ) );
13044         break;
13045      case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
13046                  //            to Double-Precision format)
13047         DIP("xvcvuxddp v%u,v%u\n", XT, XB);
13048         putVSReg( XT,
13049                   binop( Iop_64HLtoV128,
13050                          unop( Iop_ReinterpF64asI64,
13051                                binop( Iop_I64UtoF64,
13052                                       get_IR_roundingmode(),
13053                                       mkexpr( xB ) ) ),
13054                          unop( Iop_ReinterpF64asI64,
13055                                binop( Iop_I64UtoF64,
13056                                       get_IR_roundingmode(),
13057                                       mkexpr( xB2 ) ) ) ) );
13058
13059         break;
13060      case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
13061                  //            to Single-Precision format)
13062         DIP("xvcvsxddp v%u,v%u\n",  XT, XB);
13063         putVSReg( XT,
13064                   binop( Iop_64HLtoV128,
13065                          binop( Iop_32HLto64,
13066                                 unop( Iop_ReinterpF32asI32,
13067                                       unop( Iop_TruncF64asF32,
13068                                             binop( Iop_RoundF64toF32,
13069                                                    get_IR_roundingmode(),
13070                                                    binop( Iop_I64StoF64,
13071                                                           get_IR_roundingmode(),
13072                                                           mkexpr( xB ) ) ) ) ),
13073                                 mkU32( 0 ) ),
13074                          binop( Iop_32HLto64,
13075                                 unop( Iop_ReinterpF32asI32,
13076                                       unop( Iop_TruncF64asF32,
13077                                             binop( Iop_RoundF64toF32,
13078                                                    get_IR_roundingmode(),
13079                                                    binop( Iop_I64StoF64,
13080                                                           get_IR_roundingmode(),
13081                                                           mkexpr( xB2 ) ) ) ) ),
13082                                 mkU32( 0 ) ) ) );
13083         break;
13084      case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
13085                  //            to Single-Precision format)
13086         DIP("xvcvuxddp v%u,v%u\n", XT, XB);
13087         putVSReg( XT,
13088                   binop( Iop_64HLtoV128,
13089                          binop( Iop_32HLto64,
13090                                 unop( Iop_ReinterpF32asI32,
13091                                       unop( Iop_TruncF64asF32,
13092                                             binop( Iop_RoundF64toF32,
13093                                                    get_IR_roundingmode(),
13094                                                    binop( Iop_I64UtoF64,
13095                                                           get_IR_roundingmode(),
13096                                                           mkexpr( xB ) ) ) ) ),
13097                                 mkU32( 0 ) ),
13098                          binop( Iop_32HLto64,
13099                                 unop( Iop_ReinterpF32asI32,
13100                                       unop( Iop_TruncF64asF32,
13101                                             binop( Iop_RoundF64toF32,
13102                                                    get_IR_roundingmode(),
13103                                                    binop( Iop_I64UtoF64,
13104                                                           get_IR_roundingmode(),
13105                                                           mkexpr( xB2 ) ) ) ) ),
13106                                 mkU32( 0 ) ) ) );
13107         break;
13108
13109      case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
13110         DIP("xvcvsxwdp v%u,v%u\n",  XT, XB);
13111         putVSReg( XT,
13112                   binop( Iop_64HLtoV128,
13113                          unop( Iop_ReinterpF64asI64,
13114                                binop( Iop_I64StoF64, get_IR_roundingmode(),
13115                                       unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
13116                          unop( Iop_ReinterpF64asI64,
13117                                binop( Iop_I64StoF64, get_IR_roundingmode(),
13118                                       unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
13119         break;
13120      case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
13121         DIP("xvcvuxwdp v%u,v%u\n",  XT, XB);
13122         putVSReg( XT,
13123                   binop( Iop_64HLtoV128,
13124                          unop( Iop_ReinterpF64asI64,
13125                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
13126                                       unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
13127                          unop( Iop_ReinterpF64asI64,
13128                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
13129                                       unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
13130         break;
13131      case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
13132         DIP("xvcvsxwsp v%u,v%u\n",  XT, XB);
13133         putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
13134         break;
13135      case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
13136         DIP("xvcvuxwsp v%u,v%u\n",  XT, XB);
13137         putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
13138         break;
13139
13140      default:
13141         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
13142         return False;
13143   }
13144   return True;
13145}
13146
13147/*
13148 * VSX vector Double Precision Floating Point Arithmetic Instructions
13149 */
13150static Bool
13151dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
13152{
13153   /* XX3-Form */
13154   UChar opc1 = ifieldOPC( theInstr );
13155   UChar XT = ifieldRegXT( theInstr );
13156   UChar XA = ifieldRegXA( theInstr );
13157   UChar XB = ifieldRegXB( theInstr );
13158   IRExpr* rm = get_IR_roundingmode();
13159   IRTemp frA = newTemp(Ity_F64);
13160   IRTemp frB = newTemp(Ity_F64);
13161   IRTemp frA2 = newTemp(Ity_F64);
13162   IRTemp frB2 = newTemp(Ity_F64);
13163
13164   if (opc1 != 0x3C) {
13165      vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
13166      return False;
13167   }
13168
13169   assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
13170   assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
13171   assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
13172   assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
13173
13174   switch (opc2) {
13175      case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
13176      case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
13177      case 0x180: // xvadddp (VSX Vector Add Double-Precision)
13178      case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
13179      {
13180         IROp mOp;
13181         const HChar * oper_name;
13182         switch (opc2) {
13183            case 0x1E0:
13184               mOp = Iop_DivF64;
13185               oper_name = "div";
13186               break;
13187            case 0x1C0:
13188               mOp = Iop_MulF64;
13189               oper_name = "mul";
13190               break;
13191            case 0x180:
13192               mOp = Iop_AddF64;
13193               oper_name = "add";
13194               break;
13195            case 0x1A0:
13196               mOp = Iop_SubF64;
13197               oper_name = "sub";
13198               break;
13199
13200            default:
13201               vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
13202         }
13203         IRTemp hiResult = newTemp(Ity_I64);
13204         IRTemp loResult = newTemp(Ity_I64);
13205         DIP("xv%sdp v%d,v%d,v%d\n", oper_name, XT, XA, XB);
13206
13207         assign( hiResult,
13208                 unop( Iop_ReinterpF64asI64,
13209                       triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
13210         assign( loResult,
13211                 unop( Iop_ReinterpF64asI64,
13212                       triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
13213         putVSReg( XT,
13214                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
13215         break;
13216      }
13217      case 0x196: // xvsqrtdp
13218      {
13219         IRTemp hiResult = newTemp(Ity_I64);
13220         IRTemp loResult = newTemp(Ity_I64);
13221         DIP("xvsqrtdp v%d,v%d\n", XT, XB);
13222
13223         assign( hiResult,
13224                 unop( Iop_ReinterpF64asI64,
13225                       binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
13226         assign( loResult,
13227                 unop( Iop_ReinterpF64asI64,
13228                       binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
13229         putVSReg( XT,
13230                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
13231         break;
13232      }
13233      case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
13234      case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
13235      case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
13236      case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
13237      {
13238         /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
13239          *    XT == FRC
13240          *    XA == FRA
13241          *    XB == FRB
13242          *
13243          * and for xvm{add|sub}adp . . .
13244          *    XT == FRB
13245          *    XA == FRA
13246          *    XB == FRC
13247          */
13248         Bool negate;
13249         IROp mOp = Iop_INVALID;
13250         const HChar * oper_name = NULL;
13251         Bool mdp = False;
13252
13253         switch (opc2) {
13254            case 0x184: case 0x1A4:
13255            case 0x384: case 0x3A4:
13256               mOp = Iop_MAddF64;
13257               oper_name = "add";
13258               mdp = (opc2 & 0x0FF) == 0x0A4;
13259               break;
13260
13261            case 0x1C4: case 0x1E4:
13262            case 0x3C4: case 0x3E4:
13263               mOp = Iop_MSubF64;
13264               oper_name = "sub";
13265               mdp = (opc2 & 0x0FF) == 0x0E4;
13266               break;
13267
13268            default:
13269               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
13270         }
13271
13272         switch (opc2) {
13273            case 0x384: case 0x3A4:
13274            case 0x3C4: case 0x3E4:
13275               negate = True;
13276               break;
13277            default:
13278               negate = False;
13279         }
13280         IRTemp hiResult = newTemp(Ity_I64);
13281         IRTemp loResult = newTemp(Ity_I64);
13282         IRTemp frT = newTemp(Ity_F64);
13283         IRTemp frT2 = newTemp(Ity_F64);
13284         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
13285             XT, XA, XB);
13286         assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
13287         assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
13288
13289         assign( hiResult,
13290                 unop( Iop_ReinterpF64asI64,
13291                       qop( mOp,
13292                            rm,
13293                            mkexpr( frA ),
13294                            mkexpr( mdp ? frT : frB ),
13295                            mkexpr( mdp ? frB : frT ) ) ) );
13296         assign( loResult,
13297                 unop( Iop_ReinterpF64asI64,
13298                       qop( mOp,
13299                            rm,
13300                            mkexpr( frA2 ),
13301                            mkexpr( mdp ? frT2 : frB2 ),
13302                            mkexpr( mdp ? frB2 : frT2 ) ) ) );
13303         putVSReg( XT,
13304                   binop( Iop_64HLtoV128,
13305                          mkexpr( negate ? getNegatedResult( hiResult )
13306                                         : hiResult ),
13307                          mkexpr( negate ? getNegatedResult( loResult )
13308                                         : loResult ) ) );
13309         break;
13310      }
13311      case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
13312      {
13313         IRTemp frBHi_I64 = newTemp(Ity_I64);
13314         IRTemp frBLo_I64 = newTemp(Ity_I64);
13315         IRTemp flagsHi = newTemp(Ity_I32);
13316         IRTemp flagsLo = newTemp(Ity_I32);
13317         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13318         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
13319         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
13320
13321         DIP("xvtsqrtdp cr%d,v%d\n", crfD, XB);
13322         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
13323         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
13324         do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
13325         do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
13326         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13327          * where fl_flag == 1 on ppc64.
13328          */
13329         assign( flagsHi,
13330                 binop( Iop_Or32,
13331                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13332                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
13333                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
13334         assign( flagsLo,
13335                 binop( Iop_Or32,
13336                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13337                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
13338                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
13339         putGST_field( PPC_GST_CR,
13340                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
13341                       crfD );
13342         break;
13343      }
13344      case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
13345      {
13346         IRTemp frBHi_I64 = newTemp(Ity_I64);
13347         IRTemp frBLo_I64 = newTemp(Ity_I64);
13348         IRTemp frAHi_I64 = newTemp(Ity_I64);
13349         IRTemp frALo_I64 = newTemp(Ity_I64);
13350         IRTemp flagsHi = newTemp(Ity_I32);
13351         IRTemp flagsLo = newTemp(Ity_I32);
13352         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13353         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
13354         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
13355
13356         DIP("xvtdivdp cr%d,v%d,v%d\n", crfD, XA, XB);
13357         assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
13358         assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
13359         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
13360         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
13361
13362         _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
13363         _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
13364         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13365          * where fl_flag == 1 on ppc64.
13366          */
13367         assign( flagsHi,
13368                 binop( Iop_Or32,
13369                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13370                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
13371                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
13372         assign( flagsLo,
13373                 binop( Iop_Or32,
13374                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13375                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
13376                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
13377         putGST_field( PPC_GST_CR,
13378                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
13379                       crfD );
13380         break;
13381      }
13382
13383      default:
13384         vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
13385         return False;
13386   }
13387   return True;
13388}
13389
13390/*
13391 * VSX vector Single Precision Floating Point Arithmetic Instructions
13392 */
13393static Bool
13394dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
13395{
13396   /* XX3-Form */
13397   UChar opc1 = ifieldOPC( theInstr );
13398   UChar XT = ifieldRegXT( theInstr );
13399   UChar XA = ifieldRegXA( theInstr );
13400   UChar XB = ifieldRegXB( theInstr );
13401   IRExpr* rm = get_IR_roundingmode();
13402   IRTemp a3, a2, a1, a0;
13403   IRTemp b3, b2, b1, b0;
13404   IRTemp res0 = newTemp(Ity_I32);
13405   IRTemp res1 = newTemp(Ity_I32);
13406   IRTemp res2 = newTemp(Ity_I32);
13407   IRTemp res3 = newTemp(Ity_I32);
13408
13409   a3 = a2 = a1 = a0 = IRTemp_INVALID;
13410   b3 = b2 = b1 = b0 = IRTemp_INVALID;
13411
13412   if (opc1 != 0x3C) {
13413      vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
13414      return False;
13415   }
13416
13417   switch (opc2) {
13418      case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
13419         DIP("xvaddsp v%d,v%d,v%d\n", XT, XA, XB);
13420         // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
13421         putVSReg( XT, triop(Iop_Add32Fx4, rm,
13422                             getVSReg( XA ), getVSReg( XB )) );
13423         break;
13424
13425      case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
13426         DIP("xvmulsp v%d,v%d,v%d\n", XT, XA, XB);
13427         // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
13428         putVSReg( XT, triop(Iop_Mul32Fx4, rm,
13429                             getVSReg( XA ), getVSReg( XB )) );
13430         break;
13431
13432      case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
13433         DIP("xvsubsp v%d,v%d,v%d\n", XT, XA, XB);
13434         // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
13435         putVSReg( XT, triop(Iop_Sub32Fx4, rm,
13436                             getVSReg( XA ), getVSReg( XB )) );
13437         break;
13438
13439      case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
13440      {
13441         /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
13442          * So there are two choices:
13443          *   1. Implement the xvdivsp with a native insn; or
13444          *   2. Extract the 4 single precision floats from each vector
13445          *      register inputs and perform fdivs on each pair
13446          * I will do the latter, due to the general philosophy of
13447          * reusing existing implementations when practical.
13448          */
13449         DIP("xvdivsp v%d,v%d,v%d\n", XT, XA, XB);
13450         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13451         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13452
13453         assign( res0,
13454              unop( Iop_ReinterpF32asI32,
13455                    unop( Iop_TruncF64asF32,
13456                          triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
13457         assign( res1,
13458                 unop( Iop_ReinterpF32asI32,
13459                       unop( Iop_TruncF64asF32,
13460                             triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
13461         assign( res2,
13462                 unop( Iop_ReinterpF32asI32,
13463                       unop( Iop_TruncF64asF32,
13464                             triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
13465         assign( res3,
13466                 unop( Iop_ReinterpF32asI32,
13467                       unop( Iop_TruncF64asF32,
13468                             triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
13469
13470         putVSReg( XT,
13471                   binop( Iop_64HLtoV128,
13472                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13473                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13474         break;
13475      }
13476      case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
13477      {
13478         DIP("xvsqrtsp v%d,v%d\n", XT, XB);
13479         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13480         /* Note: The native xvsqrtsp insruction does not always give the same precision
13481          * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
13482          * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
13483          * to the actual instruction.
13484          */
13485
13486         assign( res0,
13487                 unop( Iop_ReinterpF32asI32,
13488                       unop( Iop_TruncF64asF32,
13489                             binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
13490         assign( res1,
13491                 unop( Iop_ReinterpF32asI32,
13492                       unop( Iop_TruncF64asF32,
13493                             binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
13494         assign( res2,
13495                 unop( Iop_ReinterpF32asI32,
13496                       unop( Iop_TruncF64asF32,
13497                             binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
13498         assign( res3,
13499                 unop( Iop_ReinterpF32asI32,
13500                       unop( Iop_TruncF64asF32,
13501                             binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
13502
13503         putVSReg( XT,
13504                   binop( Iop_64HLtoV128,
13505                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13506                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13507         break;
13508      }
13509
13510      case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
13511      case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
13512      case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
13513      case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
13514      {
13515         IRTemp t3, t2, t1, t0;
13516         Bool msp = False;
13517         Bool negate;
13518         const HChar * oper_name = NULL;
13519         IROp mOp = Iop_INVALID;
13520         switch (opc2) {
13521            case 0x104: case 0x124:
13522            case 0x304: case 0x324:
13523               msp = (opc2 & 0x0FF) == 0x024;
13524               mOp = Iop_MAddF64r32;
13525               oper_name = "madd";
13526               break;
13527
13528            case 0x144: case 0x164:
13529            case 0x344: case 0x364:
13530               msp = (opc2 & 0x0FF) == 0x064;
13531               mOp = Iop_MSubF64r32;
13532               oper_name = "sub";
13533               break;
13534
13535            default:
13536               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
13537         }
13538
13539         switch (opc2) {
13540            case 0x304: case 0x324:
13541            case 0x344: case 0x364:
13542               negate = True;
13543               break;
13544
13545            default:
13546               negate = False;
13547         }
13548
13549         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name,
13550             msp ? "msp" : "asp", XT, XA, XB);
13551
13552         t3 = t2 = t1 = t0 = IRTemp_INVALID;
13553         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13554         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13555         breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
13556
13557         assign( res0,
13558                 unop( Iop_ReinterpF32asI32,
13559                       unop( Iop_TruncF64asF32,
13560                             qop( mOp,
13561                                  rm,
13562                                  mkexpr( a0 ),
13563                                  mkexpr( msp ? t0 : b0 ),
13564                                  mkexpr( msp ? b0 : t0 ) ) ) ) );
13565         assign( res1,
13566                 unop( Iop_ReinterpF32asI32,
13567                       unop( Iop_TruncF64asF32,
13568                             qop( mOp,
13569                                  rm,
13570                                  mkexpr( a1 ),
13571                                  mkexpr( msp ? t1 : b1 ),
13572                                  mkexpr( msp ? b1 : t1 ) ) ) ) );
13573         assign( res2,
13574                 unop( Iop_ReinterpF32asI32,
13575                       unop( Iop_TruncF64asF32,
13576                             qop( mOp,
13577                                  rm,
13578                                  mkexpr( a2 ),
13579                                  mkexpr( msp ? t2 : b2 ),
13580                                  mkexpr( msp ? b2 : t2 ) ) ) ) );
13581         assign( res3,
13582                 unop( Iop_ReinterpF32asI32,
13583                       unop( Iop_TruncF64asF32,
13584                             qop( mOp,
13585                                  rm,
13586                                  mkexpr( a3 ),
13587                                  mkexpr( msp ? t3 : b3 ),
13588                                  mkexpr( msp ? b3 : t3 ) ) ) ) );
13589
13590         putVSReg( XT,
13591                   binop( Iop_64HLtoV128,
13592                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
13593                                 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
13594                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
13595                                 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
13596
13597         break;
13598      }
13599      case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
13600      {
13601         IRTemp flags0 = newTemp(Ity_I32);
13602         IRTemp flags1 = newTemp(Ity_I32);
13603         IRTemp flags2 = newTemp(Ity_I32);
13604         IRTemp flags3 = newTemp(Ity_I32);
13605         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13606         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13607         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13608         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13609         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13610         DIP("xvtsqrtsp cr%d,v%d\n", crfD, XB);
13611
13612         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13613         do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13614         do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13615         do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13616         do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13617
13618         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13619          * where fl_flag == 1 on ppc64.
13620          */
13621         assign( flags0,
13622                 binop( Iop_Or32,
13623                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13624                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13625                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13626         assign( flags1,
13627                 binop( Iop_Or32,
13628                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13629                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13630                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13631         assign( flags2,
13632                 binop( Iop_Or32,
13633                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13634                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13635                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13636         assign( flags3,
13637                 binop( Iop_Or32,
13638                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13639                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13640                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13641         putGST_field( PPC_GST_CR,
13642                       binop( Iop_Or32,
13643                              mkexpr( flags0 ),
13644                              binop( Iop_Or32,
13645                                     mkexpr( flags1 ),
13646                                     binop( Iop_Or32,
13647                                            mkexpr( flags2 ),
13648                                            mkexpr( flags3 ) ) ) ),
13649                       crfD );
13650
13651         break;
13652      }
13653      case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
13654      {
13655         IRTemp flags0 = newTemp(Ity_I32);
13656         IRTemp flags1 = newTemp(Ity_I32);
13657         IRTemp flags2 = newTemp(Ity_I32);
13658         IRTemp flags3 = newTemp(Ity_I32);
13659         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13660         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13661         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13662         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13663         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13664         DIP("xvtdivsp cr%d,v%d,v%d\n", crfD, XA, XB);
13665
13666         breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13667         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13668         _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13669         _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13670         _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13671         _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13672
13673         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13674          * where fl_flag == 1 on ppc64.
13675          */
13676         assign( flags0,
13677                 binop( Iop_Or32,
13678                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13679                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13680                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13681         assign( flags1,
13682                 binop( Iop_Or32,
13683                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13684                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13685                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13686         assign( flags2,
13687                 binop( Iop_Or32,
13688                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13689                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13690                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13691         assign( flags3,
13692                 binop( Iop_Or32,
13693                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13694                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13695                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13696         putGST_field( PPC_GST_CR,
13697                       binop( Iop_Or32,
13698                              mkexpr( flags0 ),
13699                              binop( Iop_Or32,
13700                                     mkexpr( flags1 ),
13701                                     binop( Iop_Or32,
13702                                            mkexpr( flags2 ),
13703                                            mkexpr( flags3 ) ) ) ),
13704                       crfD );
13705
13706         break;
13707      }
13708
13709      default:
13710         vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
13711         return False;
13712   }
13713   return True;
13714}
13715
13716/*
13717 * Vector Population Count/bit matrix transpose
13718 */
13719static Bool
13720dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
13721{
13722   UChar vRB_addr = ifieldRegB(theInstr);
13723   UChar vRT_addr = ifieldRegDS(theInstr);
13724   UChar opc1 = ifieldOPC( theInstr );
13725   IRTemp vB = newTemp(Ity_V128);
13726   assign( vB, getVReg(vRB_addr));
13727
13728   if (opc1 != 0x4) {
13729      vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
13730      return False;
13731   }
13732
13733   switch (opc2) {
13734      case 0x702:    // vclzb
13735         DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
13736         putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) );
13737         break;
13738
13739      case 0x742:    // vclzh
13740         DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
13741         putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) );
13742         break;
13743
13744      case 0x782:    // vclzw
13745         DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
13746         putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) );
13747         break;
13748
13749      case 0x7C2:    // vclzd
13750         DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
13751         putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
13752         break;
13753
13754      case 0x703:    // vpopcntb
13755      {
13756         /* Break vector into 32-bit words and do the population count
13757          * on byte in the words
13758          */
13759         IRType ty = Ity_I32;
13760         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13761         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13762         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13763         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13764
13765         DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
13766         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13767         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   BYTE);
13768         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  BYTE);
13769         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  BYTE);
13770         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
13771
13772         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13773                                         cnt_bits32_63, cnt_bits0_31) );
13774         break;
13775      }
13776
13777      case 0x743:    // vpopcnth
13778      {
13779         /* Break vector into 32-bit words and do the population count
13780          * for each half word
13781          */
13782         IRType ty = Ity_I32;
13783         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13784         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13785         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13786         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13787
13788         DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
13789         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13790
13791         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   HWORD);
13792         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  HWORD);
13793         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  HWORD);
13794         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
13795
13796         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13797                                         cnt_bits32_63, cnt_bits0_31) );
13798         break;
13799      }
13800
13801      case 0x783:    // vpopcntw
13802      {
13803         /* Break vector into 32-bit words and do the population count
13804          * on each word.
13805          */
13806         IRType ty = Ity_I32;
13807         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13808         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13809         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13810         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13811
13812         DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
13813         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13814
13815         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   WORD);
13816         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  WORD);
13817         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  WORD);
13818         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
13819
13820         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13821                                         cnt_bits32_63, cnt_bits0_31) );
13822         break;
13823      }
13824
13825      case 0x7C3:    // vpopcntd
13826      {
13827         if (mode64) {
13828            /* Break vector into 64-bit double words and do the population count
13829             * on each double word.
13830             */
13831            IRType ty = Ity_I64;
13832            IRTemp bits0_63   = newTemp(Ity_I64);
13833            IRTemp bits64_127 = newTemp(Ity_I64);
13834            IRTemp cnt_bits0_63   = newTemp(Ity_I64);
13835            IRTemp cnt_bits64_127 = newTemp(Ity_I64);
13836
13837            DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
13838
13839            assign(bits0_63,   unop( Iop_V128to64,   mkexpr( vB ) ) );
13840            assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
13841            cnt_bits0_63   = gen_POPCOUNT(ty, bits0_63,   DWORD);
13842            cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
13843
13844            putVReg( vRT_addr, binop( Iop_64HLtoV128,
13845                                      mkexpr( cnt_bits64_127 ),
13846                                      mkexpr( cnt_bits0_63 ) ) );
13847         } else {
13848            /* Break vector into 32-bit words and do the population count
13849             * on each doubleword.
13850             */
13851            IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13852            bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13853            IRTemp cnt_bits0_63   = newTemp(Ity_I64);
13854            IRTemp cnt_bits64_127  = newTemp(Ity_I64);
13855
13856            DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
13857            breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13858
13859            cnt_bits0_63   = gen_vpopcntd_mode32(bits0_31, bits32_63);
13860            cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
13861
13862            putVReg( vRT_addr, binop( Iop_64HLtoV128,
13863                                      mkexpr( cnt_bits64_127 ),
13864                                      mkexpr( cnt_bits0_63 ) ) );
13865         }
13866         break;
13867      }
13868
13869      case 0x50C:  // vgbbd Vector Gather Bits by Bytes by Doubleword
13870         DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
13871         putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
13872         break;
13873
13874      default:
13875         vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
13876         return False;
13877      break;
13878   }
13879   return True;
13880}
13881
13882typedef enum {
13883   PPC_CMP_EQ = 2,
13884   PPC_CMP_GT = 4,
13885   PPC_CMP_GE = 6,
13886   PPC_CMP_LT = 8
13887} ppc_cmp_t;
13888
13889
13890/*
13891  This helper function takes as input the IRExpr returned
13892  from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
13893  in IR form.  This helper function converts it to PPC form.
13894
13895  Map compare result from IR to PPC
13896
13897  FP cmp result | PPC | IR
13898  --------------------------
13899  UN            | 0x1 | 0x45
13900  EQ            | 0x2 | 0x40
13901  GT            | 0x4 | 0x00
13902  LT            | 0x8 | 0x01
13903
13904 condcode = Shl(1, (~(ccIR>>5) & 2)
13905                    | ((ccIR ^ (ccIR>>6)) & 1)
13906*/
13907static IRTemp
13908get_fp_cmp_CR_val (IRExpr * ccIR_expr)
13909{
13910   IRTemp condcode = newTemp( Ity_I32 );
13911   IRTemp ccIR = newTemp( Ity_I32 );
13912
13913   assign(ccIR, ccIR_expr);
13914   assign( condcode,
13915           binop( Iop_Shl32,
13916                  mkU32( 1 ),
13917                  unop( Iop_32to8,
13918                        binop( Iop_Or32,
13919                               binop( Iop_And32,
13920                                      unop( Iop_Not32,
13921                                            binop( Iop_Shr32,
13922                                                   mkexpr( ccIR ),
13923                                                   mkU8( 5 ) ) ),
13924                                      mkU32( 2 ) ),
13925                               binop( Iop_And32,
13926                                      binop( Iop_Xor32,
13927                                             mkexpr( ccIR ),
13928                                             binop( Iop_Shr32,
13929                                                    mkexpr( ccIR ),
13930                                                    mkU8( 6 ) ) ),
13931                                      mkU32( 1 ) ) ) ) ) );
13932   return condcode;
13933}
13934
13935/*
13936 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
13937 * following these special rules:
13938 *   - The max/min of a QNaN and any value is that value
13939 *     (When two QNaNs are being compared, the frA QNaN is the return value.)
13940 *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
13941 *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
13942 */
13943static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
13944{
13945   IRTemp frA_isNaN = newTemp(Ity_I1);
13946   IRTemp frB_isNaN = newTemp(Ity_I1);
13947   IRTemp frA_isSNaN = newTemp(Ity_I1);
13948   IRTemp frB_isSNaN = newTemp(Ity_I1);
13949   IRTemp frA_isQNaN = newTemp(Ity_I1);
13950   IRTemp frB_isQNaN = newTemp(Ity_I1);
13951
13952   assign( frA_isNaN, is_NaN( frA_I64 ) );
13953   assign( frB_isNaN, is_NaN( frB_I64 ) );
13954   // If operand is a NAN and bit 12 is '0', then it's an SNaN
13955   assign( frA_isSNaN,
13956           mkAND1( mkexpr(frA_isNaN),
13957                   binop( Iop_CmpEQ32,
13958                          binop( Iop_And32,
13959                                 unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
13960                                 mkU32( 0x00080000 ) ),
13961                          mkU32( 0 ) ) ) );
13962   assign( frB_isSNaN,
13963           mkAND1( mkexpr(frB_isNaN),
13964                   binop( Iop_CmpEQ32,
13965                          binop( Iop_And32,
13966                                 unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
13967                                 mkU32( 0x00080000 ) ),
13968                          mkU32( 0 ) ) ) );
13969   assign( frA_isQNaN,
13970           mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
13971   assign( frB_isQNaN,
13972           mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
13973
13974   /* Based on the rules specified in the function prologue, the algorithm is as follows:
13975    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
13976    *   if frA is a SNaN
13977    *     result = frA converted to QNaN
13978    *   else if frB is a SNaN
13979    *     result = frB converted to QNaN
13980    *   else if frB is a QNaN
13981    *     result = frA
13982    *   // One of frA or frB was a NaN in order for this function to be called, so
13983    *   // if we get to this point, we KNOW that frA must be a QNaN.
13984    *   else // frA is a QNaN
13985    *     result = frB
13986    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
13987    */
13988
13989#define SNAN_MASK 0x0008000000000000ULL
13990   return
13991   IRExpr_ITE(mkexpr(frA_isSNaN),
13992              /* then: result = frA converted to QNaN */
13993              binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
13994              /* else:  if frB is a SNaN */
13995              IRExpr_ITE(mkexpr(frB_isSNaN),
13996                         /* then: result = frB converted to QNaN */
13997                         binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
13998                         /* else:  if frB is a QNaN */
13999                         IRExpr_ITE(mkexpr(frB_isQNaN),
14000                                    /* then: result = frA */
14001                                    mkexpr(frA_I64),
14002                                    /* else:  frA is a QNaN, so result = frB */
14003                                    mkexpr(frB_I64))));
14004}
14005
14006/*
14007 * Helper function for get_max_min_fp.
14008 */
14009static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
14010{
14011   IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
14012                                                  unop( Iop_ReinterpI64asF64,
14013                                                        mkexpr( src1 ) ),
14014                                                  unop( Iop_ReinterpI64asF64,
14015                                                        mkexpr( src2 ) ) ) );
14016
14017   return IRExpr_ITE( binop( Iop_CmpEQ32,
14018                               mkexpr( src1cmpsrc2 ),
14019                               mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
14020                      /* then: use src1 */
14021                      mkexpr( src1 ),
14022                      /* else: use src2 */
14023                      mkexpr( src2 ) );
14024}
14025
14026/*
14027 * Helper function for "Maximum/Minimum Double Precision" operations.
14028 * Arguments: frA and frb are Ity_I64
14029 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
14030 */
14031static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
14032{
14033   /* There are three special cases where get_fp_cmp_CR_val is not helpful
14034    * for ascertaining the maximum between two doubles:
14035    *   1. The max/min of +0 and -0 is +0.
14036    *   2. The max/min of a QNaN and any value is that value.
14037    *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
14038    * We perform the check for [+/-]0 here in this function and use the
14039    * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
14040    * to do the standard comparison function.
14041    */
14042   IRTemp anyNaN = newTemp(Ity_I1);
14043   IRTemp frA_isZero = newTemp(Ity_I1);
14044   IRTemp frB_isZero = newTemp(Ity_I1);
14045   assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
14046   assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
14047   assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
14048#define MINUS_ZERO 0x8000000000000000ULL
14049
14050   return IRExpr_ITE( /* If both arguments are zero . . . */
14051                     mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
14052                     /* then: if frA is -0 and isMin==True, return -0;
14053                      *     else if frA is +0 and isMin==False; return +0;
14054                      *     otherwise, simply return frB. */
14055                     IRExpr_ITE( binop( Iop_CmpEQ32,
14056                                        unop( Iop_64HIto32,
14057                                              mkexpr( frA_I64 ) ),
14058                                        mkU32( isMin ? 0x80000000 : 0 ) ),
14059                                 mkU64( isMin ? MINUS_ZERO : 0ULL ),
14060                                 mkexpr( frB_I64 ) ),
14061                     /* else: check if either input is a NaN*/
14062                     IRExpr_ITE( mkexpr( anyNaN ),
14063                                 /* then: use "NaN helper" */
14064                                 _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
14065                                 /* else: use "comparison helper" */
14066                                 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
14067}
14068
14069static const HChar * _get_vsx_rdpi_suffix(UInt opc2)
14070{
14071   switch (opc2 & 0x7F) {
14072      case 0x72:
14073         return "m";
14074      case 0x52:
14075         return "p";
14076      case 0x56:
14077         return "c";
14078      case 0x32:
14079         return "z";
14080      case 0x12:
14081         return "";
14082
14083      default: // Impossible to get here
14084         vex_printf("Unrecognized opcode %x\n", opc2);
14085         vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
14086   }
14087}
14088
14089/*
14090 * Helper function for vector/scalar double precision fp round to integer instructions.
14091 */
14092static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
14093{
14094
14095   /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
14096   IRTemp frB = newTemp(Ity_F64);
14097   IRTemp frD = newTemp(Ity_F64);
14098   IRTemp intermediateResult = newTemp(Ity_I64);
14099   IRTemp is_SNAN = newTemp(Ity_I1);
14100   IRExpr * hi32;
14101   IRExpr * rxpi_rm;
14102   switch (opc2 & 0x7F) {
14103      case 0x72:
14104         rxpi_rm = mkU32(Irrm_NegINF);
14105         break;
14106      case 0x52:
14107         rxpi_rm = mkU32(Irrm_PosINF);
14108         break;
14109      case 0x56:
14110         rxpi_rm = get_IR_roundingmode();
14111         break;
14112      case 0x32:
14113         rxpi_rm = mkU32(Irrm_ZERO);
14114         break;
14115      case 0x12:
14116         rxpi_rm = mkU32(Irrm_NEAREST);
14117         break;
14118
14119      default: // Impossible to get here
14120         vex_printf("Unrecognized opcode %x\n", opc2);
14121         vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
14122   }
14123   assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
14124   assign( intermediateResult,
14125           binop( Iop_F64toI64S, rxpi_rm,
14126                  mkexpr( frB ) ) );
14127
14128   /* don't use the rounded integer if frB is outside -9e18..9e18 */
14129   /* F64 has only log10(2**52) significant digits anyway */
14130   /* need to preserve sign of zero */
14131   /*   frD = (fabs(frB) > 9e18) ? frB :
14132            (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
14133   assign( frD,
14134           IRExpr_ITE(
14135              binop( Iop_CmpNE8,
14136                     unop( Iop_32to8,
14137                           binop( Iop_CmpF64,
14138                                  IRExpr_Const( IRConst_F64( 9e18 ) ),
14139                                  unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
14140                     mkU8(0) ),
14141              mkexpr( frB ),
14142              IRExpr_ITE(
14143                 binop( Iop_CmpNE32,
14144                        binop( Iop_Shr32,
14145                               unop( Iop_64HIto32,
14146                                     mkexpr( frB_I64 ) ),
14147                               mkU8( 31 ) ),
14148                        mkU32(0) ),
14149                 unop( Iop_NegF64,
14150                       unop( Iop_AbsF64,
14151                             binop( Iop_I64StoF64,
14152                                    mkU32( 0 ),
14153                                    mkexpr( intermediateResult ) ) ) ),
14154                 binop( Iop_I64StoF64,
14155                        mkU32( 0 ),
14156                        mkexpr( intermediateResult ) )
14157              )
14158           )
14159   );
14160
14161   /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
14162    * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
14163    */
14164#define SNAN_MASK 0x0008000000000000ULL
14165   hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
14166   assign( is_SNAN,
14167           mkAND1( is_NaN( frB_I64 ),
14168                   binop( Iop_CmpEQ32,
14169                          binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
14170                          mkU32( 0 ) ) ) );
14171
14172   return IRExpr_ITE( mkexpr( is_SNAN ),
14173                        unop( Iop_ReinterpI64asF64,
14174                              binop( Iop_Xor64,
14175                                     mkU64( SNAN_MASK ),
14176                                     mkexpr( frB_I64 ) ) ),
14177                      mkexpr( frD ));
14178}
14179
14180/*
14181 * Miscellaneous VSX vector instructions
14182 */
14183static Bool
14184dis_vxv_misc ( UInt theInstr, UInt opc2 )
14185{
14186   /* XX3-Form */
14187   UChar opc1 = ifieldOPC( theInstr );
14188   UChar XT = ifieldRegXT( theInstr );
14189   UChar XB = ifieldRegXB( theInstr );
14190
14191   if (opc1 != 0x3C) {
14192      vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
14193      return False;
14194   }
14195
14196   switch (opc2) {
14197      case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
14198      case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
14199                   //             Double-Precision)
14200      {
14201         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
14202         IRExpr* rm  = get_IR_roundingmode();
14203         IRTemp frB = newTemp(Ity_I64);
14204         IRTemp frB2 = newTemp(Ity_I64);
14205         Bool redp = opc2 == 0x1B4;
14206         IRTemp sqrtHi = newTemp(Ity_F64);
14207         IRTemp sqrtLo = newTemp(Ity_F64);
14208         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
14209         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14210
14211         DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", XT, XB);
14212         if (!redp) {
14213            assign( sqrtHi,
14214                    binop( Iop_SqrtF64,
14215                           rm,
14216                           unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
14217            assign( sqrtLo,
14218                    binop( Iop_SqrtF64,
14219                           rm,
14220                           unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
14221         }
14222         putVSReg( XT,
14223                   binop( Iop_64HLtoV128,
14224                          unop( Iop_ReinterpF64asI64,
14225                                triop( Iop_DivF64,
14226                                       rm,
14227                                       ieee_one,
14228                                       redp ? unop( Iop_ReinterpI64asF64,
14229                                                    mkexpr( frB ) )
14230                                            : mkexpr( sqrtHi ) ) ),
14231                          unop( Iop_ReinterpF64asI64,
14232                                triop( Iop_DivF64,
14233                                       rm,
14234                                       ieee_one,
14235                                       redp ? unop( Iop_ReinterpI64asF64,
14236                                                    mkexpr( frB2 ) )
14237                                            : mkexpr( sqrtLo ) ) ) ) );
14238         break;
14239
14240      }
14241      case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
14242      case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
14243      {
14244         IRTemp b3, b2, b1, b0;
14245         IRTemp res0 = newTemp(Ity_I32);
14246         IRTemp res1 = newTemp(Ity_I32);
14247         IRTemp res2 = newTemp(Ity_I32);
14248         IRTemp res3 = newTemp(Ity_I32);
14249         IRTemp sqrt3 = newTemp(Ity_F64);
14250         IRTemp sqrt2 = newTemp(Ity_F64);
14251         IRTemp sqrt1 = newTemp(Ity_F64);
14252         IRTemp sqrt0 = newTemp(Ity_F64);
14253         IRExpr* rm  = get_IR_roundingmode();
14254         Bool resp = opc2 == 0x134;
14255
14256         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
14257
14258         b3 = b2 = b1 = b0 = IRTemp_INVALID;
14259         DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", XT, XB);
14260         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
14261
14262         if (!resp) {
14263            assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
14264            assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
14265            assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
14266            assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
14267         }
14268
14269         assign( res0,
14270                 unop( Iop_ReinterpF32asI32,
14271                       unop( Iop_TruncF64asF32,
14272                             triop( Iop_DivF64r32,
14273                                    rm,
14274                                    ieee_one,
14275                                    resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
14276         assign( res1,
14277                 unop( Iop_ReinterpF32asI32,
14278                       unop( Iop_TruncF64asF32,
14279                             triop( Iop_DivF64r32,
14280                                    rm,
14281                                    ieee_one,
14282                                    resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
14283         assign( res2,
14284                 unop( Iop_ReinterpF32asI32,
14285                       unop( Iop_TruncF64asF32,
14286                             triop( Iop_DivF64r32,
14287                                    rm,
14288                                    ieee_one,
14289                                    resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
14290         assign( res3,
14291                 unop( Iop_ReinterpF32asI32,
14292                       unop( Iop_TruncF64asF32,
14293                             triop( Iop_DivF64r32,
14294                                    rm,
14295                                    ieee_one,
14296                                    resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
14297         putVSReg( XT,
14298                   binop( Iop_64HLtoV128,
14299                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
14300                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
14301         break;
14302      }
14303      case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
14304      case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
14305      {
14306         UChar XA = ifieldRegXA( theInstr );
14307         IRTemp a3, a2, a1, a0;
14308         IRTemp b3, b2, b1, b0;
14309         IRTemp res0 = newTemp( Ity_I32 );
14310         IRTemp res1 = newTemp( Ity_I32 );
14311         IRTemp res2 = newTemp( Ity_I32 );
14312         IRTemp res3 = newTemp( Ity_I32 );
14313         IRTemp a0_I64 = newTemp( Ity_I64 );
14314         IRTemp a1_I64 = newTemp( Ity_I64 );
14315         IRTemp a2_I64 = newTemp( Ity_I64 );
14316         IRTemp a3_I64 = newTemp( Ity_I64 );
14317         IRTemp b0_I64 = newTemp( Ity_I64 );
14318         IRTemp b1_I64 = newTemp( Ity_I64 );
14319         IRTemp b2_I64 = newTemp( Ity_I64 );
14320         IRTemp b3_I64 = newTemp( Ity_I64 );
14321
14322         Bool isMin = opc2 == 0x320 ? True : False;
14323
14324         a3 = a2 = a1 = a0 = IRTemp_INVALID;
14325         b3 = b2 = b1 = b0 = IRTemp_INVALID;
14326         DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", XT, XA, XB);
14327         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
14328         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
14329         assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
14330         assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
14331         assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
14332         assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
14333         assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
14334         assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
14335         assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
14336         assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
14337         assign( res0,
14338                 unop( Iop_ReinterpF32asI32,
14339                       unop( Iop_TruncF64asF32,
14340                             unop( Iop_ReinterpI64asF64,
14341                                   get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
14342         assign( res1,
14343                 unop( Iop_ReinterpF32asI32,
14344                       unop( Iop_TruncF64asF32,
14345                             unop( Iop_ReinterpI64asF64,
14346                                   get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
14347         assign( res2,
14348                 unop( Iop_ReinterpF32asI32,
14349                       unop( Iop_TruncF64asF32,
14350                             unop( Iop_ReinterpI64asF64,
14351                                   get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
14352         assign( res3,
14353                 unop( Iop_ReinterpF32asI32,
14354                       unop( Iop_TruncF64asF32,
14355                             unop( Iop_ReinterpI64asF64,
14356                                   get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
14357         putVSReg( XT,
14358                   binop( Iop_64HLtoV128,
14359                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
14360                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
14361         break;
14362      }
14363      case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
14364      case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
14365      {
14366         UChar XA = ifieldRegXA( theInstr );
14367         IRTemp frA = newTemp(Ity_I64);
14368         IRTemp frB = newTemp(Ity_I64);
14369         IRTemp frA2 = newTemp(Ity_I64);
14370         IRTemp frB2 = newTemp(Ity_I64);
14371         Bool isMin = opc2 == 0x3A0 ? True : False;
14372
14373         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
14374         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
14375         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
14376         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14377         DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", XT, XA, XB);
14378         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
14379
14380         break;
14381      }
14382      case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
14383      {
14384         UChar XA = ifieldRegXA( theInstr );
14385         IRTemp frA = newTemp(Ity_I64);
14386         IRTemp frB = newTemp(Ity_I64);
14387         IRTemp frA2 = newTemp(Ity_I64);
14388         IRTemp frB2 = newTemp(Ity_I64);
14389         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
14390         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
14391         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
14392         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14393
14394         DIP("xvcpsgndp v%d,v%d,v%d\n", XT, XA, XB);
14395         putVSReg( XT,
14396                   binop( Iop_64HLtoV128,
14397                          binop( Iop_Or64,
14398                                 binop( Iop_And64,
14399                                        mkexpr( frA ),
14400                                        mkU64( SIGN_BIT ) ),
14401                                 binop( Iop_And64,
14402                                        mkexpr( frB ),
14403                                        mkU64( SIGN_MASK ) ) ),
14404                          binop( Iop_Or64,
14405                                 binop( Iop_And64,
14406                                        mkexpr( frA2 ),
14407                                        mkU64( SIGN_BIT ) ),
14408                                 binop( Iop_And64,
14409                                        mkexpr( frB2 ),
14410                                        mkU64( SIGN_MASK ) ) ) ) );
14411         break;
14412      }
14413      case 0x340: // xvcpsgnsp
14414      {
14415         UChar XA = ifieldRegXA( theInstr );
14416         IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
14417         IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
14418         IRTemp resHi = newTemp(Ity_I64);
14419         IRTemp resLo = newTemp(Ity_I64);
14420
14421         a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
14422         b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
14423         DIP("xvcpsgnsp v%d,v%d v%d\n",XT, XA, XB);
14424         breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
14425         breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
14426
14427         assign( resHi,
14428                 binop( Iop_32HLto64,
14429                        binop( Iop_Or32,
14430                               binop( Iop_And32,
14431                                      unop(Iop_64to32, mkexpr( a3_I64 ) ),
14432                                      mkU32( SIGN_BIT32 ) ),
14433                               binop( Iop_And32,
14434                                      unop(Iop_64to32, mkexpr( b3_I64 ) ),
14435                                      mkU32( SIGN_MASK32) ) ),
14436
14437                        binop( Iop_Or32,
14438                               binop( Iop_And32,
14439                                      unop(Iop_64to32, mkexpr( a2_I64 ) ),
14440                                      mkU32( SIGN_BIT32 ) ),
14441                               binop( Iop_And32,
14442                                      unop(Iop_64to32, mkexpr( b2_I64 ) ),
14443                                      mkU32( SIGN_MASK32 ) ) ) ) );
14444         assign( resLo,
14445                 binop( Iop_32HLto64,
14446                        binop( Iop_Or32,
14447                               binop( Iop_And32,
14448                                      unop(Iop_64to32, mkexpr( a1_I64 ) ),
14449                                      mkU32( SIGN_BIT32 ) ),
14450                               binop( Iop_And32,
14451                                      unop(Iop_64to32, mkexpr( b1_I64 ) ),
14452                                      mkU32( SIGN_MASK32 ) ) ),
14453
14454                        binop( Iop_Or32,
14455                               binop( Iop_And32,
14456                                      unop(Iop_64to32, mkexpr( a0_I64 ) ),
14457                                      mkU32( SIGN_BIT32 ) ),
14458                               binop( Iop_And32,
14459                                      unop(Iop_64to32, mkexpr( b0_I64 ) ),
14460                                      mkU32( SIGN_MASK32 ) ) ) ) );
14461         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
14462         break;
14463      }
14464      case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
14465      case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
14466      {
14467         IRTemp frB = newTemp(Ity_F64);
14468         IRTemp frB2 = newTemp(Ity_F64);
14469         IRTemp abs_resultHi = newTemp(Ity_F64);
14470         IRTemp abs_resultLo = newTemp(Ity_F64);
14471         Bool make_negative = (opc2 == 0x3D2) ? True : False;
14472         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14473         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14474
14475         DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", XT, XB);
14476         if (make_negative) {
14477            assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
14478            assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
14479
14480         } else {
14481            assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
14482            assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
14483         }
14484         putVSReg( XT, binop( Iop_64HLtoV128,
14485                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
14486                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
14487         break;
14488      }
14489      case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
14490      case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
14491      {
14492         /*
14493          * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
14494          * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
14495          * of this function is so easy using shifts, I choose to emulate this instruction that
14496          * way versus a native instruction method of implementation.
14497          */
14498         Bool make_negative = (opc2 == 0x352) ? True : False;
14499         IRTemp shiftVector = newTemp(Ity_V128);
14500         IRTemp absVal_vector = newTemp(Ity_V128);
14501         assign( shiftVector,
14502                 binop( Iop_64HLtoV128,
14503                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
14504                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
14505         assign( absVal_vector,
14506                   binop( Iop_Shr32x4,
14507                          binop( Iop_Shl32x4,
14508                                 getVSReg( XB ),
14509                                 mkexpr( shiftVector ) ),
14510                          mkexpr( shiftVector ) ) );
14511         if (make_negative) {
14512            IRTemp signBit_vector = newTemp(Ity_V128);
14513            assign( signBit_vector,
14514                    binop( Iop_64HLtoV128,
14515                           binop( Iop_32HLto64,
14516                                  mkU32( 0x80000000 ),
14517                                  mkU32( 0x80000000 ) ),
14518                           binop( Iop_32HLto64,
14519                                  mkU32( 0x80000000 ),
14520                                  mkU32( 0x80000000 ) ) ) );
14521            putVSReg( XT,
14522                      binop( Iop_OrV128,
14523                             mkexpr( absVal_vector ),
14524                             mkexpr( signBit_vector ) ) );
14525         } else {
14526            putVSReg( XT, mkexpr( absVal_vector ) );
14527         }
14528         break;
14529      }
14530      case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
14531      {
14532         IRTemp frB = newTemp(Ity_F64);
14533         IRTemp frB2 = newTemp(Ity_F64);
14534         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14535         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14536         DIP("xvnegdp v%d,v%d\n",  XT, XB);
14537         putVSReg( XT,
14538                   binop( Iop_64HLtoV128,
14539                          unop( Iop_ReinterpF64asI64,
14540                                unop( Iop_NegF64, mkexpr( frB ) ) ),
14541                          unop( Iop_ReinterpF64asI64,
14542                                unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
14543         break;
14544      }
14545      case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
14546      case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
14547      case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
14548      case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
14549      case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
14550      {
14551         IRTemp frBHi_I64 = newTemp(Ity_I64);
14552         IRTemp frBLo_I64 = newTemp(Ity_I64);
14553         IRExpr * frD_fp_roundHi = NULL;
14554         IRExpr * frD_fp_roundLo = NULL;
14555
14556         assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
14557         frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
14558         assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
14559         frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
14560
14561         DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
14562         putVSReg( XT,
14563                   binop( Iop_64HLtoV128,
14564                          unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
14565                          unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
14566         break;
14567      }
14568      case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
14569      case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
14570      case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
14571      case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
14572      case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
14573      {
14574         const HChar * insn_suffix = NULL;
14575         IROp op;
14576         if (opc2 != 0x156) {
14577            // Use pre-defined IRop's for vrfi{m|n|p|z}
14578            switch (opc2) {
14579               case 0x112:
14580                  insn_suffix = "";
14581                  op = Iop_RoundF32x4_RN;
14582                  break;
14583               case 0x172:
14584                  insn_suffix = "m";
14585                  op = Iop_RoundF32x4_RM;
14586                  break;
14587               case 0x152:
14588                  insn_suffix = "p";
14589                  op = Iop_RoundF32x4_RP;
14590                  break;
14591               case 0x132:
14592                  insn_suffix = "z";
14593                  op = Iop_RoundF32x4_RZ;
14594                  break;
14595
14596               default:
14597                  vex_printf("Unrecognized opcode %x\n", opc2);
14598                  vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
14599            }
14600            DIP("xvrspi%s v%d,v%d\n", insn_suffix, XT, XB);
14601            putVSReg( XT, unop( op, getVSReg(XB) ) );
14602         } else {
14603            // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
14604            IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
14605            IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
14606            IRTemp b3_I64 = newTemp(Ity_I64);
14607            IRTemp b2_I64 = newTemp(Ity_I64);
14608            IRTemp b1_I64 = newTemp(Ity_I64);
14609            IRTemp b0_I64 = newTemp(Ity_I64);
14610
14611            b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
14612            frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
14613            breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
14614            assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
14615            assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
14616            assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
14617            assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
14618            frD_fp_roundb3 = unop(Iop_TruncF64asF32,
14619                                  _do_vsx_fp_roundToInt(b3_I64, opc2));
14620            frD_fp_roundb2 = unop(Iop_TruncF64asF32,
14621                                  _do_vsx_fp_roundToInt(b2_I64, opc2));
14622            frD_fp_roundb1 = unop(Iop_TruncF64asF32,
14623                                  _do_vsx_fp_roundToInt(b1_I64, opc2));
14624            frD_fp_roundb0 = unop(Iop_TruncF64asF32,
14625                                  _do_vsx_fp_roundToInt(b0_I64, opc2));
14626            DIP("xvrspic v%d,v%d\n", XT, XB);
14627            putVSReg( XT,
14628                      binop( Iop_64HLtoV128,
14629                             binop( Iop_32HLto64,
14630                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
14631                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
14632                             binop( Iop_32HLto64,
14633                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
14634                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
14635         }
14636         break;
14637      }
14638
14639      default:
14640         vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
14641         return False;
14642   }
14643   return True;
14644}
14645
14646
14647/*
14648 * VSX Scalar Floating Point Arithmetic Instructions
14649 */
14650static Bool
14651dis_vxs_arith ( UInt theInstr, UInt opc2 )
14652{
14653   /* XX3-Form */
14654   UChar opc1 = ifieldOPC( theInstr );
14655   UChar XT = ifieldRegXT( theInstr );
14656   UChar XA = ifieldRegXA( theInstr );
14657   UChar XB = ifieldRegXB( theInstr );
14658   IRExpr* rm = get_IR_roundingmode();
14659   IRTemp frA = newTemp(Ity_F64);
14660   IRTemp frB = newTemp(Ity_F64);
14661
14662   if (opc1 != 0x3C) {
14663      vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
14664      return False;
14665   }
14666
14667   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
14668   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14669
14670   /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
14671    * of VSX[XT] are undefined after the operation; therefore, we can simply set
14672    * element to zero where it makes sense to do so.
14673    */
14674   switch (opc2) {
14675      case 0x000: // xsaddsp  (VSX Scalar Add Single-Precision)
14676         DIP("xsaddsp v%d,v%d,v%d\n", XT, XA, XB);
14677         putVSReg( XT, binop( Iop_64HLtoV128,
14678                              unop( Iop_ReinterpF64asI64,
14679                                    binop( Iop_RoundF64toF32, rm,
14680                                           triop( Iop_AddF64, rm,
14681                                                  mkexpr( frA ),
14682                                                  mkexpr( frB ) ) ) ),
14683                              mkU64( 0 ) ) );
14684         break;
14685      case 0x020: // xssubsp  (VSX Scalar Subtract Single-Precision)
14686         DIP("xssubsp v%d,v%d,v%d\n", XT, XA, XB);
14687         putVSReg( XT, binop( Iop_64HLtoV128,
14688                              unop( Iop_ReinterpF64asI64,
14689                                    binop( Iop_RoundF64toF32, rm,
14690                                           triop( Iop_SubF64, rm,
14691                                                  mkexpr( frA ),
14692                                                  mkexpr( frB ) ) ) ),
14693                              mkU64( 0 ) ) );
14694         break;
14695      case 0x080: // xsadddp (VSX scalar add double-precision)
14696         DIP("xsadddp v%d,v%d,v%d\n", XT, XA, XB);
14697         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14698                                                    triop( Iop_AddF64, rm,
14699                                                           mkexpr( frA ),
14700                                                           mkexpr( frB ) ) ),
14701                              mkU64( 0 ) ) );
14702         break;
14703      case 0x060: // xsdivsp (VSX scalar divide single-precision)
14704         DIP("xsdivsp v%d,v%d,v%d\n", XT, XA, XB);
14705         putVSReg( XT, binop( Iop_64HLtoV128,
14706                              unop( Iop_ReinterpF64asI64,
14707                                    binop( Iop_RoundF64toF32, rm,
14708                                           triop( Iop_DivF64, rm,
14709                                                  mkexpr( frA ),
14710                                                  mkexpr( frB ) ) ) ),
14711                               mkU64( 0 ) ) );
14712         break;
14713      case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
14714         DIP("xsdivdp v%d,v%d,v%d\n", XT, XA, XB);
14715         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14716                                                    triop( Iop_DivF64, rm,
14717                                                           mkexpr( frA ),
14718                                                           mkexpr( frB ) ) ),
14719                              mkU64( 0 ) ) );
14720         break;
14721      case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
14722                               * single-precision)
14723                               */
14724      {
14725         IRTemp frT = newTemp(Ity_F64);
14726         Bool mdp = opc2 == 0x024;
14727         DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14728         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14729                                                        getVSReg( XT ) ) ) );
14730         putVSReg( XT,
14731                   binop( Iop_64HLtoV128,
14732                          unop( Iop_ReinterpF64asI64,
14733                                binop( Iop_RoundF64toF32, rm,
14734                                       qop( Iop_MAddF64, rm,
14735                                            mkexpr( frA ),
14736                                            mkexpr( mdp ? frT : frB ),
14737                                            mkexpr( mdp ? frB : frT ) ) ) ),
14738                          mkU64( 0 ) ) );
14739         break;
14740      }
14741      case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
14742      {
14743         IRTemp frT = newTemp(Ity_F64);
14744         Bool mdp = opc2 == 0x0A4;
14745         DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14746         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14747                                                        getVSReg( XT ) ) ) );
14748         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14749                                                    qop( Iop_MAddF64, rm,
14750                                                         mkexpr( frA ),
14751                                                         mkexpr( mdp ? frT : frB ),
14752                                                         mkexpr( mdp ? frB : frT ) ) ),
14753                              mkU64( 0 ) ) );
14754         break;
14755      }
14756      case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
14757                               * multiply-subtract single-precision)
14758			       */
14759      {
14760         IRTemp frT = newTemp(Ity_F64);
14761         Bool mdp = opc2 == 0x064;
14762         DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14763         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14764                                                        getVSReg( XT ) ) ) );
14765         putVSReg( XT,
14766                   binop( Iop_64HLtoV128,
14767                          unop( Iop_ReinterpF64asI64,
14768                                binop( Iop_RoundF64toF32, rm,
14769                                       qop( Iop_MSubF64, rm,
14770                                            mkexpr( frA ),
14771                                            mkexpr( mdp ? frT : frB ),
14772                                            mkexpr( mdp ? frB : frT ) ) ) ),
14773                          mkU64( 0 ) ) );
14774         break;
14775      }
14776      case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
14777      {
14778         IRTemp frT = newTemp(Ity_F64);
14779         Bool mdp = opc2 == 0x0E4;
14780         DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14781         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14782                                                        getVSReg( XT ) ) ) );
14783         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14784                                                    qop( Iop_MSubF64, rm,
14785                                                         mkexpr( frA ),
14786                                                         mkexpr( mdp ? frT : frB ),
14787                                                         mkexpr( mdp ? frB : frT ) ) ),
14788                              mkU64( 0 ) ) );
14789         break;
14790      }
14791      case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
14792      {
14793         /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
14794          * of fnmadd and use pretty much the same code. However, that code has a bug in the
14795          * way it blindly negates the signbit, even if the floating point result is a NaN.
14796          * So, the TODO is to fix fnmadd (which I'll do in a different patch).
14797          * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
14798          * bit for NaN result.
14799          */
14800         Bool mdp = opc2 == 0x2A4;
14801         IRTemp frT = newTemp(Ity_F64);
14802         IRTemp maddResult = newTemp(Ity_I64);
14803
14804         DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14805         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14806                                                        getVSReg( XT ) ) ) );
14807         assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
14808                                                              mkexpr( frA ),
14809                                                              mkexpr( mdp ? frT : frB ),
14810                                                              mkexpr( mdp ? frB : frT ) ) ) );
14811
14812         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
14813                              mkU64( 0 ) ) );
14814         break;
14815      }
14816      case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
14817                               * multiply-add single-precision)
14818                               */
14819      {
14820         Bool mdp = opc2 == 0x224;
14821         IRTemp frT = newTemp(Ity_F64);
14822         IRTemp maddResult = newTemp(Ity_I64);
14823
14824         DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14825         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14826                                                        getVSReg( XT ) ) ) );
14827         assign( maddResult,
14828                 unop( Iop_ReinterpF64asI64,
14829                       binop( Iop_RoundF64toF32, rm,
14830                              qop( Iop_MAddF64, rm,
14831                                   mkexpr( frA ),
14832                                   mkexpr( mdp ? frT : frB ),
14833                                   mkexpr( mdp ? frB : frT ) ) ) ) );
14834
14835         putVSReg( XT, binop( Iop_64HLtoV128,
14836                              mkexpr( getNegatedResult(maddResult) ),
14837                              mkU64( 0 ) ) );
14838         break;
14839      }
14840      case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
14841                               * Multiply-Subtract Single-Precision)
14842                               */
14843      {
14844         IRTemp frT = newTemp(Ity_F64);
14845         Bool mdp = opc2 == 0x264;
14846         IRTemp msubResult = newTemp(Ity_I64);
14847
14848         DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14849         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14850                                                        getVSReg( XT ) ) ) );
14851         assign( msubResult,
14852                 unop( Iop_ReinterpF64asI64,
14853                       binop( Iop_RoundF64toF32, rm,
14854                              qop( Iop_MSubF64, rm,
14855                                   mkexpr( frA ),
14856                                   mkexpr( mdp ? frT : frB ),
14857                                   mkexpr( mdp ? frB : frT ) ) ) ) );
14858
14859         putVSReg( XT, binop( Iop_64HLtoV128,
14860                              mkexpr( getNegatedResult(msubResult) ),
14861                              mkU64( 0 ) ) );
14862
14863         break;
14864      }
14865
14866      case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
14867      {
14868         IRTemp frT = newTemp(Ity_F64);
14869         Bool mdp = opc2 == 0x2E4;
14870         IRTemp msubResult = newTemp(Ity_I64);
14871
14872         DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14873         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14874                                                        getVSReg( XT ) ) ) );
14875         assign(msubResult, unop( Iop_ReinterpF64asI64,
14876                                      qop( Iop_MSubF64,
14877                                           rm,
14878                                           mkexpr( frA ),
14879                                           mkexpr( mdp ? frT : frB ),
14880                                           mkexpr( mdp ? frB : frT ) ) ));
14881
14882         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
14883
14884         break;
14885      }
14886
14887      case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
14888         DIP("xsmulsp v%d,v%d,v%d\n", XT, XA, XB);
14889         putVSReg( XT, binop( Iop_64HLtoV128,
14890                              unop( Iop_ReinterpF64asI64,
14891                                    binop( Iop_RoundF64toF32, rm,
14892                                           triop( Iop_MulF64, rm,
14893                                                   mkexpr( frA ),
14894                                                   mkexpr( frB ) ) ) ),
14895                              mkU64( 0 ) ) );
14896         break;
14897
14898      case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
14899         DIP("xsmuldp v%d,v%d,v%d\n", XT, XA, XB);
14900         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14901                                                    triop( Iop_MulF64, rm,
14902                                                           mkexpr( frA ),
14903                                                           mkexpr( frB ) ) ),
14904                              mkU64( 0 ) ) );
14905         break;
14906      case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
14907         DIP("xssubdp v%d,v%d,v%d\n", XT, XA, XB);
14908         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14909                                                    triop( Iop_SubF64, rm,
14910                                                           mkexpr( frA ),
14911                                                           mkexpr( frB ) ) ),
14912                              mkU64( 0 ) ) );
14913         break;
14914
14915      case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
14916         DIP("xssqrtsp v%d,v%d\n", XT, XB);
14917         putVSReg( XT,
14918                   binop( Iop_64HLtoV128,
14919                          unop( Iop_ReinterpF64asI64,
14920                                binop( Iop_RoundF64toF32, rm,
14921                                       binop( Iop_SqrtF64, rm,
14922                                              mkexpr( frB ) ) ) ),
14923                          mkU64( 0 ) ) );
14924         break;
14925
14926      case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
14927         DIP("xssqrtdp v%d,v%d\n", XT, XB);
14928         putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14929                                                     binop( Iop_SqrtF64, rm,
14930                                                            mkexpr( frB ) ) ),
14931                               mkU64( 0 ) ) );
14932         break;
14933
14934      case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
14935      {
14936         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
14937         IRTemp frA_I64 = newTemp(Ity_I64);
14938         IRTemp frB_I64 = newTemp(Ity_I64);
14939         DIP("xstdivdp crf%d,v%d,v%d\n", crfD, XA, XB);
14940         assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
14941         assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
14942         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
14943         break;
14944      }
14945      case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
14946      {
14947         IRTemp frB_I64 = newTemp(Ity_I64);
14948         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
14949         IRTemp flags = newTemp(Ity_I32);
14950         IRTemp  fe_flag, fg_flag;
14951         fe_flag = fg_flag = IRTemp_INVALID;
14952         DIP("xstsqrtdp v%d,v%d\n", XT, XB);
14953         assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
14954         do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
14955         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
14956          * where fl_flag == 1 on ppc64.
14957          */
14958         assign( flags,
14959                 binop( Iop_Or32,
14960                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
14961                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
14962                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
14963         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
14964         break;
14965      }
14966
14967      default:
14968         vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
14969         return False;
14970   }
14971
14972   return True;
14973}
14974
14975
14976/*
14977 * VSX Floating Point Compare Instructions
14978 */
14979static Bool
14980dis_vx_cmp( UInt theInstr, UInt opc2 )
14981{
14982   /* XX3-Form and XX2-Form */
14983   UChar opc1 = ifieldOPC( theInstr );
14984   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
14985   IRTemp ccPPC32;
14986   UChar XA       = ifieldRegXA ( theInstr );
14987   UChar XB       = ifieldRegXB ( theInstr );
14988   IRTemp frA     = newTemp(Ity_F64);
14989   IRTemp frB     = newTemp(Ity_F64);
14990
14991   if (opc1 != 0x3C) {
14992      vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
14993      return False;
14994   }
14995
14996   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
14997   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14998   switch (opc2) {
14999      case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
15000         /* Note: Differences between xscmpudp and xscmpodp are only in
15001          * exception flag settings, which aren't supported anyway. */
15002         DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
15003                                           crfD, XA, XB);
15004         ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
15005         putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
15006         break;
15007
15008      default:
15009         vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
15010         return False;
15011   }
15012   return True;
15013}
15014
15015static void
15016do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
15017                 ppc_cmp_t cmp_type )
15018{
15019   IRTemp frA_hi     = newTemp(Ity_F64);
15020   IRTemp frB_hi     = newTemp(Ity_F64);
15021   IRTemp frA_lo     = newTemp(Ity_F64);
15022   IRTemp frB_lo     = newTemp(Ity_F64);
15023   IRTemp ccPPC32    = newTemp(Ity_I32);
15024   IRTemp ccIR_hi;
15025   IRTemp ccIR_lo;
15026
15027   IRTemp hiResult = newTemp(Ity_I64);
15028   IRTemp loResult = newTemp(Ity_I64);
15029   IRTemp hiEQlo = newTemp(Ity_I1);
15030   IRTemp all_elem_true = newTemp(Ity_I32);
15031   IRTemp all_elem_false = newTemp(Ity_I32);
15032
15033   assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
15034   assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
15035   assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
15036   assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
15037
15038   ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
15039                                       mkexpr( frA_hi ),
15040                                       mkexpr( frB_hi ) ) );
15041   ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
15042                                       mkexpr( frA_lo ),
15043                                       mkexpr( frB_lo ) ) );
15044
15045   if (cmp_type != PPC_CMP_GE) {
15046      assign( hiResult,
15047              unop( Iop_1Sto64,
15048                    binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
15049      assign( loResult,
15050              unop( Iop_1Sto64,
15051                    binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
15052   } else {
15053      // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
15054      // the other element compare may return "2" (for "equal to").
15055      IRTemp lo_GE = newTemp(Ity_I1);
15056      IRTemp hi_GE = newTemp(Ity_I1);
15057
15058      assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
15059                           binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
15060      assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
15061
15062      assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
15063                           binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
15064      assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
15065   }
15066
15067   // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
15068   assign( hiEQlo,
15069           binop( Iop_CmpEQ32,
15070                  unop( Iop_64to32, mkexpr( hiResult ) ),
15071                  unop( Iop_64to32, mkexpr( loResult ) ) ) );
15072   putVSReg( XT,
15073             binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
15074
15075   assign( all_elem_true,
15076           unop( Iop_1Uto32,
15077                 mkAND1( mkexpr( hiEQlo ),
15078                         binop( Iop_CmpEQ32,
15079                                mkU32( 0xffffffff ),
15080                                unop( Iop_64to32,
15081                                mkexpr( hiResult ) ) ) ) ) );
15082
15083   assign( all_elem_false,
15084           unop( Iop_1Uto32,
15085                 mkAND1( mkexpr( hiEQlo ),
15086                         binop( Iop_CmpEQ32,
15087                                mkU32( 0 ),
15088                                unop( Iop_64to32,
15089                                mkexpr( hiResult ) ) ) ) ) );
15090   assign( ccPPC32,
15091           binop( Iop_Or32,
15092                  binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
15093                  binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
15094
15095   if (flag_rC) {
15096      putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
15097   }
15098}
15099
15100/*
15101 * VSX Vector Compare Instructions
15102 */
15103static Bool
15104dis_vvec_cmp( UInt theInstr, UInt opc2 )
15105{
15106   /* XX3-Form */
15107   UChar opc1 = ifieldOPC( theInstr );
15108   UChar XT = ifieldRegXT ( theInstr );
15109   UChar XA = ifieldRegXA ( theInstr );
15110   UChar XB = ifieldRegXB ( theInstr );
15111   UChar flag_rC  = ifieldBIT10(theInstr);
15112   IRTemp vA = newTemp( Ity_V128 );
15113   IRTemp vB = newTemp( Ity_V128 );
15114
15115   if (opc1 != 0x3C) {
15116      vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
15117      return False;
15118   }
15119
15120   assign( vA, getVSReg( XA ) );
15121   assign( vB, getVSReg( XB ) );
15122
15123   switch (opc2) {
15124      case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
15125      {
15126         DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15127             XT, XA, XB);
15128         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
15129         break;
15130      }
15131
15132      case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
15133      {
15134         DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15135             XT, XA, XB);
15136         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
15137         break;
15138      }
15139
15140      case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
15141      {
15142         DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15143             XT, XA, XB);
15144         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
15145         break;
15146      }
15147
15148      case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
15149      {
15150         IRTemp vD = newTemp(Ity_V128);
15151
15152         DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15153             XT, XA, XB);
15154         assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
15155         putVSReg( XT, mkexpr(vD) );
15156         if (flag_rC) {
15157            set_AV_CR6( mkexpr(vD), True );
15158         }
15159         break;
15160      }
15161
15162      case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
15163      {
15164         IRTemp vD = newTemp(Ity_V128);
15165
15166         DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15167             XT, XA, XB);
15168         assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
15169         putVSReg( XT, mkexpr(vD) );
15170         if (flag_rC) {
15171            set_AV_CR6( mkexpr(vD), True );
15172         }
15173         break;
15174      }
15175
15176      case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
15177      {
15178         IRTemp vD = newTemp(Ity_V128);
15179
15180         DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15181             XT, XA, XB);
15182         assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
15183         putVSReg( XT, mkexpr(vD) );
15184         if (flag_rC) {
15185            set_AV_CR6( mkexpr(vD), True );
15186         }
15187         break;
15188      }
15189
15190      default:
15191         vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
15192         return False;
15193   }
15194   return True;
15195}
15196/*
15197 * Miscellaneous VSX Scalar Instructions
15198 */
15199static Bool
15200dis_vxs_misc( UInt theInstr, UInt opc2 )
15201{
15202#define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
15203   /* XX3-Form and XX2-Form */
15204   UChar opc1 = ifieldOPC( theInstr );
15205   UChar XT = ifieldRegXT ( theInstr );
15206   UChar XA = ifieldRegXA ( theInstr );
15207   UChar XB = ifieldRegXB ( theInstr );
15208   IRTemp vA = newTemp( Ity_V128 );
15209   IRTemp vB = newTemp( Ity_V128 );
15210
15211   if (opc1 != 0x3C) {
15212      vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
15213      return False;
15214   }
15215
15216   assign( vA, getVSReg( XA ) );
15217   assign( vB, getVSReg( XB ) );
15218
15219   /* For all the VSX move instructions, the contents of doubleword element 1
15220    * of VSX[XT] are undefined after the operation; therefore, we can simply
15221    * move the entire array element where it makes sense to do so.
15222    */
15223
15224   switch (opc2) {
15225      case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
15226      {
15227         /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
15228         IRTemp absVal = newTemp(Ity_V128);
15229         if (host_endness == VexEndnessLE) {
15230            IRTemp hi64 = newTemp(Ity_I64);
15231            IRTemp lo64 = newTemp(Ity_I64);
15232            assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) );
15233            assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) );
15234            assign( absVal, binop( Iop_64HLtoV128,
15235                                   binop( Iop_And64, mkexpr(hi64),
15236                                          mkU64(VG_PPC_SIGN_MASK) ),
15237                                   mkexpr(lo64) ) );
15238         } else {
15239            assign(absVal, binop(Iop_ShrV128,
15240                                 binop(Iop_ShlV128, mkexpr(vB),
15241                                       mkU8(1)), mkU8(1)));
15242         }
15243         DIP("xsabsdp v%d,v%d\n", XT, XB);
15244         putVSReg(XT, mkexpr(absVal));
15245         break;
15246      }
15247      case 0x2C0: // xscpsgndp
15248      {
15249         /* Scalar copy sign double-precision */
15250         IRTemp vecA_signed = newTemp(Ity_I64);
15251         IRTemp vecB_unsigned = newTemp(Ity_I64);
15252         IRTemp vec_result = newTemp(Ity_V128);
15253         DIP("xscpsgndp v%d,v%d v%d\n", XT, XA, XB);
15254         assign( vecA_signed, binop( Iop_And64,
15255                                     unop( Iop_V128HIto64,
15256                                           mkexpr(vA)),
15257                                           mkU64(~VG_PPC_SIGN_MASK) ) );
15258         assign( vecB_unsigned, binop( Iop_And64,
15259                                       unop( Iop_V128HIto64,
15260                                             mkexpr(vB) ),
15261                                             mkU64(VG_PPC_SIGN_MASK) ) );
15262         assign( vec_result, binop( Iop_64HLtoV128,
15263                                    binop( Iop_Or64,
15264                                           mkexpr(vecA_signed),
15265                                           mkexpr(vecB_unsigned) ),
15266                                    mkU64(0x0ULL)));
15267         putVSReg(XT, mkexpr(vec_result));
15268         break;
15269      }
15270      case 0x2D2: // xsnabsdp
15271      {
15272         /* Scalar negative absolute value double-precision */
15273         IRTemp BHi_signed = newTemp(Ity_I64);
15274         DIP("xsnabsdp v%d,v%d\n", XT, XB);
15275         assign( BHi_signed, binop( Iop_Or64,
15276                                    unop( Iop_V128HIto64,
15277                                          mkexpr(vB) ),
15278                                          mkU64(~VG_PPC_SIGN_MASK) ) );
15279         putVSReg(XT, binop( Iop_64HLtoV128,
15280                             mkexpr(BHi_signed), mkU64(0x0ULL) ) );
15281         break;
15282      }
15283      case 0x2F2: // xsnegdp
15284      {
15285         /* Scalar negate double-precision */
15286         IRTemp BHi_signed = newTemp(Ity_I64);
15287         IRTemp BHi_unsigned = newTemp(Ity_I64);
15288         IRTemp BHi_negated = newTemp(Ity_I64);
15289         IRTemp BHi_negated_signbit = newTemp(Ity_I1);
15290         IRTemp vec_result = newTemp(Ity_V128);
15291         DIP("xsnabsdp v%d,v%d\n", XT, XB);
15292         assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) );
15293         assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed),
15294                                      mkU64(VG_PPC_SIGN_MASK) ) );
15295         assign( BHi_negated_signbit,
15296                 unop( Iop_Not1,
15297                       unop( Iop_32to1,
15298                             binop( Iop_Shr32,
15299                                    unop( Iop_64HIto32,
15300                                          binop( Iop_And64,
15301                                                 mkexpr(BHi_signed),
15302                                                 mkU64(~VG_PPC_SIGN_MASK) )
15303                                          ),
15304                                    mkU8(31) ) ) ) );
15305         assign( BHi_negated,
15306                 binop( Iop_Or64,
15307                        binop( Iop_32HLto64,
15308                               binop( Iop_Shl32,
15309                                      unop( Iop_1Uto32,
15310                                            mkexpr(BHi_negated_signbit) ),
15311                                      mkU8(31) ),
15312                               mkU32(0) ),
15313                        mkexpr(BHi_unsigned) ) );
15314         assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
15315                                    mkU64(0x0ULL)));
15316         putVSReg( XT, mkexpr(vec_result));
15317         break;
15318      }
15319      case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
15320      case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
15321      {
15322         IRTemp frA     = newTemp(Ity_I64);
15323         IRTemp frB     = newTemp(Ity_I64);
15324         Bool isMin = opc2 == 0x2A0 ? True : False;
15325         DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", XT, XA, XB);
15326
15327         assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
15328         assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
15329         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
15330
15331         break;
15332      }
15333      case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
15334      case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
15335      case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
15336      case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
15337      case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
15338      {
15339         IRTemp frB_I64 = newTemp(Ity_I64);
15340         IRExpr * frD_fp_round = NULL;
15341
15342         assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
15343         frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
15344
15345         DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
15346         putVSReg( XT,
15347                   binop( Iop_64HLtoV128,
15348                          unop( Iop_ReinterpF64asI64, frD_fp_round),
15349                          mkU64( 0 ) ) );
15350         break;
15351      }
15352      case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
15353      case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
15354                   * single-Precision)
15355                   */
15356      {
15357         IRTemp frB = newTemp(Ity_F64);
15358         IRTemp sqrt = newTemp(Ity_F64);
15359         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
15360         IRExpr* rm  = get_IR_roundingmode();
15361         Bool redp = opc2 == 0x034;
15362         DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", XT,
15363             XB);
15364
15365         assign( frB,
15366                 unop( Iop_ReinterpI64asF64,
15367                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
15368
15369         if (!redp)
15370            assign( sqrt,
15371                    binop( Iop_SqrtF64,
15372                           rm,
15373                           mkexpr(frB) ) );
15374         putVSReg( XT,
15375                      binop( Iop_64HLtoV128,
15376                             unop( Iop_ReinterpF64asI64,
15377                                   binop( Iop_RoundF64toF32, rm,
15378                                          triop( Iop_DivF64,
15379                                                 rm,
15380                                                 ieee_one,
15381                                                 redp ? mkexpr( frB ) :
15382                                                        mkexpr( sqrt ) ) ) ),
15383                             mkU64( 0 ) ) );
15384         break;
15385      }
15386
15387      case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
15388      case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
15389
15390      {
15391         IRTemp frB = newTemp(Ity_F64);
15392         IRTemp sqrt = newTemp(Ity_F64);
15393         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
15394         IRExpr* rm  = get_IR_roundingmode();
15395         Bool redp = opc2 == 0x0B4;
15396         DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", XT, XB);
15397         assign( frB,
15398                 unop( Iop_ReinterpI64asF64,
15399                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
15400
15401         if (!redp)
15402            assign( sqrt,
15403                    binop( Iop_SqrtF64,
15404                           rm,
15405                           mkexpr(frB) ) );
15406         putVSReg( XT,
15407                      binop( Iop_64HLtoV128,
15408                             unop( Iop_ReinterpF64asI64,
15409                                   triop( Iop_DivF64,
15410                                          rm,
15411                                          ieee_one,
15412                                          redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
15413                             mkU64( 0 ) ) );
15414         break;
15415      }
15416
15417      case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
15418      {
15419         IRTemp frB = newTemp(Ity_F64);
15420         IRExpr* rm  = get_IR_roundingmode();
15421         DIP("xsrsp v%d, v%d\n", XT, XB);
15422         assign( frB,
15423                 unop( Iop_ReinterpI64asF64,
15424                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
15425
15426         putVSReg( XT, binop( Iop_64HLtoV128,
15427                              unop( Iop_ReinterpF64asI64,
15428                                    binop( Iop_RoundF64toF32,
15429                                           rm,
15430                                           mkexpr( frB ) ) ),
15431                              mkU64( 0 ) ) );
15432         break;
15433      }
15434
15435      default:
15436         vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
15437         return False;
15438   }
15439   return True;
15440}
15441
15442/*
15443 * VSX Logical Instructions
15444 */
15445static Bool
15446dis_vx_logic ( UInt theInstr, UInt opc2 )
15447{
15448   /* XX3-Form */
15449   UChar opc1 = ifieldOPC( theInstr );
15450   UChar XT = ifieldRegXT ( theInstr );
15451   UChar XA = ifieldRegXA ( theInstr );
15452   UChar XB = ifieldRegXB ( theInstr );
15453   IRTemp vA = newTemp( Ity_V128 );
15454   IRTemp vB = newTemp( Ity_V128 );
15455
15456   if (opc1 != 0x3C) {
15457      vex_printf( "dis_vx_logic(ppc)(instr)\n" );
15458      return False;
15459   }
15460
15461   assign( vA, getVSReg( XA ) );
15462   assign( vB, getVSReg( XB ) );
15463
15464   switch (opc2) {
15465      case 0x268: // xxlxor
15466         DIP("xxlxor v%d,v%d,v%d\n", XT, XA, XB);
15467         putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
15468         break;
15469      case 0x248: // xxlor
15470         DIP("xxlor v%d,v%d,v%d\n", XT, XA, XB);
15471         putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
15472         break;
15473      case 0x288: // xxlnor
15474         DIP("xxlnor v%d,v%d,v%d\n", XT, XA, XB);
15475         putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
15476                                                 mkexpr( vB ) ) ) );
15477         break;
15478      case 0x208: // xxland
15479         DIP("xxland v%d,v%d,v%d\n", XT, XA, XB);
15480         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
15481         break;
15482      case 0x228: //xxlandc
15483         DIP("xxlandc v%d,v%d,v%d\n", XT, XA, XB);
15484         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
15485                                                               mkexpr( vB ) ) ) );
15486         break;
15487      case 0x2A8: // xxlorc (VSX Logical OR with complement)
15488         DIP("xxlorc v%d,v%d,v%d\n", XT, XA, XB);
15489         putVSReg( XT, binop( Iop_OrV128,
15490                              mkexpr( vA ),
15491                              unop( Iop_NotV128, mkexpr( vB ) ) ) );
15492         break;
15493      case 0x2C8: // xxlnand (VSX Logical NAND)
15494         DIP("xxlnand v%d,v%d,v%d\n", XT, XA, XB);
15495         putVSReg( XT, unop( Iop_NotV128,
15496                             binop( Iop_AndV128, mkexpr( vA ),
15497                                    mkexpr( vB ) ) ) );
15498         break;
15499      case 0x2E8: // xxleqv (VSX Logical Equivalence)
15500         DIP("xxleqv v%d,v%d,v%d\n", XT, XA, XB);
15501         putVSReg( XT, unop( Iop_NotV128,
15502                             binop( Iop_XorV128,
15503                             mkexpr( vA ), mkexpr( vB ) ) ) );
15504         break;
15505      default:
15506         vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
15507         return False;
15508   }
15509   return True;
15510}
15511
15512/*
15513 * VSX Load Instructions
15514 * NOTE: VSX supports word-aligned storage access.
15515 */
15516static Bool
15517dis_vx_load ( UInt theInstr )
15518{
15519   /* XX1-Form */
15520   UChar opc1 = ifieldOPC( theInstr );
15521   UChar XT = ifieldRegXT ( theInstr );
15522   UChar rA_addr = ifieldRegA( theInstr );
15523   UChar rB_addr = ifieldRegB( theInstr );
15524   UInt opc2 = ifieldOPClo10( theInstr );
15525
15526   IRType ty = mode64 ? Ity_I64 : Ity_I32;
15527   IRTemp EA = newTemp( ty );
15528
15529   if (opc1 != 0x1F) {
15530      vex_printf( "dis_vx_load(ppc)(instr)\n" );
15531      return False;
15532   }
15533
15534   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
15535
15536   switch (opc2) {
15537   case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
15538   {
15539      IRExpr * exp;
15540      DIP("lxsiwzx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15541
15542      if (host_endness == VexEndnessLE)
15543         exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
15544      else
15545         exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
15546
15547      putVSReg( XT, binop( Iop_64HLtoV128,
15548                           unop( Iop_32Uto64, exp),
15549                           mkU64(0) ) );
15550      break;
15551   }
15552   case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
15553   {
15554      IRExpr * exp;
15555      DIP("lxsiwax %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15556
15557      if (host_endness == VexEndnessLE)
15558         exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
15559      else
15560         exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
15561
15562      putVSReg( XT, binop( Iop_64HLtoV128,
15563                           unop( Iop_32Sto64, exp),
15564                           mkU64(0) ) );
15565      break;
15566   }
15567   case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
15568   {
15569      IRExpr * exp;
15570      DIP("lxsspx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15571      /* Take 32-bit floating point value in the upper half of the fetched
15572       * 64-bit value, convert to 64-bit floating point value and load into
15573       * top word of V128.
15574       */
15575      exp = unop( Iop_ReinterpF64asI64,
15576                  unop( Iop_F32toF64,
15577                        unop( Iop_ReinterpI32asF32,
15578                              load( Ity_I32, mkexpr( EA ) ) ) ) );
15579
15580      putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
15581      break;
15582   }
15583   case 0x24C: // lxsdx
15584   {
15585      IRExpr * exp;
15586      DIP("lxsdx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15587      exp = load( Ity_I64, mkexpr( EA ) );
15588      // We need to pass an expression of type Ity_V128 with putVSReg, but the load
15589      // we just performed is only a DW.  But since the contents of VSR[XT] element 1
15590      // are undefined after this operation, we can just do a splat op.
15591      putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
15592      break;
15593   }
15594   case 0x34C: // lxvd2x
15595   {
15596      IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
15597      IRExpr * high, *low;
15598      ULong ea_off = 8;
15599      IRExpr* high_addr;
15600      DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15601      high = load( Ity_I64, mkexpr( EA ) );
15602      high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
15603            : mkU32( ea_off ) );
15604      low = load( Ity_I64, high_addr );
15605      putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
15606      break;
15607   }
15608   case 0x14C: // lxvdsx
15609   {
15610      IRTemp data = newTemp(Ity_I64);
15611      DIP("lxvdsx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15612      assign( data, load( Ity_I64, mkexpr( EA ) ) );
15613      putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
15614      break;
15615   }
15616   case 0x30C:
15617   {
15618      IRExpr *t0;
15619
15620      DIP("lxvw4x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15621
15622      /* The load will result in the data being in BE order. */
15623      if (host_endness == VexEndnessLE) {
15624         IRExpr *t0_BE;
15625         IRTemp perm_LE = newTemp(Ity_V128);
15626
15627         t0_BE = load( Ity_V128, mkexpr( EA ) );
15628
15629         /*  Permute the data to LE format */
15630         assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL),
15631                                 mkU64(0x0405060700010203ULL)));
15632
15633         t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) );
15634      } else {
15635         t0 = load( Ity_V128, mkexpr( EA ) );
15636      }
15637
15638      putVSReg( XT, t0 );
15639      break;
15640   }
15641   default:
15642      vex_printf( "dis_vx_load(ppc)(opc2)\n" );
15643      return False;
15644   }
15645   return True;
15646}
15647
15648/*
15649 * VSX Store Instructions
15650 * NOTE: VSX supports word-aligned storage access.
15651 */
15652static Bool
15653dis_vx_store ( UInt theInstr )
15654{
15655   /* XX1-Form */
15656   UChar opc1 = ifieldOPC( theInstr );
15657   UChar XS = ifieldRegXS( theInstr );
15658   UChar rA_addr = ifieldRegA( theInstr );
15659   UChar rB_addr = ifieldRegB( theInstr );
15660   IRTemp vS = newTemp( Ity_V128 );
15661   UInt opc2 = ifieldOPClo10( theInstr );
15662
15663   IRType ty = mode64 ? Ity_I64 : Ity_I32;
15664   IRTemp EA = newTemp( ty );
15665
15666   if (opc1 != 0x1F) {
15667      vex_printf( "dis_vx_store(ppc)(instr)\n" );
15668      return False;
15669   }
15670
15671   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
15672   assign( vS, getVSReg( XS ) );
15673
15674   switch (opc2) {
15675   case 0x08C:
15676   {
15677     /* Need the next to the most significant 32-bit word from
15678      * the 128-bit vector.
15679      */
15680      IRExpr * high64, * low32;
15681      DIP("stxsiwx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15682      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15683      low32  = unop( Iop_64to32, high64 );
15684      store( mkexpr( EA ), low32 );
15685      break;
15686   }
15687   case 0x28C:
15688   {
15689      IRTemp high64 = newTemp(Ity_F64);
15690      IRTemp val32  = newTemp(Ity_I32);
15691      DIP("stxsspx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15692      assign(high64, unop( Iop_ReinterpI64asF64,
15693                           unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
15694      assign(val32, unop( Iop_ReinterpF32asI32,
15695                          unop( Iop_TruncF64asF32,
15696                                mkexpr(high64) ) ) );
15697      store( mkexpr( EA ), mkexpr( val32 ) );
15698      break;
15699   }
15700   case 0x2CC:
15701   {
15702      IRExpr * high64;
15703      DIP("stxsdx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15704      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15705      store( mkexpr( EA ), high64 );
15706      break;
15707   }
15708   case 0x3CC:
15709   {
15710      IRExpr * high64, *low64;
15711      DIP("stxvd2x %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15712      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15713      low64 = unop( Iop_V128to64, mkexpr( vS ) );
15714      store( mkexpr( EA ), high64 );
15715      store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15716                    ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 );
15717      break;
15718   }
15719   case 0x38C:
15720   {
15721      UInt ea_off = 0;
15722      IRExpr* irx_addr;
15723      IRTemp hi64 = newTemp( Ity_I64 );
15724      IRTemp lo64 = newTemp( Ity_I64 );
15725
15726      DIP("stxvw4x %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15727
15728      // This instruction supports word-aligned stores, so EA may not be
15729      // quad-word aligned.  Therefore, do 4 individual word-size stores.
15730      assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
15731      assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
15732      store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
15733      ea_off += 4;
15734      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15735                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15736      store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
15737      ea_off += 4;
15738      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15739                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15740      store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
15741      ea_off += 4;
15742      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15743                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15744      store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
15745
15746      break;
15747   }
15748   default:
15749      vex_printf( "dis_vx_store(ppc)(opc2)\n" );
15750      return False;
15751   }
15752   return True;
15753}
15754
15755/*
15756 * VSX permute and other miscealleous instructions
15757 */
15758static Bool
15759dis_vx_permute_misc( UInt theInstr, UInt opc2 )
15760{
15761   /* XX3-Form */
15762   UChar opc1 = ifieldOPC( theInstr );
15763   UChar XT = ifieldRegXT ( theInstr );
15764   UChar XA = ifieldRegXA ( theInstr );
15765   UChar XB = ifieldRegXB ( theInstr );
15766   IRTemp vT = newTemp( Ity_V128 );
15767   IRTemp vA = newTemp( Ity_V128 );
15768   IRTemp vB = newTemp( Ity_V128 );
15769
15770   if (opc1 != 0x3C) {
15771      vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
15772      return False;
15773   }
15774
15775   assign( vA, getVSReg( XA ) );
15776   assign( vB, getVSReg( XB ) );
15777
15778   switch (opc2) {
15779      case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
15780      {
15781         UChar SHW = ifieldSHW ( theInstr );
15782         IRTemp result = newTemp(Ity_V128);
15783         if ( SHW != 0 ) {
15784             IRTemp hi = newTemp(Ity_V128);
15785             IRTemp lo = newTemp(Ity_V128);
15786             assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
15787             assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
15788             assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
15789         } else
15790             assign ( result, mkexpr(vA) );
15791         DIP("xxsldwi v%d,v%d,v%d,%d\n", XT, XA, XB, SHW);
15792         putVSReg( XT, mkexpr(result) );
15793         break;
15794      }
15795      case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
15796      {
15797         UChar DM = ifieldDM ( theInstr );
15798         IRTemp hi = newTemp(Ity_I64);
15799         IRTemp lo = newTemp(Ity_I64);
15800
15801         if (DM & 0x2)
15802           assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
15803         else
15804           assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
15805
15806         if (DM & 0x1)
15807           assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
15808         else
15809           assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
15810
15811         assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
15812
15813         DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT, XA, XB, DM);
15814         putVSReg( XT, mkexpr( vT ) );
15815         break;
15816      }
15817      case 0x48: // xxmrghw (VSX Merge High Word)
15818      case 0xc8: // xxmrglw (VSX Merge Low Word)
15819      {
15820         const HChar type = (opc2 == 0x48) ? 'h' : 'l';
15821         IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
15822         IRTemp a64 = newTemp(Ity_I64);
15823         IRTemp ahi32 = newTemp(Ity_I32);
15824         IRTemp alo32 = newTemp(Ity_I32);
15825         IRTemp b64 = newTemp(Ity_I64);
15826         IRTemp bhi32 = newTemp(Ity_I32);
15827         IRTemp blo32 = newTemp(Ity_I32);
15828
15829         assign( a64, unop(word_op, mkexpr(vA)) );
15830         assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
15831         assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
15832
15833         assign( b64, unop(word_op, mkexpr(vB)) );
15834         assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
15835         assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
15836
15837         assign( vT, binop(Iop_64HLtoV128,
15838                           binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
15839                           binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
15840
15841         DIP("xxmrg%cw v%d,v%d,v%d\n", type, XT, XA, XB);
15842         putVSReg( XT, mkexpr( vT ) );
15843         break;
15844      }
15845      case 0x018: // xxsel (VSX Select)
15846      {
15847         UChar XC = ifieldRegXC(theInstr);
15848         IRTemp vC = newTemp( Ity_V128 );
15849         assign( vC, getVSReg( XC ) );
15850         DIP("xxsel v%d,v%d,v%d,v%d\n", XT, XA, XB, XC);
15851         /* vD = (vA & ~vC) | (vB & vC) */
15852         putVSReg( XT, binop(Iop_OrV128,
15853            binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
15854            binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
15855         break;
15856      }
15857      case 0x148: // xxspltw (VSX Splat Word)
15858      {
15859         UChar UIM   = ifieldRegA(theInstr) & 3;
15860         UChar sh_uim = (3 - (UIM)) * 32;
15861         DIP("xxspltw v%d,v%d,%d\n", XT, XB, UIM);
15862         putVSReg( XT,
15863                   unop( Iop_Dup32x4,
15864                         unop( Iop_V128to32,
15865                               binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
15866         break;
15867      }
15868
15869      default:
15870         vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
15871         return False;
15872   }
15873   return True;
15874}
15875
15876/*
15877  AltiVec Load Instructions
15878*/
15879static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr )
15880{
15881   /* X-Form */
15882   UChar opc1     = ifieldOPC(theInstr);
15883   UChar vD_addr  = ifieldRegDS(theInstr);
15884   UChar rA_addr  = ifieldRegA(theInstr);
15885   UChar rB_addr  = ifieldRegB(theInstr);
15886   UInt  opc2     = ifieldOPClo10(theInstr);
15887   UChar b0       = ifieldBIT0(theInstr);
15888
15889   IRType ty         = mode64 ? Ity_I64 : Ity_I32;
15890   IRTemp EA         = newTemp(ty);
15891   IRTemp EA_align16 = newTemp(ty);
15892
15893   if (opc1 != 0x1F || b0 != 0) {
15894      vex_printf("dis_av_load(ppc)(instr)\n");
15895      return False;
15896   }
15897
15898   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
15899   assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
15900
15901   switch (opc2) {
15902
15903   case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
15904      IRDirty* d;
15905      UInt vD_off = vectorGuestRegOffset(vD_addr);
15906      IRExpr** args_be = mkIRExprVec_5(
15907                         IRExpr_BBPTR(),
15908                         mkU32(vD_off),
15909                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15910                                          mkU32(0xF)),
15911                         mkU32(0)/*left*/,
15912                         mkU32(1)/*Big Endian*/);
15913      IRExpr** args_le = mkIRExprVec_5(
15914                         IRExpr_BBPTR(),
15915                         mkU32(vD_off),
15916                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15917                                          mkU32(0xF)),
15918                         mkU32(0)/*left*/,
15919                         mkU32(0)/*Little Endian*/);
15920      if (!mode64) {
15921         d = unsafeIRDirty_0_N (
15922                        0/*regparms*/,
15923                        "ppc32g_dirtyhelper_LVS",
15924                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
15925                        args_be );
15926      } else {
15927         if (host_endness == VexEndnessBE)
15928            d = unsafeIRDirty_0_N (
15929                           0/*regparms*/,
15930                           "ppc64g_dirtyhelper_LVS",
15931                           fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
15932                           args_be );
15933         else
15934            d = unsafeIRDirty_0_N (
15935                           0/*regparms*/,
15936                           "ppc64g_dirtyhelper_LVS",
15937                           &ppc64g_dirtyhelper_LVS,
15938                           args_le );
15939      }
15940      DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15941      /* declare guest state effects */
15942      d->nFxState = 1;
15943      vex_bzero(&d->fxState, sizeof(d->fxState));
15944      d->fxState[0].fx     = Ifx_Write;
15945      d->fxState[0].offset = vD_off;
15946      d->fxState[0].size   = sizeof(U128);
15947
15948      /* execute the dirty call, side-effecting guest state */
15949      stmt( IRStmt_Dirty(d) );
15950      break;
15951   }
15952   case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
15953      IRDirty* d;
15954      UInt vD_off = vectorGuestRegOffset(vD_addr);
15955      IRExpr** args_be = mkIRExprVec_5(
15956                             IRExpr_BBPTR(),
15957                             mkU32(vD_off),
15958                             binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15959                                              mkU32(0xF)),
15960                             mkU32(1)/*right*/,
15961                             mkU32(1)/*Big Endian*/);
15962      IRExpr** args_le = mkIRExprVec_5(
15963                             IRExpr_BBPTR(),
15964                             mkU32(vD_off),
15965                             binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15966                                              mkU32(0xF)),
15967                             mkU32(1)/*right*/,
15968                             mkU32(0)/*Little Endian*/);
15969
15970      if (!mode64) {
15971         d = unsafeIRDirty_0_N (
15972                        0/*regparms*/,
15973                        "ppc32g_dirtyhelper_LVS",
15974                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
15975                        args_be );
15976      } else {
15977         if (host_endness == VexEndnessBE)
15978            d = unsafeIRDirty_0_N (
15979                           0/*regparms*/,
15980                           "ppc64g_dirtyhelper_LVS",
15981                           fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
15982                           args_be );
15983         else
15984            d = unsafeIRDirty_0_N (
15985                           0/*regparms*/,
15986                           "ppc64g_dirtyhelper_LVS",
15987                           &ppc64g_dirtyhelper_LVS,
15988                           args_le );
15989      }
15990      DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15991      /* declare guest state effects */
15992      d->nFxState = 1;
15993      vex_bzero(&d->fxState, sizeof(d->fxState));
15994      d->fxState[0].fx     = Ifx_Write;
15995      d->fxState[0].offset = vD_off;
15996      d->fxState[0].size   = sizeof(U128);
15997
15998      /* execute the dirty call, side-effecting guest state */
15999      stmt( IRStmt_Dirty(d) );
16000      break;
16001   }
16002   case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
16003      DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16004      /* loads addressed byte into vector[EA[0:3]
16005         since all other destination bytes are undefined,
16006         can simply load entire vector from 16-aligned EA */
16007      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16008      break;
16009
16010   case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
16011      DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16012      /* see note for lvebx */
16013      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16014      break;
16015
16016   case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
16017      DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16018      /* see note for lvebx */
16019      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16020      break;
16021
16022   case 0x067: // lvx (Load Vector Indexed, AV p127)
16023      DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16024      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16025      break;
16026
16027   case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
16028      DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16029      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16030      break;
16031
16032   default:
16033      vex_printf("dis_av_load(ppc)(opc2)\n");
16034      return False;
16035   }
16036   return True;
16037}
16038
16039/*
16040  AltiVec Store Instructions
16041*/
16042static Bool dis_av_store ( UInt theInstr )
16043{
16044   /* X-Form */
16045   UChar opc1     = ifieldOPC(theInstr);
16046   UChar vS_addr  = ifieldRegDS(theInstr);
16047   UChar rA_addr  = ifieldRegA(theInstr);
16048   UChar rB_addr  = ifieldRegB(theInstr);
16049   UInt  opc2     = ifieldOPClo10(theInstr);
16050   UChar b0       = ifieldBIT0(theInstr);
16051
16052   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
16053   IRTemp EA           = newTemp(ty);
16054   IRTemp addr_aligned = newTemp(ty);
16055   IRTemp vS           = newTemp(Ity_V128);
16056   IRTemp eb           = newTemp(Ity_I8);
16057   IRTemp idx          = newTemp(Ity_I8);
16058
16059   if (opc1 != 0x1F || b0 != 0) {
16060      vex_printf("dis_av_store(ppc)(instr)\n");
16061      return False;
16062   }
16063
16064   assign( vS, getVReg(vS_addr));
16065   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
16066
16067   switch (opc2) {
16068   case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
16069      DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16070      assign( eb, binop(Iop_And8, mkU8(0xF),
16071                        unop(Iop_32to8,
16072                             mkNarrowTo32(ty, mkexpr(EA)) )) );
16073     if (host_endness == VexEndnessLE) {
16074         assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
16075      } else {
16076         assign( idx, binop(Iop_Shl8,
16077                            binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
16078                            mkU8(3)) );
16079      }
16080      store( mkexpr(EA),
16081             unop( Iop_32to8, unop(Iop_V128to32,
16082                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
16083      break;
16084   }
16085   case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
16086      DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16087      assign( addr_aligned, addr_align(mkexpr(EA), 2) );
16088      assign( eb, binop(Iop_And8, mkU8(0xF),
16089                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
16090      if (host_endness == VexEndnessLE) {
16091          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
16092      } else {
16093         assign( idx, binop(Iop_Shl8,
16094                            binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
16095                            mkU8(3)) );
16096      }
16097      store( mkexpr(addr_aligned),
16098             unop( Iop_32to16, unop(Iop_V128to32,
16099                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
16100      break;
16101   }
16102   case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
16103      DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16104      assign( addr_aligned, addr_align(mkexpr(EA), 4) );
16105      assign( eb, binop(Iop_And8, mkU8(0xF),
16106                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
16107      if (host_endness == VexEndnessLE) {
16108         assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
16109      } else {
16110         assign( idx, binop(Iop_Shl8,
16111                            binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
16112                            mkU8(3)) );
16113      }
16114      store( mkexpr( addr_aligned),
16115             unop( Iop_V128to32,
16116                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
16117      break;
16118   }
16119
16120   case 0x0E7: // stvx (Store Vector Indexed, AV p134)
16121      DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16122      store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
16123      break;
16124
16125   case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
16126      DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16127      store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
16128      break;
16129
16130   default:
16131      vex_printf("dis_av_store(ppc)(opc2)\n");
16132      return False;
16133   }
16134   return True;
16135}
16136
16137/*
16138  AltiVec Arithmetic Instructions
16139*/
16140static Bool dis_av_arith ( UInt theInstr )
16141{
16142   /* VX-Form */
16143   UChar opc1     = ifieldOPC(theInstr);
16144   UChar vD_addr  = ifieldRegDS(theInstr);
16145   UChar vA_addr  = ifieldRegA(theInstr);
16146   UChar vB_addr  = ifieldRegB(theInstr);
16147   UInt  opc2     = IFIELD( theInstr, 0, 11 );
16148
16149   IRTemp vA = newTemp(Ity_V128);
16150   IRTemp vB = newTemp(Ity_V128);
16151   IRTemp z3 = newTemp(Ity_I64);
16152   IRTemp z2 = newTemp(Ity_I64);
16153   IRTemp z1 = newTemp(Ity_I64);
16154   IRTemp z0 = newTemp(Ity_I64);
16155   IRTemp aEvn, aOdd;
16156   IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
16157   IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
16158   IRTemp b3, b2, b1, b0;
16159
16160   aEvn = aOdd = IRTemp_INVALID;
16161   a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
16162   a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
16163   b3 = b2 = b1 = b0 = IRTemp_INVALID;
16164
16165   assign( vA, getVReg(vA_addr));
16166   assign( vB, getVReg(vB_addr));
16167
16168   if (opc1 != 0x4) {
16169      vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
16170      return False;
16171   }
16172
16173   switch (opc2) {
16174   /* Add */
16175   case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
16176      DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16177      /* unsigned_ov(x+y) = (y >u not(x)) */
16178      putVReg( vD_addr, binop(Iop_ShrN32x4,
16179                              binop(Iop_CmpGT32Ux4, mkexpr(vB),
16180                                    unop(Iop_NotV128, mkexpr(vA))),
16181                              mkU8(31)) );
16182      break;
16183   }
16184   case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
16185      DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16186      putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
16187      break;
16188
16189   case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
16190      DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16191      putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
16192      break;
16193
16194   case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
16195      DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16196      putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
16197      break;
16198
16199   case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
16200      DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16201      putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
16202      break;
16203
16204   case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
16205      DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16206      putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
16207      // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
16208      break;
16209
16210   case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
16211      DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16212      putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
16213      // TODO: set VSCR[SAT]
16214      break;
16215
16216   case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
16217      DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16218      putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
16219      // TODO: set VSCR[SAT]
16220      break;
16221
16222   case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
16223      DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16224      putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
16225      // TODO: set VSCR[SAT]
16226      break;
16227
16228   case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
16229      DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16230      putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
16231      // TODO: set VSCR[SAT]
16232      break;
16233
16234   case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
16235      DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16236      putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
16237      // TODO: set VSCR[SAT]
16238      break;
16239
16240
16241   /* Subtract */
16242   case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
16243      DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16244      /* unsigned_ov(x-y) = (y >u x) */
16245      putVReg( vD_addr, binop(Iop_ShrN32x4,
16246                              unop(Iop_NotV128,
16247                                   binop(Iop_CmpGT32Ux4, mkexpr(vB),
16248                                         mkexpr(vA))),
16249                              mkU8(31)) );
16250      break;
16251   }
16252   case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
16253      DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16254      putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
16255      break;
16256
16257   case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
16258      DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16259      putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
16260      break;
16261
16262   case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
16263      DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16264      putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
16265      break;
16266
16267   case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
16268      DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16269      putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
16270      break;
16271
16272   case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
16273      DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16274      putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
16275      // TODO: set VSCR[SAT]
16276      break;
16277
16278   case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
16279      DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16280      putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
16281      // TODO: set VSCR[SAT]
16282      break;
16283
16284   case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
16285      DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16286      putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
16287      // TODO: set VSCR[SAT]
16288      break;
16289
16290   case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
16291      DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16292      putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
16293      // TODO: set VSCR[SAT]
16294      break;
16295
16296   case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
16297      DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16298      putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
16299      // TODO: set VSCR[SAT]
16300      break;
16301
16302   case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
16303      DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16304      putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
16305      // TODO: set VSCR[SAT]
16306      break;
16307
16308
16309   /* Maximum */
16310   case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
16311      DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16312      putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
16313      break;
16314
16315   case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
16316      DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16317      putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
16318      break;
16319
16320   case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
16321      DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16322      putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
16323      break;
16324
16325   case 0x0C2: // vmaxud (Maximum Unsigned Double word)
16326      DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16327      putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
16328      break;
16329
16330   case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
16331      DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16332      putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
16333      break;
16334
16335   case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
16336      DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16337      putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
16338      break;
16339
16340   case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
16341      DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16342      putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
16343      break;
16344
16345   case 0x1C2: // vmaxsd (Maximum Signed Double word)
16346      DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16347      putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
16348      break;
16349
16350   /* Minimum */
16351   case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
16352      DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16353      putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
16354      break;
16355
16356   case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
16357      DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16358      putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
16359      break;
16360
16361   case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
16362      DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16363      putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
16364      break;
16365
16366   case 0x2C2: // vminud (Minimum Unsigned Double Word)
16367      DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16368      putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
16369      break;
16370
16371   case 0x302: // vminsb (Minimum Signed Byte, AV p188)
16372      DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16373      putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
16374      break;
16375
16376   case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
16377      DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16378      putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
16379      break;
16380
16381   case 0x382: // vminsw (Minimum Signed Word, AV p190)
16382      DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16383      putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
16384      break;
16385
16386   case 0x3C2: // vminsd (Minimum Signed Double Word)
16387      DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16388      putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
16389      break;
16390
16391
16392   /* Average */
16393   case 0x402: // vavgub (Average Unsigned Byte, AV p152)
16394      DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16395      putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
16396      break;
16397
16398   case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
16399      DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16400      putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
16401      break;
16402
16403   case 0x482: // vavguw (Average Unsigned Word, AV p154)
16404      DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16405      putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
16406      break;
16407
16408   case 0x502: // vavgsb (Average Signed Byte, AV p149)
16409      DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16410      putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
16411      break;
16412
16413   case 0x542: // vavgsh (Average Signed Half Word, AV p150)
16414      DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16415      putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
16416      break;
16417
16418   case 0x582: // vavgsw (Average Signed Word, AV p151)
16419      DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16420      putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
16421      break;
16422
16423
16424   /* Multiply */
16425   case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
16426      DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16427      putVReg( vD_addr,
16428               binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
16429      break;
16430
16431   case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
16432      DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16433      putVReg( vD_addr,
16434               binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
16435      break;
16436
16437   case 0x088: // vmulouw (Multiply Odd Unsigned Word)
16438      DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16439      putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
16440      break;
16441
16442   case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
16443      DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16444      putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
16445      break;
16446
16447   case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
16448      DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16449      putVReg( vD_addr,
16450               binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
16451      break;
16452
16453   case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
16454      DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16455      putVReg( vD_addr,
16456               binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
16457      break;
16458
16459   case 0x188: // vmulosw (Multiply Odd Signed Word)
16460      DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16461      putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
16462      break;
16463
16464   case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
16465      DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16466      putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
16467      break;
16468
16469   case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
16470      DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16471      putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
16472      break;
16473
16474   case 0x288: // vmuleuw (Multiply Even Unsigned Word)
16475      DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16476      putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
16477      break;
16478
16479   case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
16480      DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16481      putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
16482      break;
16483
16484   case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
16485      DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16486      putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
16487      break;
16488
16489   case 0x388: // vmulesw (Multiply Even Signed Word)
16490      DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16491      putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
16492      break;
16493
16494   /* Sum Across Partial */
16495   case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
16496      IRTemp aEE, aEO, aOE, aOO;
16497      aEE = aEO = aOE = aOO = IRTemp_INVALID;
16498      DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16499
16500      /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
16501      expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
16502      expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
16503      expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
16504
16505      /* break V128 to 4xI32's, zero-extending to I64's */
16506      breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
16507      breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
16508      breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
16509      breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
16510      breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
16511
16512      /* add lanes */
16513      assign( z3, binop(Iop_Add64, mkexpr(b3),
16514                     binop(Iop_Add64,
16515                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
16516                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
16517      assign( z2, binop(Iop_Add64, mkexpr(b2),
16518                     binop(Iop_Add64,
16519                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
16520                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
16521      assign( z1, binop(Iop_Add64, mkexpr(b1),
16522                     binop(Iop_Add64,
16523                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
16524                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
16525      assign( z0, binop(Iop_Add64, mkexpr(b0),
16526                     binop(Iop_Add64,
16527                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16528                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16529
16530      /* saturate-narrow to 32bit, and combine to V128 */
16531      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
16532                                         mkexpr(z1), mkexpr(z0)) );
16533      break;
16534   }
16535   case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
16536      IRTemp aEE, aEO, aOE, aOO;
16537      aEE = aEO = aOE = aOO = IRTemp_INVALID;
16538      DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16539
16540      /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
16541      expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
16542      expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
16543      expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
16544
16545      /* break V128 to 4xI32's, sign-extending to I64's */
16546      breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
16547      breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
16548      breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
16549      breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
16550      breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
16551
16552      /* add lanes */
16553      assign( z3, binop(Iop_Add64, mkexpr(b3),
16554                     binop(Iop_Add64,
16555                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
16556                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
16557      assign( z2, binop(Iop_Add64, mkexpr(b2),
16558                     binop(Iop_Add64,
16559                        binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
16560                        binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
16561      assign( z1, binop(Iop_Add64, mkexpr(b1),
16562                     binop(Iop_Add64,
16563                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
16564                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
16565      assign( z0, binop(Iop_Add64, mkexpr(b0),
16566                     binop(Iop_Add64,
16567                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16568                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16569
16570      /* saturate-narrow to 32bit, and combine to V128 */
16571      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
16572                                         mkexpr(z1), mkexpr(z0)) );
16573      break;
16574   }
16575   case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
16576      DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16577
16578      /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
16579      expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
16580
16581      /* break V128 to 4xI32's, sign-extending to I64's */
16582      breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
16583      breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
16584      breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
16585
16586      /* add lanes */
16587      assign( z3, binop(Iop_Add64, mkexpr(b3),
16588                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
16589      assign( z2, binop(Iop_Add64, mkexpr(b2),
16590                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
16591      assign( z1, binop(Iop_Add64, mkexpr(b1),
16592                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
16593      assign( z0, binop(Iop_Add64, mkexpr(b0),
16594                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
16595
16596      /* saturate-narrow to 32bit, and combine to V128 */
16597      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
16598                                         mkexpr(z1), mkexpr(z0)) );
16599      break;
16600   }
16601   case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
16602      DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16603
16604      /* break V128 to 4xI32's, sign-extending to I64's */
16605      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
16606      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
16607
16608      /* add lanes */
16609      assign( z2, binop(Iop_Add64, mkexpr(b2),
16610                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
16611      assign( z0, binop(Iop_Add64, mkexpr(b0),
16612                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
16613
16614      /* saturate-narrow to 32bit, and combine to V128 */
16615      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
16616                                         mkU64(0), mkexpr(z0)) );
16617      break;
16618   }
16619   case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
16620      DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16621
16622      /* break V128 to 4xI32's, sign-extending to I64's */
16623      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
16624      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
16625
16626      /* add lanes */
16627      assign( z0, binop(Iop_Add64, mkexpr(b0),
16628                     binop(Iop_Add64,
16629                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16630                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16631
16632      /* saturate-narrow to 32bit, and combine to V128 */
16633      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
16634                                         mkU64(0), mkexpr(z0)) );
16635      break;
16636   }
16637   default:
16638      vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
16639      return False;
16640   }
16641   return True;
16642}
16643
16644/*
16645  AltiVec Logic Instructions
16646*/
16647static Bool dis_av_logic ( UInt theInstr )
16648{
16649   /* VX-Form */
16650   UChar opc1    = ifieldOPC(theInstr);
16651   UChar vD_addr = ifieldRegDS(theInstr);
16652   UChar vA_addr = ifieldRegA(theInstr);
16653   UChar vB_addr = ifieldRegB(theInstr);
16654   UInt  opc2    = IFIELD( theInstr, 0, 11 );
16655
16656   IRTemp vA = newTemp(Ity_V128);
16657   IRTemp vB = newTemp(Ity_V128);
16658   assign( vA, getVReg(vA_addr));
16659   assign( vB, getVReg(vB_addr));
16660
16661   if (opc1 != 0x4) {
16662      vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
16663      return False;
16664   }
16665
16666   switch (opc2) {
16667   case 0x404: // vand (And, AV p147)
16668      DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16669      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
16670      break;
16671
16672   case 0x444: // vandc (And, AV p148)
16673      DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16674      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
16675                              unop(Iop_NotV128, mkexpr(vB))) );
16676      break;
16677
16678   case 0x484: // vor (Or, AV p217)
16679      DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16680      putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
16681      break;
16682
16683   case 0x4C4: // vxor (Xor, AV p282)
16684      DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16685      putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
16686      break;
16687
16688   case 0x504: // vnor (Nor, AV p216)
16689      DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16690      putVReg( vD_addr,
16691         unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
16692      break;
16693
16694   case 0x544: // vorc (vA Or'd with complement of vb)
16695      DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16696      putVReg( vD_addr, binop( Iop_OrV128,
16697                               mkexpr( vA ),
16698                               unop( Iop_NotV128, mkexpr( vB ) ) ) );
16699      break;
16700
16701   case 0x584: // vnand (Nand)
16702      DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16703      putVReg( vD_addr, unop( Iop_NotV128,
16704                              binop(Iop_AndV128, mkexpr( vA ),
16705                              mkexpr( vB ) ) ) );
16706      break;
16707
16708   case 0x684: // veqv (complemented XOr)
16709      DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16710      putVReg( vD_addr, unop( Iop_NotV128,
16711                              binop( Iop_XorV128, mkexpr( vA ),
16712                              mkexpr( vB ) ) ) );
16713      break;
16714
16715   default:
16716      vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
16717      return False;
16718   }
16719   return True;
16720}
16721
16722/*
16723  AltiVec Compare Instructions
16724*/
16725static Bool dis_av_cmp ( UInt theInstr )
16726{
16727   /* VXR-Form */
16728   UChar opc1     = ifieldOPC(theInstr);
16729   UChar vD_addr  = ifieldRegDS(theInstr);
16730   UChar vA_addr  = ifieldRegA(theInstr);
16731   UChar vB_addr  = ifieldRegB(theInstr);
16732   UChar flag_rC  = ifieldBIT10(theInstr);
16733   UInt  opc2     = IFIELD( theInstr, 0, 10 );
16734
16735   IRTemp vA = newTemp(Ity_V128);
16736   IRTemp vB = newTemp(Ity_V128);
16737   IRTemp vD = newTemp(Ity_V128);
16738   assign( vA, getVReg(vA_addr));
16739   assign( vB, getVReg(vB_addr));
16740
16741   if (opc1 != 0x4) {
16742      vex_printf("dis_av_cmp(ppc)(instr)\n");
16743      return False;
16744   }
16745
16746   switch (opc2) {
16747   case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
16748      DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16749                                      vD_addr, vA_addr, vB_addr);
16750      assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
16751      break;
16752
16753   case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
16754      DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16755                                      vD_addr, vA_addr, vB_addr);
16756      assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
16757      break;
16758
16759   case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
16760      DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16761                                      vD_addr, vA_addr, vB_addr);
16762      assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
16763      break;
16764
16765   case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
16766      DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16767                                      vD_addr, vA_addr, vB_addr);
16768      assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
16769      break;
16770
16771   case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
16772      DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16773                                      vD_addr, vA_addr, vB_addr);
16774      assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
16775      break;
16776
16777   case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
16778      DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16779                                      vD_addr, vA_addr, vB_addr);
16780      assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
16781      break;
16782
16783   case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
16784      DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16785                                       vD_addr, vA_addr, vB_addr);
16786      assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
16787      break;
16788
16789   case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
16790      DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16791                                      vD_addr, vA_addr, vB_addr);
16792      assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
16793      break;
16794
16795   case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
16796      DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16797                                       vD_addr, vA_addr, vB_addr);
16798      assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
16799      break;
16800
16801   case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
16802      DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16803                                      vD_addr, vA_addr, vB_addr);
16804      assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
16805      break;
16806
16807   case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
16808      DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16809                                      vD_addr, vA_addr, vB_addr);
16810      assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
16811      break;
16812
16813   case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
16814      DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16815                                      vD_addr, vA_addr, vB_addr);
16816      assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
16817      break;
16818
16819   default:
16820      vex_printf("dis_av_cmp(ppc)(opc2)\n");
16821      return False;
16822   }
16823
16824   putVReg( vD_addr, mkexpr(vD) );
16825
16826   if (flag_rC) {
16827      set_AV_CR6( mkexpr(vD), True );
16828   }
16829   return True;
16830}
16831
16832/*
16833  AltiVec Multiply-Sum Instructions
16834*/
16835static Bool dis_av_multarith ( UInt theInstr )
16836{
16837   /* VA-Form */
16838   UChar opc1     = ifieldOPC(theInstr);
16839   UChar vD_addr  = ifieldRegDS(theInstr);
16840   UChar vA_addr  = ifieldRegA(theInstr);
16841   UChar vB_addr  = ifieldRegB(theInstr);
16842   UChar vC_addr  = ifieldRegC(theInstr);
16843   UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
16844
16845   IRTemp vA    = newTemp(Ity_V128);
16846   IRTemp vB    = newTemp(Ity_V128);
16847   IRTemp vC    = newTemp(Ity_V128);
16848   IRTemp zeros = newTemp(Ity_V128);
16849   IRTemp aLo   = newTemp(Ity_V128);
16850   IRTemp bLo   = newTemp(Ity_V128);
16851   IRTemp cLo   = newTemp(Ity_V128);
16852   IRTemp zLo   = newTemp(Ity_V128);
16853   IRTemp aHi   = newTemp(Ity_V128);
16854   IRTemp bHi   = newTemp(Ity_V128);
16855   IRTemp cHi   = newTemp(Ity_V128);
16856   IRTemp zHi   = newTemp(Ity_V128);
16857   IRTemp abEvn = newTemp(Ity_V128);
16858   IRTemp abOdd = newTemp(Ity_V128);
16859   IRTemp z3    = newTemp(Ity_I64);
16860   IRTemp z2    = newTemp(Ity_I64);
16861   IRTemp z1    = newTemp(Ity_I64);
16862   IRTemp z0    = newTemp(Ity_I64);
16863   IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
16864   IRTemp c3, c2, c1, c0;
16865
16866   ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
16867   c3 = c2 = c1 = c0 = IRTemp_INVALID;
16868
16869   assign( vA, getVReg(vA_addr));
16870   assign( vB, getVReg(vB_addr));
16871   assign( vC, getVReg(vC_addr));
16872   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
16873
16874   if (opc1 != 0x4) {
16875      vex_printf("dis_av_multarith(ppc)(instr)\n");
16876      return False;
16877   }
16878
16879   switch (opc2) {
16880   /* Multiply-Add */
16881   case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
16882      IRTemp cSigns = newTemp(Ity_V128);
16883      DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
16884          vD_addr, vA_addr, vB_addr, vC_addr);
16885      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
16886      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16887      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16888      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
16889      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16890      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16891      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
16892
16893      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
16894                         binop(Iop_SarN32x4,
16895                               binop(Iop_MullEven16Sx8,
16896                                     mkexpr(aLo), mkexpr(bLo)),
16897                               mkU8(15))) );
16898
16899      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
16900                         binop(Iop_SarN32x4,
16901                               binop(Iop_MullEven16Sx8,
16902                                     mkexpr(aHi), mkexpr(bHi)),
16903                               mkU8(15))) );
16904
16905      putVReg( vD_addr,
16906               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
16907      break;
16908   }
16909   case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
16910      IRTemp zKonst = newTemp(Ity_V128);
16911      IRTemp cSigns = newTemp(Ity_V128);
16912      DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
16913          vD_addr, vA_addr, vB_addr, vC_addr);
16914      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
16915      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16916      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16917      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
16918      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16919      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16920      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
16921
16922      /* shifting our const avoids store/load version of Dup */
16923      assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
16924                            mkU8(14)) );
16925
16926      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
16927                         binop(Iop_SarN32x4,
16928                               binop(Iop_Add32x4, mkexpr(zKonst),
16929                                     binop(Iop_MullEven16Sx8,
16930                                           mkexpr(aLo), mkexpr(bLo))),
16931                               mkU8(15))) );
16932
16933      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
16934                         binop(Iop_SarN32x4,
16935                               binop(Iop_Add32x4, mkexpr(zKonst),
16936                                     binop(Iop_MullEven16Sx8,
16937                                           mkexpr(aHi), mkexpr(bHi))),
16938                               mkU8(15))) );
16939
16940      putVReg( vD_addr,
16941               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
16942      break;
16943   }
16944   case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
16945      DIP("vmladduhm v%d,v%d,v%d,v%d\n",
16946          vD_addr, vA_addr, vB_addr, vC_addr);
16947      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16948      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16949      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
16950      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16951      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16952      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
16953      assign(zLo, binop(Iop_Add32x4,
16954                     binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
16955                     mkexpr(cLo)) );
16956      assign(zHi, binop(Iop_Add32x4,
16957                     binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
16958                     mkexpr(cHi)));
16959      putVReg( vD_addr,
16960               binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
16961      break;
16962   }
16963
16964
16965   /* Multiply-Sum */
16966   case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
16967      IRTemp abEE, abEO, abOE, abOO;
16968      abEE = abEO = abOE = abOO = IRTemp_INVALID;
16969      DIP("vmsumubm v%d,v%d,v%d,v%d\n",
16970          vD_addr, vA_addr, vB_addr, vC_addr);
16971
16972      /* multiply vA,vB (unsigned, widening) */
16973      assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
16974      assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
16975
16976      /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
16977      expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
16978      expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
16979
16980      putVReg( vD_addr,
16981         binop(Iop_Add32x4, mkexpr(vC),
16982               binop(Iop_Add32x4,
16983                     binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
16984                     binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
16985      break;
16986   }
16987   case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
16988      IRTemp aEvn, aOdd, bEvn, bOdd;
16989      IRTemp abEE = newTemp(Ity_V128);
16990      IRTemp abEO = newTemp(Ity_V128);
16991      IRTemp abOE = newTemp(Ity_V128);
16992      IRTemp abOO = newTemp(Ity_V128);
16993      aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
16994      DIP("vmsummbm v%d,v%d,v%d,v%d\n",
16995          vD_addr, vA_addr, vB_addr, vC_addr);
16996
16997      /* sign-extend vA, zero-extend vB, for mixed-sign multiply
16998         (separating out adjacent lanes to different vectors) */
16999      expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
17000      expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
17001
17002      /* multiply vA, vB, again separating adjacent lanes */
17003      assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
17004      assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
17005      assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
17006      assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
17007
17008      /* add results together, + vC */
17009      putVReg( vD_addr,
17010         binop(Iop_QAdd32Sx4, mkexpr(vC),
17011               binop(Iop_QAdd32Sx4,
17012                     binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
17013                     binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
17014      break;
17015   }
17016   case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
17017      DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
17018          vD_addr, vA_addr, vB_addr, vC_addr);
17019      assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
17020      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
17021      putVReg( vD_addr,
17022         binop(Iop_Add32x4, mkexpr(vC),
17023               binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
17024      break;
17025   }
17026   case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
17027      DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
17028          vD_addr, vA_addr, vB_addr, vC_addr);
17029      /* widening multiply, separating lanes */
17030      assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
17031      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
17032
17033      /* break V128 to 4xI32's, zero-extending to I64's */
17034      breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
17035      breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
17036      breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
17037
17038      /* add lanes */
17039      assign( z3, binop(Iop_Add64, mkexpr(c3),
17040                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
17041      assign( z2, binop(Iop_Add64, mkexpr(c2),
17042                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
17043      assign( z1, binop(Iop_Add64, mkexpr(c1),
17044                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
17045      assign( z0, binop(Iop_Add64, mkexpr(c0),
17046                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
17047
17048      /* saturate-narrow to 32bit, and combine to V128 */
17049      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
17050                                         mkexpr(z1), mkexpr(z0)) );
17051
17052      break;
17053   }
17054   case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
17055      DIP("vmsumshm v%d,v%d,v%d,v%d\n",
17056          vD_addr, vA_addr, vB_addr, vC_addr);
17057      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
17058      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
17059      putVReg( vD_addr,
17060         binop(Iop_Add32x4, mkexpr(vC),
17061               binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
17062      break;
17063   }
17064   case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
17065      DIP("vmsumshs v%d,v%d,v%d,v%d\n",
17066          vD_addr, vA_addr, vB_addr, vC_addr);
17067      /* widening multiply, separating lanes */
17068      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
17069      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
17070
17071      /* break V128 to 4xI32's, sign-extending to I64's */
17072      breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
17073      breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
17074      breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
17075
17076      /* add lanes */
17077      assign( z3, binop(Iop_Add64, mkexpr(c3),
17078                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
17079      assign( z2, binop(Iop_Add64, mkexpr(c2),
17080                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
17081      assign( z1, binop(Iop_Add64, mkexpr(c1),
17082                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
17083      assign( z0, binop(Iop_Add64, mkexpr(c0),
17084                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
17085
17086      /* saturate-narrow to 32bit, and combine to V128 */
17087      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
17088                                         mkexpr(z1), mkexpr(z0)) );
17089      break;
17090   }
17091   default:
17092      vex_printf("dis_av_multarith(ppc)(opc2)\n");
17093      return False;
17094   }
17095   return True;
17096}
17097
17098/*
17099  AltiVec Polynomial Multiply-Sum Instructions
17100*/
17101static Bool dis_av_polymultarith ( UInt theInstr )
17102{
17103   /* VA-Form */
17104   UChar opc1     = ifieldOPC(theInstr);
17105   UChar vD_addr  = ifieldRegDS(theInstr);
17106   UChar vA_addr  = ifieldRegA(theInstr);
17107   UChar vB_addr  = ifieldRegB(theInstr);
17108   UChar vC_addr  = ifieldRegC(theInstr);
17109   UInt  opc2     = IFIELD(theInstr, 0, 11);
17110   IRTemp vA    = newTemp(Ity_V128);
17111   IRTemp vB    = newTemp(Ity_V128);
17112   IRTemp vC    = newTemp(Ity_V128);
17113
17114   assign( vA, getVReg(vA_addr));
17115   assign( vB, getVReg(vB_addr));
17116   assign( vC, getVReg(vC_addr));
17117
17118   if (opc1 != 0x4) {
17119      vex_printf("dis_av_polymultarith(ppc)(instr)\n");
17120      return False;
17121   }
17122
17123   switch (opc2) {
17124      /* Polynomial Multiply-Add */
17125      case 0x408:  // vpmsumb   Vector Polynomial Multipy-sum Byte
17126         DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17127         putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
17128                                 mkexpr(vA), mkexpr(vB)) );
17129         break;
17130      case 0x448:  // vpmsumd   Vector Polynomial Multipy-sum Double Word
17131         DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17132         putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
17133                                 mkexpr(vA), mkexpr(vB)) );
17134         break;
17135      case 0x488:  // vpmsumw   Vector Polynomial Multipy-sum Word
17136         DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17137         putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
17138                                 mkexpr(vA), mkexpr(vB)) );
17139         break;
17140      case 0x4C8:  // vpmsumh   Vector Polynomial Multipy-sum Half Word
17141         DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17142         putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
17143                                 mkexpr(vA), mkexpr(vB)) );
17144         break;
17145      default:
17146         vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
17147         return False;
17148   }
17149   return True;
17150}
17151
17152/*
17153  AltiVec Shift/Rotate Instructions
17154*/
17155static Bool dis_av_shift ( UInt theInstr )
17156{
17157   /* VX-Form */
17158   UChar opc1    = ifieldOPC(theInstr);
17159   UChar vD_addr = ifieldRegDS(theInstr);
17160   UChar vA_addr = ifieldRegA(theInstr);
17161   UChar vB_addr = ifieldRegB(theInstr);
17162   UInt  opc2    = IFIELD( theInstr, 0, 11 );
17163
17164   IRTemp vA = newTemp(Ity_V128);
17165   IRTemp vB = newTemp(Ity_V128);
17166   assign( vA, getVReg(vA_addr));
17167   assign( vB, getVReg(vB_addr));
17168
17169   if (opc1 != 0x4){
17170      vex_printf("dis_av_shift(ppc)(instr)\n");
17171      return False;
17172   }
17173
17174   switch (opc2) {
17175   /* Rotate */
17176   case 0x004: // vrlb (Rotate Left Integer B, AV p234)
17177      DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17178      putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
17179      break;
17180
17181   case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
17182      DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17183      putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
17184      break;
17185
17186   case 0x084: // vrlw (Rotate Left Integer W, AV p236)
17187      DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17188      putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
17189      break;
17190
17191   case 0x0C4: // vrld (Rotate Left Integer Double Word)
17192      DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17193      putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
17194      break;
17195
17196
17197   /* Shift Left */
17198   case 0x104: // vslb (Shift Left Integer B, AV p240)
17199      DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17200      putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
17201      break;
17202
17203   case 0x144: // vslh (Shift Left Integer HW, AV p242)
17204      DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17205      putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
17206      break;
17207
17208   case 0x184: // vslw (Shift Left Integer W, AV p244)
17209      DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17210      putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
17211      break;
17212
17213   case 0x5C4: // vsld (Shift Left Integer Double Word)
17214      DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17215      putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
17216      break;
17217
17218   case 0x1C4: { // vsl (Shift Left, AV p239)
17219      IRTemp sh = newTemp(Ity_I8);
17220      DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17221      assign( sh, binop(Iop_And8, mkU8(0x7),
17222                        unop(Iop_32to8,
17223                             unop(Iop_V128to32, mkexpr(vB)))) );
17224      putVReg( vD_addr,
17225               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
17226      break;
17227   }
17228   case 0x40C: { // vslo (Shift Left by Octet, AV p243)
17229      IRTemp sh = newTemp(Ity_I8);
17230      DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17231      assign( sh, binop(Iop_And8, mkU8(0x78),
17232                        unop(Iop_32to8,
17233                             unop(Iop_V128to32, mkexpr(vB)))) );
17234      putVReg( vD_addr,
17235               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
17236      break;
17237   }
17238
17239
17240   /* Shift Right */
17241   case 0x204: // vsrb (Shift Right B, AV p256)
17242      DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17243      putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
17244      break;
17245
17246   case 0x244: // vsrh (Shift Right HW, AV p257)
17247      DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17248      putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
17249      break;
17250
17251   case 0x284: // vsrw (Shift Right W, AV p259)
17252      DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17253      putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
17254      break;
17255
17256   case 0x2C4: { // vsr (Shift Right, AV p251)
17257      IRTemp sh = newTemp(Ity_I8);
17258      DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17259      assign( sh, binop(Iop_And8, mkU8(0x7),
17260                        unop(Iop_32to8,
17261                             unop(Iop_V128to32, mkexpr(vB)))) );
17262      putVReg( vD_addr,
17263               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
17264      break;
17265   }
17266   case 0x304: // vsrab (Shift Right Alg B, AV p253)
17267      DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17268      putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
17269      break;
17270
17271   case 0x344: // vsrah (Shift Right Alg HW, AV p254)
17272      DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17273      putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
17274      break;
17275
17276   case 0x384: // vsraw (Shift Right Alg W, AV p255)
17277      DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17278      putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
17279      break;
17280
17281   case 0x3C4: // vsrad (Shift Right Alg Double Word)
17282      DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17283      putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
17284      break;
17285
17286   case 0x44C: { // vsro (Shift Right by Octet, AV p258)
17287      IRTemp sh = newTemp(Ity_I8);
17288      DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17289      assign( sh, binop(Iop_And8, mkU8(0x78),
17290                        unop(Iop_32to8,
17291                             unop(Iop_V128to32, mkexpr(vB)))) );
17292      putVReg( vD_addr,
17293               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
17294      break;
17295   }
17296
17297   case 0x6C4: // vsrd (Shift Right Double Word)
17298      DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17299      putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
17300      break;
17301
17302
17303   default:
17304      vex_printf("dis_av_shift(ppc)(opc2)\n");
17305      return False;
17306   }
17307   return True;
17308}
17309
17310/*
17311  AltiVec Permute Instructions
17312*/
17313static Bool dis_av_permute ( UInt theInstr )
17314{
17315   /* VA-Form, VX-Form */
17316   UChar opc1      = ifieldOPC(theInstr);
17317   UChar vD_addr   = ifieldRegDS(theInstr);
17318   UChar vA_addr   = ifieldRegA(theInstr);
17319   UChar UIMM_5    = vA_addr;
17320   UChar vB_addr   = ifieldRegB(theInstr);
17321   UChar vC_addr   = ifieldRegC(theInstr);
17322   UChar b10       = ifieldBIT10(theInstr);
17323   UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
17324   UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
17325
17326   UChar SIMM_8 = extend_s_5to8(UIMM_5);
17327
17328   IRTemp vA = newTemp(Ity_V128);
17329   IRTemp vB = newTemp(Ity_V128);
17330   IRTemp vC = newTemp(Ity_V128);
17331   assign( vA, getVReg(vA_addr));
17332   assign( vB, getVReg(vB_addr));
17333   assign( vC, getVReg(vC_addr));
17334
17335   if (opc1 != 0x4) {
17336      vex_printf("dis_av_permute(ppc)(instr)\n");
17337      return False;
17338   }
17339
17340   switch (opc2) {
17341   case 0x2A: // vsel (Conditional Select, AV p238)
17342      DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
17343      /* vD = (vA & ~vC) | (vB & vC) */
17344      putVReg( vD_addr, binop(Iop_OrV128,
17345         binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
17346         binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
17347      return True;
17348
17349   case 0x2B: { // vperm (Permute, AV p218)
17350      /* limited to two args for IR, so have to play games... */
17351      IRTemp a_perm  = newTemp(Ity_V128);
17352      IRTemp b_perm  = newTemp(Ity_V128);
17353      IRTemp mask    = newTemp(Ity_V128);
17354      IRTemp vC_andF = newTemp(Ity_V128);
17355      DIP("vperm v%d,v%d,v%d,v%d\n",
17356          vD_addr, vA_addr, vB_addr, vC_addr);
17357      /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
17358         IR specifies, and also to hide irrelevant bits from
17359         memcheck */
17360      assign( vC_andF,
17361              binop(Iop_AndV128, mkexpr(vC),
17362                                 unop(Iop_Dup8x16, mkU8(0xF))) );
17363      assign( a_perm,
17364              binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
17365      assign( b_perm,
17366              binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
17367      // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
17368      assign( mask, binop(Iop_SarN8x16,
17369                          binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
17370                          mkU8(7)) );
17371      // dst = (a & ~mask) | (b & mask)
17372      putVReg( vD_addr, binop(Iop_OrV128,
17373                              binop(Iop_AndV128, mkexpr(a_perm),
17374                                    unop(Iop_NotV128, mkexpr(mask))),
17375                              binop(Iop_AndV128, mkexpr(b_perm),
17376                                    mkexpr(mask))) );
17377      return True;
17378   }
17379   case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
17380      if (b10 != 0) {
17381         vex_printf("dis_av_permute(ppc)(vsldoi)\n");
17382         return False;
17383      }
17384      DIP("vsldoi v%d,v%d,v%d,%d\n",
17385          vD_addr, vA_addr, vB_addr, SHB_uimm4);
17386      if (SHB_uimm4 == 0)
17387         putVReg( vD_addr, mkexpr(vA) );
17388      else
17389         putVReg( vD_addr,
17390            binop(Iop_OrV128,
17391                  binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
17392                  binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
17393      return True;
17394   case 0x2D: {  // vpermxor (Vector Permute and Exclusive-OR)
17395      IRTemp a_perm  = newTemp(Ity_V128);
17396      IRTemp b_perm  = newTemp(Ity_V128);
17397      IRTemp vrc_a   = newTemp(Ity_V128);
17398      IRTemp vrc_b   = newTemp(Ity_V128);
17399
17400      /* IBM index  is 0:7, Change index value to index 7:0 */
17401      assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
17402                            unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
17403      assign( vrc_a, binop( Iop_ShrV128,
17404                            binop( Iop_AndV128, mkexpr( vC ),
17405                                   unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
17406                            mkU8 ( 4 ) ) );
17407      assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
17408      assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
17409      putVReg( vD_addr, binop( Iop_XorV128,
17410                               mkexpr( a_perm ), mkexpr( b_perm) ) );
17411      return True;
17412   }
17413   default:
17414     break; // Fall through...
17415   }
17416
17417   opc2 = IFIELD( theInstr, 0, 11 );
17418   switch (opc2) {
17419
17420   /* Merge */
17421   case 0x00C: // vmrghb (Merge High B, AV p195)
17422      DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17423      putVReg( vD_addr,
17424               binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
17425      break;
17426
17427   case 0x04C: // vmrghh (Merge High HW, AV p196)
17428      DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17429      putVReg( vD_addr,
17430               binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
17431      break;
17432
17433   case 0x08C: // vmrghw (Merge High W, AV p197)
17434      DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17435      putVReg( vD_addr,
17436               binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
17437      break;
17438
17439   case 0x10C: // vmrglb (Merge Low B, AV p198)
17440      DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17441      putVReg( vD_addr,
17442               binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
17443      break;
17444
17445   case 0x14C: // vmrglh (Merge Low HW, AV p199)
17446      DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17447      putVReg( vD_addr,
17448               binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
17449      break;
17450
17451   case 0x18C: // vmrglw (Merge Low W, AV p200)
17452      DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17453      putVReg( vD_addr,
17454               binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
17455      break;
17456
17457
17458   /* Splat */
17459   case 0x20C: { // vspltb (Splat Byte, AV p245)
17460      /* vD = Dup8x16( vB[UIMM_5] ) */
17461      UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
17462      DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
17463      putVReg( vD_addr, unop(Iop_Dup8x16,
17464           unop(Iop_32to8, unop(Iop_V128to32,
17465                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
17466      break;
17467   }
17468   case 0x24C: { // vsplth (Splat Half Word, AV p246)
17469      UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
17470      DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
17471      putVReg( vD_addr, unop(Iop_Dup16x8,
17472           unop(Iop_32to16, unop(Iop_V128to32,
17473                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
17474      break;
17475   }
17476   case 0x28C: { // vspltw (Splat Word, AV p250)
17477      /* vD = Dup32x4( vB[UIMM_5] ) */
17478      UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
17479      DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
17480      putVReg( vD_addr, unop(Iop_Dup32x4,
17481         unop(Iop_V128to32,
17482              binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
17483      break;
17484   }
17485   case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
17486      DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
17487      putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
17488      break;
17489
17490   case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
17491      DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
17492      putVReg( vD_addr,
17493               unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
17494      break;
17495
17496   case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
17497      DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
17498      putVReg( vD_addr,
17499               unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
17500      break;
17501
17502   case 0x68C: // vmrgow (Merge Odd Word)
17503     DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17504      /*   VD[0] <- VA[1]
17505           VD[1] <- VB[1]
17506           VD[2] <- VA[3]
17507           VD[3] <- VB[3]
17508      */
17509      putVReg( vD_addr,
17510               binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
17511      break;
17512
17513   case 0x78C: // vmrgew (Merge Even Word)
17514      DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17515      /*   VD[0] <- VA[0]
17516           VD[1] <- VB[0]
17517           VD[2] <- VA[2]
17518           VD[3] <- VB[2]
17519      */
17520      putVReg( vD_addr,
17521               binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
17522      break;
17523
17524   default:
17525      vex_printf("dis_av_permute(ppc)(opc2)\n");
17526      return False;
17527   }
17528   return True;
17529}
17530
17531/*
17532  AltiVec Pack/Unpack Instructions
17533*/
17534static Bool dis_av_pack ( UInt theInstr )
17535{
17536   /* VX-Form */
17537   UChar opc1     = ifieldOPC(theInstr);
17538   UChar vD_addr  = ifieldRegDS(theInstr);
17539   UChar vA_addr  = ifieldRegA(theInstr);
17540   UChar vB_addr  = ifieldRegB(theInstr);
17541   UInt  opc2     = IFIELD( theInstr, 0, 11 );
17542
17543   IRTemp signs = IRTemp_INVALID;
17544   IRTemp zeros = IRTemp_INVALID;
17545   IRTemp vA    = newTemp(Ity_V128);
17546   IRTemp vB    = newTemp(Ity_V128);
17547   assign( vA, getVReg(vA_addr));
17548   assign( vB, getVReg(vB_addr));
17549
17550   if (opc1 != 0x4) {
17551      vex_printf("dis_av_pack(ppc)(instr)\n");
17552      return False;
17553   }
17554   switch (opc2) {
17555   /* Packing */
17556   case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
17557      DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17558      putVReg( vD_addr,
17559               binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
17560      return True;
17561
17562   case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
17563      DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17564      putVReg( vD_addr,
17565               binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
17566      return True;
17567
17568   case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
17569      DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17570      putVReg( vD_addr,
17571               binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
17572      // TODO: set VSCR[SAT]
17573      return True;
17574
17575   case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
17576      DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17577      putVReg( vD_addr,
17578               binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
17579      // TODO: set VSCR[SAT]
17580      return True;
17581
17582   case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
17583      // This insn does a signed->unsigned saturating conversion.
17584      // Conversion done here, then uses unsigned->unsigned vpk insn:
17585      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
17586      IRTemp vA_tmp = newTemp(Ity_V128);
17587      IRTemp vB_tmp = newTemp(Ity_V128);
17588      DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17589      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17590                            unop(Iop_NotV128,
17591                                 binop(Iop_SarN16x8,
17592                                       mkexpr(vA), mkU8(15)))) );
17593      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17594                            unop(Iop_NotV128,
17595                                 binop(Iop_SarN16x8,
17596                                       mkexpr(vB), mkU8(15)))) );
17597      putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
17598                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17599      // TODO: set VSCR[SAT]
17600      return True;
17601   }
17602   case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
17603      // This insn does a signed->unsigned saturating conversion.
17604      // Conversion done here, then uses unsigned->unsigned vpk insn:
17605      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
17606      IRTemp vA_tmp = newTemp(Ity_V128);
17607      IRTemp vB_tmp = newTemp(Ity_V128);
17608      DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17609      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17610                            unop(Iop_NotV128,
17611                                 binop(Iop_SarN32x4,
17612                                       mkexpr(vA), mkU8(31)))) );
17613      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17614                            unop(Iop_NotV128,
17615                                 binop(Iop_SarN32x4,
17616                                       mkexpr(vB), mkU8(31)))) );
17617      putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
17618                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17619      // TODO: set VSCR[SAT]
17620      return True;
17621   }
17622   case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
17623      DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17624      putVReg( vD_addr,
17625               binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
17626      // TODO: set VSCR[SAT]
17627      return True;
17628
17629   case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
17630      DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17631      putVReg( vD_addr,
17632               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
17633      // TODO: set VSCR[SAT]
17634      return True;
17635
17636   case 0x30E: { // vpkpx (Pack Pixel, AV p219)
17637      /* CAB: Worth a new primop? */
17638      /* Using shifts to compact pixel elements, then packing them */
17639      IRTemp a1 = newTemp(Ity_V128);
17640      IRTemp a2 = newTemp(Ity_V128);
17641      IRTemp a3 = newTemp(Ity_V128);
17642      IRTemp a_tmp = newTemp(Ity_V128);
17643      IRTemp b1 = newTemp(Ity_V128);
17644      IRTemp b2 = newTemp(Ity_V128);
17645      IRTemp b3 = newTemp(Ity_V128);
17646      IRTemp b_tmp = newTemp(Ity_V128);
17647      DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17648      assign( a1, binop(Iop_ShlN16x8,
17649                        binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
17650                        mkU8(10)) );
17651      assign( a2, binop(Iop_ShlN16x8,
17652                        binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
17653                        mkU8(5)) );
17654      assign( a3,  binop(Iop_ShrN16x8,
17655                         binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
17656                         mkU8(11)) );
17657      assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
17658                           binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
17659
17660      assign( b1, binop(Iop_ShlN16x8,
17661                        binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
17662                        mkU8(10)) );
17663      assign( b2, binop(Iop_ShlN16x8,
17664                        binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
17665                        mkU8(5)) );
17666      assign( b3,  binop(Iop_ShrN16x8,
17667                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
17668                         mkU8(11)) );
17669      assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
17670                           binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
17671
17672      putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
17673                              mkexpr(a_tmp), mkexpr(b_tmp)) );
17674      return True;
17675   }
17676
17677   case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
17678      DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17679      putVReg( vD_addr,
17680               binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
17681      return True;
17682
17683   case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
17684      DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17685      putVReg( vD_addr,
17686               binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
17687      // TODO: set VSCR[SAT]
17688      return True;
17689
17690   case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
17691      // This insn does a doubled signed->double unsigned saturating conversion
17692      // Conversion done here, then uses unsigned->unsigned vpk insn:
17693      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
17694      // This is similar to the technique used for vpkswus, except done
17695      // with double word integers versus word integers.
17696      IRTemp vA_tmp = newTemp(Ity_V128);
17697      IRTemp vB_tmp = newTemp(Ity_V128);
17698      DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17699      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17700                            unop(Iop_NotV128,
17701                                 binop(Iop_SarN64x2,
17702                                       mkexpr(vA), mkU8(63)))) );
17703      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17704                            unop(Iop_NotV128,
17705                                 binop(Iop_SarN64x2,
17706                                       mkexpr(vB), mkU8(63)))) );
17707      putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
17708                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17709      // TODO: set VSCR[SAT]
17710      return True;
17711   }
17712
17713   case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
17714      DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17715      putVReg( vD_addr,
17716               binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
17717      // TODO: set VSCR[SAT]
17718      return True;
17719   default:
17720      break; // Fall through...
17721   }
17722
17723
17724   if (vA_addr != 0) {
17725      vex_printf("dis_av_pack(ppc)(vA_addr)\n");
17726      return False;
17727   }
17728
17729   signs = newTemp(Ity_V128);
17730   zeros = newTemp(Ity_V128);
17731   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
17732
17733   switch (opc2) {
17734   /* Unpacking */
17735   case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
17736      DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
17737      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
17738      putVReg( vD_addr,
17739               binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
17740      break;
17741   }
17742   case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
17743      DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
17744      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
17745      putVReg( vD_addr,
17746               binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
17747      break;
17748   }
17749   case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
17750      DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
17751      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
17752      putVReg( vD_addr,
17753               binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
17754      break;
17755   }
17756   case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
17757      DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
17758      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
17759      putVReg( vD_addr,
17760               binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
17761      break;
17762   }
17763   case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
17764      /* CAB: Worth a new primop? */
17765      /* Using shifts to isolate pixel elements, then expanding them */
17766      IRTemp z0  = newTemp(Ity_V128);
17767      IRTemp z1  = newTemp(Ity_V128);
17768      IRTemp z01 = newTemp(Ity_V128);
17769      IRTemp z2  = newTemp(Ity_V128);
17770      IRTemp z3  = newTemp(Ity_V128);
17771      IRTemp z23 = newTemp(Ity_V128);
17772      DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
17773      assign( z0,  binop(Iop_ShlN16x8,
17774                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
17775                         mkU8(8)) );
17776      assign( z1,  binop(Iop_ShrN16x8,
17777                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
17778                         mkU8(11)) );
17779      assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
17780                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
17781      assign( z2,  binop(Iop_ShrN16x8,
17782                         binop(Iop_ShlN16x8,
17783                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
17784                               mkU8(11)),
17785                         mkU8(3)) );
17786      assign( z3,  binop(Iop_ShrN16x8,
17787                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
17788                         mkU8(11)) );
17789      assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
17790                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
17791      putVReg( vD_addr,
17792               binop(Iop_OrV128,
17793                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
17794                     mkexpr(z23)) );
17795      break;
17796   }
17797   case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
17798      /* identical to vupkhpx, except interleaving LO */
17799      IRTemp z0  = newTemp(Ity_V128);
17800      IRTemp z1  = newTemp(Ity_V128);
17801      IRTemp z01 = newTemp(Ity_V128);
17802      IRTemp z2  = newTemp(Ity_V128);
17803      IRTemp z3  = newTemp(Ity_V128);
17804      IRTemp z23 = newTemp(Ity_V128);
17805      DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
17806      assign( z0,  binop(Iop_ShlN16x8,
17807                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
17808                         mkU8(8)) );
17809      assign( z1,  binop(Iop_ShrN16x8,
17810                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
17811                         mkU8(11)) );
17812      assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
17813                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
17814      assign( z2,  binop(Iop_ShrN16x8,
17815                         binop(Iop_ShlN16x8,
17816                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
17817                               mkU8(11)),
17818                         mkU8(3)) );
17819      assign( z3,  binop(Iop_ShrN16x8,
17820                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
17821                         mkU8(11)) );
17822      assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
17823                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
17824      putVReg( vD_addr,
17825               binop(Iop_OrV128,
17826                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
17827                     mkexpr(z23)) );
17828      break;
17829   }
17830   case 0x64E: { // vupkhsw (Unpack High Signed Word)
17831      DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
17832      assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
17833      putVReg( vD_addr,
17834               binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
17835      break;
17836   }
17837   case 0x6CE: { // vupklsw (Unpack Low Signed Word)
17838      DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
17839      assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
17840      putVReg( vD_addr,
17841               binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
17842      break;
17843   }
17844   default:
17845      vex_printf("dis_av_pack(ppc)(opc2)\n");
17846      return False;
17847   }
17848   return True;
17849}
17850
17851/*
17852  AltiVec Cipher Instructions
17853*/
17854static Bool dis_av_cipher ( UInt theInstr )
17855{
17856   /* VX-Form */
17857   UChar opc1     = ifieldOPC(theInstr);
17858   UChar vD_addr  = ifieldRegDS(theInstr);
17859   UChar vA_addr  = ifieldRegA(theInstr);
17860   UChar vB_addr  = ifieldRegB(theInstr);
17861   UInt  opc2     = IFIELD( theInstr, 0, 11 );
17862
17863   IRTemp vA    = newTemp(Ity_V128);
17864   IRTemp vB    = newTemp(Ity_V128);
17865   assign( vA, getVReg(vA_addr));
17866   assign( vB, getVReg(vB_addr));
17867
17868   if (opc1 != 0x4) {
17869      vex_printf("dis_av_cipher(ppc)(instr)\n");
17870      return False;
17871   }
17872   switch (opc2) {
17873      case 0x508: // vcipher (Vector Inverser Cipher)
17874         DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17875         putVReg( vD_addr,
17876                  binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
17877         return True;
17878
17879      case 0x509: // vcipherlast (Vector Inverser Cipher Last)
17880         DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17881         putVReg( vD_addr,
17882                  binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
17883         return True;
17884
17885      case 0x548: // vncipher (Vector Inverser Cipher)
17886         DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17887         putVReg( vD_addr,
17888                  binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
17889         return True;
17890
17891      case 0x549: // vncipherlast (Vector Inverser Cipher Last)
17892         DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17893         putVReg( vD_addr,
17894                  binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
17895         return True;
17896
17897      case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
17898       * subBytes transform)
17899       */
17900         DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
17901         putVReg( vD_addr,
17902                  unop(Iop_CipherSV128, mkexpr(vA) ) );
17903         return True;
17904
17905      default:
17906         vex_printf("dis_av_cipher(ppc)(opc2)\n");
17907         return False;
17908   }
17909   return True;
17910}
17911
17912/*
17913  AltiVec Secure Hash Instructions
17914*/
17915static Bool dis_av_hash ( UInt theInstr )
17916{
17917   /* VX-Form */
17918   UChar opc1     = ifieldOPC(theInstr);
17919   UChar vRT_addr = ifieldRegDS(theInstr);
17920   UChar vRA_addr  = ifieldRegA(theInstr);
17921   UChar s_field  = IFIELD( theInstr, 11, 5 );  // st and six field
17922   UChar st       = IFIELD( theInstr, 15, 1 );  // st
17923   UChar six      = IFIELD( theInstr, 11, 4 );  // six field
17924   UInt  opc2     = IFIELD( theInstr, 0, 11 );
17925
17926   IRTemp vA    = newTemp(Ity_V128);
17927   IRTemp dst    = newTemp(Ity_V128);
17928   assign( vA, getVReg(vRA_addr));
17929
17930   if (opc1 != 0x4) {
17931      vex_printf("dis_av_hash(ppc)(instr)\n");
17932      return False;
17933   }
17934
17935   switch (opc2) {
17936      case 0x682:  // vshasigmaw
17937         DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
17938         assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
17939         putVReg( vRT_addr, mkexpr(dst));
17940         return True;
17941
17942      case 0x6C2:  // vshasigmad,
17943         DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
17944         putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
17945         return True;
17946
17947      default:
17948         vex_printf("dis_av_hash(ppc)(opc2)\n");
17949         return False;
17950   }
17951   return True;
17952}
17953
17954/*
17955 * This function is used by the Vector add/subtract [extended] modulo/carry
17956 * instructions.
17957 *   - For the non-extended add instructions, the cin arg is set to zero.
17958 *   - For the extended add instructions, cin is the integer value of
17959 *     src3.bit[127].
17960 *   - For the non-extended subtract instructions, src1 is added to the one's
17961 *     complement of src2 + 1.  We re-use the cin argument to hold the '1'
17962 *     value for this operation.
17963 *   - For the extended subtract instructions, cin is the integer value of src3.bit[127].
17964 */
17965static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
17966                                        IRExpr * cin, Bool modulo)
17967{
17968   IRTemp _vecA_32   = IRTemp_INVALID;
17969   IRTemp _vecB_32   = IRTemp_INVALID;
17970   IRTemp res_32     = IRTemp_INVALID;
17971   IRTemp result     = IRTemp_INVALID;
17972   IRTemp tmp_result = IRTemp_INVALID;
17973   IRTemp carry      = IRTemp_INVALID;
17974   Int i;
17975   IRExpr * _vecA_low64 =  unop( Iop_V128to64, vecA );
17976   IRExpr * _vecB_low64 =  unop( Iop_V128to64, vecB );
17977   IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
17978   IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
17979
17980   for (i = 0; i < 4; i++) {
17981      _vecA_32 = newTemp(Ity_I32);
17982      _vecB_32 = newTemp(Ity_I32);
17983      res_32   = newTemp(Ity_I32);
17984      switch (i) {
17985      case 0:
17986         assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
17987         assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
17988         break;
17989      case 1:
17990         assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
17991         assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
17992         break;
17993      case 2:
17994         assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
17995         assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
17996         break;
17997      case 3:
17998         assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
17999         assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
18000         break;
18001      }
18002
18003      assign(res_32, binop( Iop_Add32,
18004                            binop( Iop_Add32,
18005                                   binop ( Iop_Add32,
18006                                           mkexpr(_vecA_32),
18007                                           mkexpr(_vecB_32) ),
18008                                   (i == 0) ? mkU32(0) : mkexpr(carry) ),
18009                            (i == 0) ? cin : mkU32(0) ) );
18010      if (modulo) {
18011         result = newTemp(Ity_V128);
18012         assign(result, binop( Iop_OrV128,
18013                              (i == 0) ? binop( Iop_64HLtoV128,
18014                                                mkU64(0),
18015                                                mkU64(0) ) : mkexpr(tmp_result),
18016                              binop( Iop_ShlV128,
18017                                     binop( Iop_64HLtoV128,
18018                                            mkU64(0),
18019                                            binop( Iop_32HLto64,
18020                                                   mkU32(0),
18021                                                   mkexpr(res_32) ) ),
18022                                     mkU8(i * 32) ) ) );
18023         tmp_result = newTemp(Ity_V128);
18024         assign(tmp_result, mkexpr(result));
18025      }
18026      carry = newTemp(Ity_I32);
18027      assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U,
18028                                            mkexpr(res_32),
18029                                            mkexpr(_vecA_32 ) ) ) );
18030   }
18031   if (modulo)
18032      return result;
18033   else
18034      return carry;
18035}
18036
18037
18038static Bool dis_av_quad ( UInt theInstr )
18039{
18040   /* VX-Form */
18041   UChar opc1     = ifieldOPC(theInstr);
18042   UChar vRT_addr = ifieldRegDS(theInstr);
18043   UChar vRA_addr = ifieldRegA(theInstr);
18044   UChar vRB_addr = ifieldRegB(theInstr);
18045   UChar vRC_addr;
18046   UInt  opc2     = IFIELD( theInstr, 0, 11 );
18047
18048   IRTemp vA    = newTemp(Ity_V128);
18049   IRTemp vB    = newTemp(Ity_V128);
18050   IRTemp vC    = IRTemp_INVALID;
18051   IRTemp cin    = IRTemp_INVALID;
18052   assign( vA, getVReg(vRA_addr));
18053   assign( vB, getVReg(vRB_addr));
18054
18055   if (opc1 != 0x4) {
18056      vex_printf("dis_av_quad(ppc)(instr)\n");
18057      return False;
18058   }
18059
18060   switch (opc2) {
18061   case 0x140:  // vaddcuq
18062     DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18063     putVReg( vRT_addr, unop( Iop_32UtoV128,
18064                              mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18065                                                               mkexpr(vB),
18066                                                               mkU32(0), False) ) ) );
18067     return True;
18068   case 0x100: // vadduqm
18069      DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18070      putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18071                                                          mkexpr(vB), mkU32(0), True) ) );
18072      return True;
18073   case 0x540: // vsubcuq
18074      DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18075      putVReg( vRT_addr,
18076               unop( Iop_32UtoV128,
18077                     mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18078                                                      unop( Iop_NotV128,
18079                                                            mkexpr(vB) ),
18080                                                      mkU32(1), False) ) ) );
18081      return True;
18082   case 0x500: // vsubuqm
18083      DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18084      putVReg( vRT_addr,
18085               mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18086                                                unop( Iop_NotV128, mkexpr(vB) ),
18087                                                mkU32(1), True) ) );
18088      return True;
18089   case 0x054C: // vbpermq
18090   {
18091#define BPERMD_IDX_MASK 0x00000000000000FFULL
18092#define BPERMD_BIT_MASK 0x8000000000000000ULL
18093      int i;
18094      IRExpr * vB_expr = mkexpr(vB);
18095      IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
18096      DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18097      for (i = 0; i < 16; i++) {
18098         IRTemp idx_tmp = newTemp( Ity_V128 );
18099         IRTemp perm_bit = newTemp( Ity_V128 );
18100         IRTemp idx = newTemp( Ity_I8 );
18101         IRTemp idx_LT127 = newTemp( Ity_I1 );
18102         IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
18103
18104         assign( idx_tmp,
18105                 binop( Iop_AndV128,
18106                        binop( Iop_64HLtoV128,
18107                               mkU64(0),
18108                               mkU64(BPERMD_IDX_MASK) ),
18109                        vB_expr ) );
18110         assign( idx_LT127,
18111                 binop( Iop_CmpEQ32,
18112                        unop ( Iop_64to32,
18113                               unop( Iop_V128to64, binop( Iop_ShrV128,
18114                                                          mkexpr(idx_tmp),
18115                                                          mkU8(7) ) ) ),
18116                        mkU32(0) ) );
18117
18118         /* Below, we set idx to determine which bit of vA to use for the
18119          * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
18120          */
18121         assign( idx,
18122                 binop( Iop_And8,
18123                        unop( Iop_1Sto8,
18124                              mkexpr(idx_LT127) ),
18125                        unop( Iop_32to8,
18126                              unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
18127
18128         assign( idx_LT127_ity128,
18129                 binop( Iop_64HLtoV128,
18130                        mkU64(0),
18131                        unop( Iop_32Uto64,
18132                              unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
18133         assign( perm_bit,
18134                 binop( Iop_AndV128,
18135                        mkexpr( idx_LT127_ity128 ),
18136                        binop( Iop_ShrV128,
18137                               binop( Iop_AndV128,
18138                                      binop (Iop_64HLtoV128,
18139                                             mkU64( BPERMD_BIT_MASK ),
18140                                             mkU64(0)),
18141                                      binop( Iop_ShlV128,
18142                                             mkexpr( vA ),
18143                                             mkexpr( idx ) ) ),
18144                               mkU8( 127 ) ) ) );
18145         res = binop( Iop_OrV128,
18146                      res,
18147                      binop( Iop_ShlV128,
18148                             mkexpr( perm_bit ),
18149                             mkU8( i + 64 ) ) );
18150         vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
18151      }
18152      putVReg( vRT_addr, res);
18153      return True;
18154#undef BPERMD_IDX_MASK
18155#undef BPERMD_BIT_MASK
18156   }
18157
18158   default:
18159      break;  // fall through
18160   }
18161
18162   opc2     = IFIELD( theInstr, 0, 6 );
18163   vRC_addr = ifieldRegC(theInstr);
18164   vC = newTemp(Ity_V128);
18165   cin = newTemp(Ity_I32);
18166   switch (opc2) {
18167      case 0x3D: // vaddecuq
18168         assign( vC, getVReg(vRC_addr));
18169         DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18170             vRC_addr);
18171         assign(cin, binop( Iop_And32,
18172                            unop( Iop_64to32,
18173                                  unop( Iop_V128to64, mkexpr(vC) ) ),
18174                            mkU32(1) ) );
18175         putVReg( vRT_addr,
18176                  unop( Iop_32UtoV128,
18177                        mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
18178                                                         mkexpr(cin),
18179                                                         False) ) ) );
18180         return True;
18181      case 0x3C: // vaddeuqm
18182         assign( vC, getVReg(vRC_addr));
18183         DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18184             vRC_addr);
18185         assign(cin, binop( Iop_And32,
18186                            unop( Iop_64to32,
18187                                  unop( Iop_V128to64, mkexpr(vC) ) ),
18188                            mkU32(1) ) );
18189         putVReg( vRT_addr,
18190                  mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
18191                                                   mkexpr(cin),
18192                                                   True) ) );
18193         return True;
18194      case 0x3F: // vsubecuq
18195         assign( vC, getVReg(vRC_addr));
18196         DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18197             vRC_addr);
18198         assign(cin, binop( Iop_And32,
18199                            unop( Iop_64to32,
18200                                  unop( Iop_V128to64, mkexpr(vC) ) ),
18201                            mkU32(1) ) );
18202         putVReg( vRT_addr,
18203                  unop( Iop_32UtoV128,
18204                        mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18205                                                         unop( Iop_NotV128,
18206                                                               mkexpr(vB) ),
18207                                                         mkexpr(cin),
18208                                                         False) ) ) );
18209         return True;
18210      case 0x3E: // vsubeuqm
18211         assign( vC, getVReg(vRC_addr));
18212         DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18213             vRC_addr);
18214         assign(cin, binop( Iop_And32,
18215                            unop( Iop_64to32,
18216                                  unop( Iop_V128to64, mkexpr(vC) ) ),
18217                            mkU32(1) ) );
18218         putVReg( vRT_addr,
18219                  mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18220                                                   unop( Iop_NotV128, mkexpr(vB) ),
18221                                                   mkexpr(cin),
18222                                                   True) ) );
18223         return True;
18224      default:
18225         vex_printf("dis_av_quad(ppc)(opc2.2)\n");
18226         return False;
18227   }
18228
18229   return True;
18230}
18231
18232
18233/*
18234  AltiVec BCD Arithmetic instructions.
18235  These instructions modify CR6 for various conditions in the result,
18236  including when an overflow occurs.  We could easily detect all conditions
18237  except when an overflow occurs.  But since we can't be 100% accurate
18238  in our emulation of CR6, it seems best to just not support it all.
18239*/
18240static Bool dis_av_bcd ( UInt theInstr )
18241{
18242   /* VX-Form */
18243   UChar opc1     = ifieldOPC(theInstr);
18244   UChar vRT_addr = ifieldRegDS(theInstr);
18245   UChar vRA_addr = ifieldRegA(theInstr);
18246   UChar vRB_addr = ifieldRegB(theInstr);
18247   UChar ps       = IFIELD( theInstr, 9, 1 );
18248   UInt  opc2     = IFIELD( theInstr, 0, 9 );
18249
18250   IRTemp vA    = newTemp(Ity_V128);
18251   IRTemp vB    = newTemp(Ity_V128);
18252   IRTemp dst    = newTemp(Ity_V128);
18253   assign( vA, getVReg(vRA_addr));
18254   assign( vB, getVReg(vRB_addr));
18255
18256   if (opc1 != 0x4) {
18257      vex_printf("dis_av_bcd(ppc)(instr)\n");
18258      return False;
18259   }
18260
18261   switch (opc2) {
18262   case 0x1:  // bcdadd
18263     DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
18264     assign( dst, triop( Iop_BCDAdd, mkexpr( vA ),
18265                         mkexpr( vB ), mkU8( ps ) ) );
18266     putVReg( vRT_addr, mkexpr(dst));
18267     return True;
18268
18269   case 0x41:  // bcdsub
18270     DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
18271     assign( dst, triop( Iop_BCDSub, mkexpr( vA ),
18272                         mkexpr( vB ), mkU8( ps ) ) );
18273     putVReg( vRT_addr, mkexpr(dst));
18274     return True;
18275
18276   default:
18277      vex_printf("dis_av_bcd(ppc)(opc2)\n");
18278      return False;
18279   }
18280   return True;
18281}
18282
18283/*
18284  AltiVec Floating Point Arithmetic Instructions
18285*/
18286static Bool dis_av_fp_arith ( UInt theInstr )
18287{
18288   /* VA-Form */
18289   UChar opc1     = ifieldOPC(theInstr);
18290   UChar vD_addr  = ifieldRegDS(theInstr);
18291   UChar vA_addr  = ifieldRegA(theInstr);
18292   UChar vB_addr  = ifieldRegB(theInstr);
18293   UChar vC_addr  = ifieldRegC(theInstr);
18294   UInt  opc2=0;
18295
18296   IRTemp vA = newTemp(Ity_V128);
18297   IRTemp vB = newTemp(Ity_V128);
18298   IRTemp vC = newTemp(Ity_V128);
18299   assign( vA, getVReg(vA_addr));
18300   assign( vB, getVReg(vB_addr));
18301   assign( vC, getVReg(vC_addr));
18302
18303   if (opc1 != 0x4) {
18304      vex_printf("dis_av_fp_arith(ppc)(instr)\n");
18305      return False;
18306   }
18307
18308   IRTemp rm = newTemp(Ity_I32);
18309   assign(rm, get_IR_roundingmode());
18310
18311   opc2 = IFIELD( theInstr, 0, 6 );
18312   switch (opc2) {
18313   case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
18314      DIP("vmaddfp v%d,v%d,v%d,v%d\n",
18315          vD_addr, vA_addr, vC_addr, vB_addr);
18316      putVReg( vD_addr,
18317               triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
18318                     mkexpr(vB),
18319                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18320                           mkexpr(vA), mkexpr(vC))) );
18321      return True;
18322
18323   case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
18324      DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
18325          vD_addr, vA_addr, vC_addr, vB_addr);
18326      putVReg( vD_addr,
18327               triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
18328                     mkexpr(vB),
18329                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18330                           mkexpr(vA), mkexpr(vC))) );
18331      return True;
18332   }
18333
18334   default:
18335     break; // Fall through...
18336   }
18337
18338   opc2 = IFIELD( theInstr, 0, 11 );
18339   switch (opc2) {
18340   case 0x00A: // vaddfp (Add FP, AV p137)
18341      DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18342      putVReg( vD_addr, triop(Iop_Add32Fx4,
18343                              mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
18344      return True;
18345
18346  case 0x04A: // vsubfp (Subtract FP, AV p261)
18347      DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18348      putVReg( vD_addr, triop(Iop_Sub32Fx4,
18349                              mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
18350      return True;
18351
18352   case 0x40A: // vmaxfp (Maximum FP, AV p178)
18353      DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18354      putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
18355      return True;
18356
18357   case 0x44A: // vminfp (Minimum FP, AV p187)
18358      DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18359      putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
18360      return True;
18361
18362   default:
18363      break; // Fall through...
18364   }
18365
18366
18367   if (vA_addr != 0) {
18368      vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
18369      return False;
18370   }
18371
18372   switch (opc2) {
18373   case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
18374      DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
18375      putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) );
18376      return True;
18377
18378   case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
18379      DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
18380      putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) );
18381      return True;
18382
18383   case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
18384      DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
18385      DIP(" => not implemented\n");
18386      return False;
18387
18388   case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
18389      DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
18390      DIP(" => not implemented\n");
18391      return False;
18392
18393   default:
18394      vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
18395      return False;
18396   }
18397   return True;
18398}
18399
18400/*
18401  AltiVec Floating Point Compare Instructions
18402*/
18403static Bool dis_av_fp_cmp ( UInt theInstr )
18404{
18405   /* VXR-Form */
18406   UChar opc1     = ifieldOPC(theInstr);
18407   UChar vD_addr  = ifieldRegDS(theInstr);
18408   UChar vA_addr  = ifieldRegA(theInstr);
18409   UChar vB_addr  = ifieldRegB(theInstr);
18410   UChar flag_rC  = ifieldBIT10(theInstr);
18411   UInt  opc2     = IFIELD( theInstr, 0, 10 );
18412
18413   Bool cmp_bounds = False;
18414
18415   IRTemp vA = newTemp(Ity_V128);
18416   IRTemp vB = newTemp(Ity_V128);
18417   IRTemp vD = newTemp(Ity_V128);
18418   assign( vA, getVReg(vA_addr));
18419   assign( vB, getVReg(vB_addr));
18420
18421   if (opc1 != 0x4) {
18422      vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
18423      return False;
18424   }
18425
18426   switch (opc2) {
18427   case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
18428      DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18429                                      vD_addr, vA_addr, vB_addr);
18430      assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
18431      break;
18432
18433   case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
18434      DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18435                                      vD_addr, vA_addr, vB_addr);
18436      assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
18437      break;
18438
18439   case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
18440      DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18441                                      vD_addr, vA_addr, vB_addr);
18442      assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
18443      break;
18444
18445   case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
18446      IRTemp gt      = newTemp(Ity_V128);
18447      IRTemp lt      = newTemp(Ity_V128);
18448      IRTemp zeros   = newTemp(Ity_V128);
18449      DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18450                                     vD_addr, vA_addr, vB_addr);
18451      cmp_bounds = True;
18452      assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
18453
18454      /* Note: making use of fact that the ppc backend for compare insns
18455         return zero'd lanes if either of the corresponding arg lanes is
18456         a nan.
18457
18458         Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
18459         need this for the other compares too (vcmpeqfp etc)...
18460         Better still, tighten down the spec for compare irops.
18461       */
18462      assign( gt, unop(Iop_NotV128,
18463                       binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
18464      assign( lt, unop(Iop_NotV128,
18465                       binop(Iop_CmpGE32Fx4, mkexpr(vA),
18466                             triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
18467                                   mkexpr(zeros),
18468                                   mkexpr(vB)))) );
18469
18470      // finally, just shift gt,lt to correct position
18471      assign( vD, binop(Iop_ShlN32x4,
18472                        binop(Iop_OrV128,
18473                              binop(Iop_AndV128, mkexpr(gt),
18474                                    unop(Iop_Dup32x4, mkU32(0x2))),
18475                              binop(Iop_AndV128, mkexpr(lt),
18476                                    unop(Iop_Dup32x4, mkU32(0x1)))),
18477                        mkU8(30)) );
18478      break;
18479   }
18480
18481   default:
18482      vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
18483      return False;
18484   }
18485
18486   putVReg( vD_addr, mkexpr(vD) );
18487
18488   if (flag_rC) {
18489      set_AV_CR6( mkexpr(vD), !cmp_bounds );
18490   }
18491   return True;
18492}
18493
18494/*
18495  AltiVec Floating Point Convert/Round Instructions
18496*/
18497static Bool dis_av_fp_convert ( UInt theInstr )
18498{
18499   /* VX-Form */
18500   UChar opc1     = ifieldOPC(theInstr);
18501   UChar vD_addr  = ifieldRegDS(theInstr);
18502   UChar UIMM_5   = ifieldRegA(theInstr);
18503   UChar vB_addr  = ifieldRegB(theInstr);
18504   UInt  opc2     = IFIELD( theInstr, 0, 11 );
18505
18506   IRTemp vB        = newTemp(Ity_V128);
18507   IRTemp vScale    = newTemp(Ity_V128);
18508   IRTemp vInvScale = newTemp(Ity_V128);
18509
18510   float scale, inv_scale;
18511
18512   assign( vB, getVReg(vB_addr));
18513
18514   /* scale = 2^UIMM, cast to float, reinterpreted as uint */
18515   scale = (float)( (unsigned int) 1<<UIMM_5 );
18516   assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
18517   inv_scale = 1/scale;
18518   assign( vInvScale,
18519           unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
18520
18521   if (opc1 != 0x4) {
18522      vex_printf("dis_av_fp_convert(ppc)(instr)\n");
18523      return False;
18524   }
18525
18526   switch (opc2) {
18527   case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
18528      DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18529      putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18530                              unop(Iop_I32UtoFx4, mkexpr(vB)),
18531                              mkexpr(vInvScale)) );
18532      return True;
18533
18534   case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
18535      DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18536
18537      putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18538                              unop(Iop_I32StoFx4, mkexpr(vB)),
18539                              mkexpr(vInvScale)) );
18540      return True;
18541
18542   case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
18543      DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18544      putVReg( vD_addr,
18545               unop(Iop_QFtoI32Ux4_RZ,
18546                    triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18547                          mkexpr(vB), mkexpr(vScale))) );
18548      return True;
18549
18550   case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
18551      DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18552      putVReg( vD_addr,
18553               unop(Iop_QFtoI32Sx4_RZ,
18554                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18555                           mkexpr(vB), mkexpr(vScale))) );
18556      return True;
18557
18558   default:
18559     break;    // Fall through...
18560   }
18561
18562   if (UIMM_5 != 0) {
18563      vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
18564      return False;
18565   }
18566
18567   switch (opc2) {
18568   case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
18569      DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
18570      putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
18571      break;
18572
18573   case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
18574      DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
18575      putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
18576      break;
18577
18578   case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
18579      DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
18580      putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
18581      break;
18582
18583   case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
18584      DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
18585      putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
18586      break;
18587
18588   default:
18589      vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
18590      return False;
18591   }
18592   return True;
18593}
18594
18595static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
18596                                       const VexAbiInfo* vbi,
18597                                       /*OUT*/DisResult* dres,
18598                                       Bool (*resteerOkFn)(void*,Addr),
18599                                       void* callback_opaque )
18600{
18601   UInt   opc2      = IFIELD( theInstr, 1, 10 );
18602
18603   switch (opc2) {
18604   case 0x28E: {        //tbegin.
18605      /* The current implementation is to just fail the tbegin and execute
18606       * the failure path.  The failure path is assumed to be functionaly
18607       * equivalent to the transactional path with the needed data locking
18608       * to ensure correctness.  The tend is just a noop and shouldn't
18609       * actually get executed.
18610       *   1) set cr0 to 0x2
18611       *   2) Initialize TFHAR to CIA+4
18612       *   3) Initialize TEXASR
18613       *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
18614       *   5) Continue executing at the next instruction.
18615       */
18616      UInt R = IFIELD( theInstr, 21, 1 );
18617
18618      ULong tm_reason;
18619      UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
18620                               * or treclaim.
18621                               */
18622      UInt persistant = 1;    /* set persistant since we are always failing
18623                               * the tbegin.
18624                               */
18625      UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
18626                                 as the reason for failing the trasaction */
18627      UInt tm_exact   = 1;    /* have exact address for failure */
18628
18629      DIP("tbegin. %u\n", R);
18630
18631      /* Set the CR0 field to indicate the tbegin failed.  Then let
18632       * the code do the branch to the failure path.
18633       *
18634       * 000 || 0  Transaction initiation successful,
18635       *           unnested (Transaction state of
18636       *           Non-transactional prior to tbegin.)
18637       * 010 || 0  Transaction initiation successful, nested
18638       *           (Transaction state of Transactional
18639       *           prior to tbegin.)
18640       * 001 || 0  Transaction initiation unsuccessful,
18641       *           (Transaction state of Suspended prior
18642       *           to tbegin.)
18643       */
18644      putCR321( 0, mkU8( 0x2 ) );
18645
18646      tm_reason = generate_TMreason( failure_code, persistant,
18647                                     nest_overflow, tm_exact );
18648
18649      storeTMfailure( guest_CIA_curr_instr, tm_reason,
18650                      guest_CIA_curr_instr+4 );
18651
18652      return True;
18653
18654      break;
18655   }
18656
18657   case 0x2AE: {        //tend.
18658      /* The tend. is just a noop.  Do nothing */
18659      UInt A = IFIELD( theInstr, 25, 1 );
18660
18661      DIP("tend. %u\n", A);
18662      break;
18663   }
18664
18665   case 0x2EE: {        //tsr.
18666      /* The tsr. is just a noop.  Do nothing */
18667      UInt L = IFIELD( theInstr, 21, 1 );
18668
18669      DIP("tsr. %u\n", L);
18670      break;
18671   }
18672
18673   case 0x2CE: {        //tcheck.
18674      /* The tcheck. is just a noop.  Do nothing */
18675      UInt BF = IFIELD( theInstr, 25, 1 );
18676
18677      DIP("tcheck. %u\n", BF);
18678      break;
18679   }
18680
18681   case 0x30E: {        //tbortwc.
18682      /* The tabortwc. is just a noop.  Do nothing */
18683      UInt TO = IFIELD( theInstr, 25, 1 );
18684      UInt RA = IFIELD( theInstr, 16, 5 );
18685      UInt RB = IFIELD( theInstr, 11, 5 );
18686
18687      DIP("tabortwc. %u,%u,%u\n", TO, RA, RB);
18688      break;
18689   }
18690
18691   case 0x32E: {        //tbortdc.
18692      /* The tabortdc. is just a noop.  Do nothing */
18693      UInt TO = IFIELD( theInstr, 25, 1 );
18694      UInt RA = IFIELD( theInstr, 16, 5 );
18695      UInt RB = IFIELD( theInstr, 11, 5 );
18696
18697      DIP("tabortdc. %u,%u,%u\n", TO, RA, RB);
18698      break;
18699   }
18700
18701   case 0x34E: {        //tbortwci.
18702      /* The tabortwci. is just a noop.  Do nothing */
18703      UInt TO = IFIELD( theInstr, 25, 1 );
18704      UInt RA = IFIELD( theInstr, 16, 5 );
18705      UInt SI = IFIELD( theInstr, 11, 5 );
18706
18707      DIP("tabortwci. %u,%u,%u\n", TO, RA, SI);
18708      break;
18709   }
18710
18711   case 0x36E: {        //tbortdci.
18712      /* The tabortdci. is just a noop.  Do nothing */
18713      UInt TO = IFIELD( theInstr, 25, 1 );
18714      UInt RA = IFIELD( theInstr, 16, 5 );
18715      UInt SI = IFIELD( theInstr, 11, 5 );
18716
18717      DIP("tabortdci. %u,%u,%u\n", TO, RA, SI);
18718      break;
18719   }
18720
18721   case 0x38E: {        //tbort.
18722      /* The tabort. is just a noop.  Do nothing */
18723      UInt RA = IFIELD( theInstr, 16, 5 );
18724
18725      DIP("tabort. %u\n", RA);
18726      break;
18727   }
18728
18729   case 0x3AE: {        //treclaim.
18730      /* The treclaim. is just a noop.  Do nothing */
18731      UInt RA = IFIELD( theInstr, 16, 5 );
18732
18733      DIP("treclaim. %u\n", RA);
18734      break;
18735   }
18736
18737   case 0x3EE: {        //trechkpt.
18738      /* The trechkpt. is just a noop.  Do nothing */
18739      DIP("trechkpt.\n");
18740      break;
18741   }
18742
18743   default:
18744      vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
18745      return False;
18746   }
18747
18748   return True;
18749}
18750
18751
18752/* The 0x3C primary opcode (VSX category) uses several different forms of
18753 * extended opcodes:
18754 *   o XX2-form:
18755 *      - [10:2] (IBM notation [21:29])
18756 *   o XX3-form variants:
18757 *       - variant 1: [10:3] (IBM notation [21:28])
18758 *       - variant 2: [9:3] (IBM notation [22:28])
18759 *       - variant 3: [7:3] (IBM notation [24:28])
18760 *   o XX-4 form:
18761 *      - [10:6] (IBM notation [21:25])
18762 *
18763 * The XX2-form needs bit 0 masked from the standard extended opcode
18764 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
18765 * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
18766 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
18767 * front end since their encoding does not begin at bit 21 like the standard
18768 * format.
18769 *
18770 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
18771 * secondary opcode for such VSX instructions.
18772 *
18773*/
18774
18775
18776struct vsx_insn {
18777   UInt opcode;
18778   const HChar * name;
18779};
18780
18781//  ATTENTION:  Keep this array sorted on the opcocde!!!
18782static struct vsx_insn vsx_all[] = {
18783      { 0x0, "xsaddsp" },
18784      { 0x4, "xsmaddasp" },
18785      { 0x8, "xxsldwi" },
18786      { 0x14, "xsrsqrtesp" },
18787      { 0x16, "xssqrtsp" },
18788      { 0x18, "xxsel" },
18789      { 0x20, "xssubsp" },
18790      { 0x24, "xsmaddmsp" },
18791      { 0x28, "xxpermdi" },
18792      { 0x34, "xsresp" },
18793      { 0x40, "xsmulsp" },
18794      { 0x44, "xsmsubasp" },
18795      { 0x48, "xxmrghw" },
18796      { 0x60, "xsdivsp" },
18797      { 0x64, "xsmsubmsp" },
18798      { 0x80, "xsadddp" },
18799      { 0x84, "xsmaddadp" },
18800      { 0x8c, "xscmpudp" },
18801      { 0x90, "xscvdpuxws" },
18802      { 0x92, "xsrdpi" },
18803      { 0x94, "xsrsqrtedp" },
18804      { 0x96, "xssqrtdp" },
18805      { 0xa0, "xssubdp" },
18806      { 0xa4, "xsmaddmdp" },
18807      { 0xac, "xscmpodp" },
18808      { 0xb0, "xscvdpsxws" },
18809      { 0xb2, "xsrdpiz" },
18810      { 0xb4, "xsredp" },
18811      { 0xc0, "xsmuldp" },
18812      { 0xc4, "xsmsubadp" },
18813      { 0xc8, "xxmrglw" },
18814      { 0xd2, "xsrdpip" },
18815      { 0xd4, "xstsqrtdp" },
18816      { 0xd6, "xsrdpic" },
18817      { 0xe0, "xsdivdp" },
18818      { 0xe4, "xsmsubmdp" },
18819      { 0xf2, "xsrdpim" },
18820      { 0xf4, "xstdivdp" },
18821      { 0x100, "xvaddsp" },
18822      { 0x104, "xvmaddasp" },
18823      { 0x10c, "xvcmpeqsp" },
18824      { 0x110, "xvcvspuxws" },
18825      { 0x112, "xvrspi" },
18826      { 0x114, "xvrsqrtesp" },
18827      { 0x116, "xvsqrtsp" },
18828      { 0x120, "xvsubsp" },
18829      { 0x124, "xvmaddmsp" },
18830      { 0x12c, "xvcmpgtsp" },
18831      { 0x130, "xvcvspsxws" },
18832      { 0x132, "xvrspiz" },
18833      { 0x134, "xvresp" },
18834      { 0x140, "xvmulsp" },
18835      { 0x144, "xvmsubasp" },
18836      { 0x148, "xxspltw" },
18837      { 0x14c, "xvcmpgesp" },
18838      { 0x150, "xvcvuxwsp" },
18839      { 0x152, "xvrspip" },
18840      { 0x154, "xvtsqrtsp" },
18841      { 0x156, "xvrspic" },
18842      { 0x160, "xvdivsp" },
18843      { 0x164, "xvmsubmsp" },
18844      { 0x170, "xvcvsxwsp" },
18845      { 0x172, "xvrspim" },
18846      { 0x174, "xvtdivsp" },
18847      { 0x180, "xvadddp" },
18848      { 0x184, "xvmaddadp" },
18849      { 0x18c, "xvcmpeqdp" },
18850      { 0x190, "xvcvdpuxws" },
18851      { 0x192, "xvrdpi" },
18852      { 0x194, "xvrsqrtedp" },
18853      { 0x196, "xvsqrtdp" },
18854      { 0x1a0, "xvsubdp" },
18855      { 0x1a4, "xvmaddmdp" },
18856      { 0x1ac, "xvcmpgtdp" },
18857      { 0x1b0, "xvcvdpsxws" },
18858      { 0x1b2, "xvrdpiz" },
18859      { 0x1b4, "xvredp" },
18860      { 0x1c0, "xvmuldp" },
18861      { 0x1c4, "xvmsubadp" },
18862      { 0x1cc, "xvcmpgedp" },
18863      { 0x1d0, "xvcvuxwdp" },
18864      { 0x1d2, "xvrdpip" },
18865      { 0x1d4, "xvtsqrtdp" },
18866      { 0x1d6, "xvrdpic" },
18867      { 0x1e0, "xvdivdp" },
18868      { 0x1e4, "xvmsubmdp" },
18869      { 0x1f0, "xvcvsxwdp" },
18870      { 0x1f2, "xvrdpim" },
18871      { 0x1f4, "xvtdivdp" },
18872      { 0x204, "xsnmaddasp" },
18873      { 0x208, "xxland" },
18874      { 0x212, "xscvdpsp" },
18875      { 0x216, "xscvdpspn" },
18876      { 0x224, "xsnmaddmsp" },
18877      { 0x228, "xxlandc" },
18878      { 0x232, "xxrsp" },
18879      { 0x244, "xsnmsubasp" },
18880      { 0x248, "xxlor" },
18881      { 0x250, "xscvuxdsp" },
18882      { 0x264, "xsnmsubmsp" },
18883      { 0x268, "xxlxor" },
18884      { 0x270, "xscvsxdsp" },
18885      { 0x280, "xsmaxdp" },
18886      { 0x284, "xsnmaddadp" },
18887      { 0x288, "xxlnor" },
18888      { 0x290, "xscvdpuxds" },
18889      { 0x292, "xscvspdp" },
18890      { 0x296, "xscvspdpn" },
18891      { 0x2a0, "xsmindp" },
18892      { 0x2a4, "xsnmaddmdp" },
18893      { 0x2a8, "xxlorc" },
18894      { 0x2b0, "xscvdpsxds" },
18895      { 0x2b2, "xsabsdp" },
18896      { 0x2c0, "xscpsgndp" },
18897      { 0x2c4, "xsnmsubadp" },
18898      { 0x2c8, "xxlnand" },
18899      { 0x2d0, "xscvuxddp" },
18900      { 0x2d2, "xsnabsdp" },
18901      { 0x2e4, "xsnmsubmdp" },
18902      { 0x2e8, "xxleqv" },
18903      { 0x2f0, "xscvsxddp" },
18904      { 0x2f2, "xsnegdp" },
18905      { 0x300, "xvmaxsp" },
18906      { 0x304, "xvnmaddasp" },
18907      { 0x30c, "xvcmpeqsp." },
18908      { 0x310, "xvcvspuxds" },
18909      { 0x312, "xvcvdpsp" },
18910      { 0x320, "xvminsp" },
18911      { 0x324, "xvnmaddmsp" },
18912      { 0x32c, "xvcmpgtsp." },
18913      { 0x330, "xvcvspsxds" },
18914      { 0x332, "xvabssp" },
18915      { 0x340, "xvcpsgnsp" },
18916      { 0x344, "xvnmsubasp" },
18917      { 0x34c, "xvcmpgesp." },
18918      { 0x350, "xvcvuxdsp" },
18919      { 0x352, "xvnabssp" },
18920      { 0x364, "xvnmsubmsp" },
18921      { 0x370, "xvcvsxdsp" },
18922      { 0x372, "xvnegsp" },
18923      { 0x380, "xvmaxdp" },
18924      { 0x384, "xvnmaddadp" },
18925      { 0x38c, "xvcmpeqdp." },
18926      { 0x390, "xvcvdpuxds" },
18927      { 0x392, "xvcvspdp" },
18928      { 0x3a0, "xvmindp" },
18929      { 0x3a4, "xvnmaddmdp" },
18930      { 0x3ac, "xvcmpgtdp." },
18931      { 0x3b0, "xvcvdpsxds" },
18932      { 0x3b2, "xvabsdp" },
18933      { 0x3c0, "xvcpsgndp" },
18934      { 0x3c4, "xvnmsubadp" },
18935      { 0x3cc, "xvcmpgedp." },
18936      { 0x3d0, "xvcvuxddp" },
18937      { 0x3d2, "xvnabsdp" },
18938      { 0x3e4, "xvnmsubmdp" },
18939      { 0x3f0, "xvcvsxddp" },
18940      { 0x3f2, "xvnegdp" }
18941};
18942#define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all)
18943
18944
18945// ATTENTION: This search function assumes vsx_all array is sorted.
18946static Int findVSXextOpCode(UInt opcode)
18947{
18948   Int low, mid, high;
18949   low = 0;
18950   high = VSX_ALL_LEN - 1;
18951   while (low <= high) {
18952      mid = (low + high)/2;
18953      if (opcode < vsx_all[mid].opcode)
18954         high = mid - 1;
18955      else if (opcode > vsx_all[mid].opcode)
18956         low = mid + 1;
18957      else
18958         return mid;
18959   }
18960   return -1;
18961}
18962
18963
18964/* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
18965 * passed, and we then try to match it up with one of the VSX forms
18966 * below.
18967 */
18968static UInt get_VSX60_opc2(UInt opc2_full)
18969{
18970#define XX2_MASK 0x000003FE
18971#define XX3_1_MASK 0x000003FC
18972#define XX3_2_MASK 0x000001FC
18973#define XX3_3_MASK 0x0000007C
18974#define XX4_MASK 0x00000018
18975   Int ret;
18976   UInt vsxExtOpcode = 0;
18977
18978   if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
18979      vsxExtOpcode = vsx_all[ret].opcode;
18980   else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
18981      vsxExtOpcode = vsx_all[ret].opcode;
18982   else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
18983      vsxExtOpcode = vsx_all[ret].opcode;
18984   else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
18985      vsxExtOpcode = vsx_all[ret].opcode;
18986   else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
18987      vsxExtOpcode = vsx_all[ret].opcode;
18988
18989   return vsxExtOpcode;
18990}
18991
18992/*------------------------------------------------------------*/
18993/*--- Disassemble a single instruction                     ---*/
18994/*------------------------------------------------------------*/
18995
18996/* Disassemble a single instruction into IR.  The instruction
18997   is located in host memory at &guest_code[delta]. */
18998
18999static
19000DisResult disInstr_PPC_WRK (
19001             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr ),
19002             Bool         resteerCisOk,
19003             void*        callback_opaque,
19004             Long         delta64,
19005             const VexArchInfo* archinfo,
19006             const VexAbiInfo*  abiinfo,
19007             Bool         sigill_diag
19008          )
19009{
19010   UChar     opc1;
19011   UInt      opc2;
19012   DisResult dres;
19013   UInt      theInstr;
19014   IRType    ty = mode64 ? Ity_I64 : Ity_I32;
19015   Bool      allow_F  = False;
19016   Bool      allow_V  = False;
19017   Bool      allow_FX = False;
19018   Bool      allow_GX = False;
19019   Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
19020   Bool      allow_DFP = False;
19021   Bool      allow_isa_2_07 = False;
19022   UInt      hwcaps = archinfo->hwcaps;
19023   Long      delta;
19024
19025   /* What insn variants are we supporting today? */
19026   if (mode64) {
19027      allow_F  = True;
19028      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
19029      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
19030      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
19031      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
19032      allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
19033      allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
19034   } else {
19035      allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
19036      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
19037      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
19038      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
19039      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
19040      allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
19041      allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
19042   }
19043
19044   /* The running delta */
19045   delta = (Long)mkSzAddr(ty, (ULong)delta64);
19046
19047   /* Set result defaults. */
19048   dres.whatNext    = Dis_Continue;
19049   dres.len         = 0;
19050   dres.continueAt  = 0;
19051   dres.jk_StopHere = Ijk_INVALID;
19052
19053   /* At least this is simple on PPC32: insns are all 4 bytes long, and
19054      4-aligned.  So just fish the whole thing out of memory right now
19055      and have done. */
19056   theInstr = getUIntPPCendianly( &guest_code[delta] );
19057
19058   if (0) vex_printf("insn: 0x%x\n", theInstr);
19059
19060   DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
19061
19062   /* Spot "Special" instructions (see comment at top of file). */
19063   {
19064      const UChar* code = guest_code + delta;
19065      /* Spot the 16-byte preamble:
19066         32-bit mode:
19067            5400183E  rlwinm 0,0,3,0,31
19068            5400683E  rlwinm 0,0,13,0,31
19069            5400E83E  rlwinm 0,0,29,0,31
19070            5400983E  rlwinm 0,0,19,0,31
19071         64-bit mode:
19072            78001800  rotldi 0,0,3
19073            78006800  rotldi 0,0,13
19074            7800E802  rotldi 0,0,61
19075            78009802  rotldi 0,0,51
19076      */
19077      UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
19078      UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
19079      UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
19080      UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
19081      Bool is_special_preamble = False;
19082      if (getUIntPPCendianly(code+ 0) == word1 &&
19083          getUIntPPCendianly(code+ 4) == word2 &&
19084          getUIntPPCendianly(code+ 8) == word3 &&
19085          getUIntPPCendianly(code+12) == word4) {
19086         is_special_preamble = True;
19087      } else if (! mode64 &&
19088                 getUIntPPCendianly(code+ 0) == 0x54001800 &&
19089                 getUIntPPCendianly(code+ 4) == 0x54006800 &&
19090                 getUIntPPCendianly(code+ 8) == 0x5400E800 &&
19091                 getUIntPPCendianly(code+12) == 0x54009800) {
19092         static Bool reported = False;
19093         if (!reported) {
19094            vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
19095            vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
19096            reported = True;
19097         }
19098         is_special_preamble = True;
19099      }
19100      if (is_special_preamble) {
19101         /* Got a "Special" instruction preamble.  Which one is it? */
19102         if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
19103            /* %R3 = client_request ( %R4 ) */
19104            DIP("r3 = client_request ( %%r4 )\n");
19105            delta += 20;
19106            putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
19107            dres.jk_StopHere = Ijk_ClientReq;
19108            dres.whatNext    = Dis_StopHere;
19109            goto decode_success;
19110         }
19111         else
19112         if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
19113            /* %R3 = guest_NRADDR */
19114            DIP("r3 = guest_NRADDR\n");
19115            delta += 20;
19116            dres.len = 20;
19117            putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
19118            goto decode_success;
19119         }
19120         else
19121         if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
19122            delta += 20;
19123            if (host_endness == VexEndnessLE) {
19124                /*  branch-and-link-to-noredir %R12 */
19125                DIP("branch-and-link-to-noredir r12\n");
19126                putGST( PPC_GST_LR,
19127                        mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
19128                putGST( PPC_GST_CIA, getIReg(12));
19129            } else {
19130                /*  branch-and-link-to-noredir %R11 */
19131                DIP("branch-and-link-to-noredir r11\n");
19132                putGST( PPC_GST_LR,
19133                        mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
19134                putGST( PPC_GST_CIA, getIReg(11));
19135            }
19136            dres.jk_StopHere = Ijk_NoRedir;
19137            dres.whatNext    = Dis_StopHere;
19138            goto decode_success;
19139         }
19140         else
19141         if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
19142            /* %R3 = guest_NRADDR_GPR2 */
19143            DIP("r3 = guest_NRADDR_GPR2\n");
19144            delta += 20;
19145            dres.len = 20;
19146            putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
19147            goto decode_success;
19148         }
19149         else
19150         if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
19151            DIP("IR injection\n");
19152            if (host_endness == VexEndnessBE)
19153               vex_inject_ir(irsb, Iend_BE);
19154            else
19155               vex_inject_ir(irsb, Iend_LE);
19156
19157            delta += 20;
19158            dres.len = 20;
19159
19160            // Invalidate the current insn. The reason is that the IRop we're
19161            // injecting here can change. In which case the translation has to
19162            // be redone. For ease of handling, we simply invalidate all the
19163            // time.
19164
19165            stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
19166            stmt(IRStmt_Put(OFFB_CMLEN,   mkSzImm(ty, 20)));
19167
19168            putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
19169            dres.whatNext    = Dis_StopHere;
19170            dres.jk_StopHere = Ijk_InvalICache;
19171            goto decode_success;
19172         }
19173         /* We don't know what it is.  Set opc1/opc2 so decode_failure
19174            can print the insn following the Special-insn preamble. */
19175         theInstr = getUIntPPCendianly(code+16);
19176         opc1     = ifieldOPC(theInstr);
19177         opc2     = ifieldOPClo10(theInstr);
19178         goto decode_failure;
19179         /*NOTREACHED*/
19180      }
19181   }
19182
19183   opc1 = ifieldOPC(theInstr);
19184   opc2 = ifieldOPClo10(theInstr);
19185
19186   // Note: all 'reserved' bits must be cleared, else invalid
19187   switch (opc1) {
19188
19189   /* Integer Arithmetic Instructions */
19190   case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
19191   case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
19192      if (dis_int_arith( theInstr )) goto decode_success;
19193      goto decode_failure;
19194
19195   /* Integer Compare Instructions */
19196   case 0x0B: case 0x0A: // cmpi, cmpli
19197      if (dis_int_cmp( theInstr )) goto decode_success;
19198      goto decode_failure;
19199
19200   /* Integer Logical Instructions */
19201   case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
19202   case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
19203      if (dis_int_logic( theInstr )) goto decode_success;
19204      goto decode_failure;
19205
19206   /* Integer Rotate Instructions */
19207   case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
19208      if (dis_int_rot( theInstr )) goto decode_success;
19209      goto decode_failure;
19210
19211   /* 64bit Integer Rotate Instructions */
19212   case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
19213      if (!mode64) goto decode_failure;
19214      if (dis_int_rot( theInstr )) goto decode_success;
19215      goto decode_failure;
19216
19217   /* Integer Load Instructions */
19218   case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
19219   case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
19220   case 0x20: case 0x21:            // lwz,  lwzu
19221      if (dis_int_load( theInstr )) goto decode_success;
19222      goto decode_failure;
19223
19224   /* Integer Store Instructions */
19225   case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
19226   case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
19227      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19228      goto decode_failure;
19229
19230   /* Integer Load and Store Multiple Instructions */
19231   case 0x2E: case 0x2F: // lmw, stmw
19232      if (dis_int_ldst_mult( theInstr )) goto decode_success;
19233      goto decode_failure;
19234
19235   /* Branch Instructions */
19236   case 0x12: case 0x10: // b, bc
19237      if (dis_branch(theInstr, abiinfo, &dres,
19238                               resteerOkFn, callback_opaque))
19239         goto decode_success;
19240      goto decode_failure;
19241
19242   /* System Linkage Instructions */
19243   case 0x11: // sc
19244      if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
19245      goto decode_failure;
19246
19247   /* Trap Instructions */
19248   case 0x02:    // tdi
19249      if (!mode64) goto decode_failure;
19250      if (dis_trapi(theInstr, &dres)) goto decode_success;
19251      goto decode_failure;
19252
19253   case 0x03:   // twi
19254      if (dis_trapi(theInstr, &dres)) goto decode_success;
19255      goto decode_failure;
19256
19257   /* Floating Point Load Instructions */
19258   case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
19259   case 0x33:                       // lfdu
19260      if (!allow_F) goto decode_noF;
19261      if (dis_fp_load( theInstr )) goto decode_success;
19262      goto decode_failure;
19263
19264   /* Floating Point Store Instructions */
19265   case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
19266   case 0x37:                       // stfdux
19267      if (!allow_F) goto decode_noF;
19268      if (dis_fp_store( theInstr )) goto decode_success;
19269      goto decode_failure;
19270
19271      /* Floating Point Load Double Pair Instructions */
19272   case 0x39: case 0x3D:
19273      if (!allow_F) goto decode_noF;
19274      if (dis_fp_pair( theInstr )) goto decode_success;
19275      goto decode_failure;
19276
19277   /* 128-bit Integer Load */
19278   case 0x38:  // lq
19279      if (dis_int_load( theInstr )) goto decode_success;
19280      goto decode_failure;
19281
19282   /* 64bit Integer Loads */
19283   case 0x3A:  // ld, ldu, lwa
19284      if (!mode64) goto decode_failure;
19285      if (dis_int_load( theInstr )) goto decode_success;
19286      goto decode_failure;
19287
19288   case 0x3B:
19289      if (!allow_F) goto decode_noF;
19290      opc2 = ifieldOPClo10(theInstr);
19291
19292      switch (opc2) {
19293         case 0x2:    // dadd - DFP Add
19294         case 0x202:  // dsub - DFP Subtract
19295         case 0x22:   // dmul - DFP Mult
19296         case 0x222:  // ddiv - DFP Divide
19297            if (!allow_DFP) goto decode_noDFP;
19298            if (dis_dfp_arith( theInstr ))
19299               goto decode_success;
19300         case 0x82:   // dcmpo, DFP comparison ordered instruction
19301         case 0x282:  // dcmpu, DFP comparison unordered instruction
19302            if (!allow_DFP) goto decode_noDFP;
19303            if (dis_dfp_compare( theInstr ) )
19304               goto decode_success;
19305            goto decode_failure;
19306         case 0x102: // dctdp  - DFP convert to DFP long
19307         case 0x302: // drsp   - DFP round to dfp short
19308         case 0x122: // dctfix - DFP convert to fixed
19309            if (!allow_DFP) goto decode_noDFP;
19310            if (dis_dfp_fmt_conv( theInstr ))
19311               goto decode_success;
19312            goto decode_failure;
19313         case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
19314            if (!allow_VX)
19315               goto decode_failure;
19316            if (!allow_DFP) goto decode_noDFP;
19317            if (dis_dfp_fmt_conv( theInstr ))
19318               goto decode_success;
19319            goto decode_failure;
19320         case 0x2A2: // dtstsf - DFP number of significant digits
19321            if (!allow_DFP) goto decode_noDFP;
19322            if (dis_dfp_significant_digits(theInstr))
19323               goto decode_success;
19324            goto decode_failure;
19325         case 0x142: // ddedpd   DFP Decode DPD to BCD
19326         case 0x342: // denbcd   DFP Encode BCD to DPD
19327            if (!allow_DFP) goto decode_noDFP;
19328            if (dis_dfp_bcd(theInstr))
19329               goto decode_success;
19330            goto decode_failure;
19331         case 0x162:  // dxex - Extract exponent
19332         case 0x362:  // diex - Insert exponent
19333            if (!allow_DFP) goto decode_noDFP;
19334            if (dis_dfp_extract_insert( theInstr ) )
19335               goto decode_success;
19336            goto decode_failure;
19337         case 0x3CE: // fcfidus (implemented as native insn)
19338            if (!allow_VX)
19339               goto decode_noVX;
19340            if (dis_fp_round( theInstr ))
19341               goto decode_success;
19342            goto decode_failure;
19343         case 0x34E: // fcfids
19344            if (dis_fp_round( theInstr ))
19345               goto decode_success;
19346            goto decode_failure;
19347      }
19348
19349      opc2 = ifieldOPClo9( theInstr );
19350      switch (opc2) {
19351      case 0x42: // dscli, DFP shift left
19352      case 0x62: // dscri, DFP shift right
19353         if (!allow_DFP) goto decode_noDFP;
19354         if (dis_dfp_shift( theInstr ))
19355            goto decode_success;
19356         goto decode_failure;
19357      case 0xc2:  // dtstdc, DFP test data class
19358      case 0xe2:  // dtstdg, DFP test data group
19359         if (!allow_DFP) goto decode_noDFP;
19360         if (dis_dfp_class_test( theInstr ))
19361            goto decode_success;
19362         goto decode_failure;
19363      }
19364
19365      opc2 = ifieldOPClo8( theInstr );
19366      switch (opc2) {
19367      case 0x3:   // dqua  - DFP Quantize
19368      case 0x23:  // drrnd - DFP Reround
19369      case 0x43:  // dquai - DFP Quantize immediate
19370         if (!allow_DFP) goto decode_noDFP;
19371         if (dis_dfp_quantize_sig_rrnd( theInstr ) )
19372            goto decode_success;
19373         goto decode_failure;
19374      case 0xA2: // dtstex - DFP Test exponent
19375         if (!allow_DFP) goto decode_noDFP;
19376         if (dis_dfp_exponent_test( theInstr ) )
19377            goto decode_success;
19378         goto decode_failure;
19379      case 0x63: // drintx - Round to an integer value
19380      case 0xE3: // drintn - Round to an integer value
19381         if (!allow_DFP) goto decode_noDFP;
19382         if (dis_dfp_round( theInstr ) ) {
19383            goto decode_success;
19384         }
19385         goto decode_failure;
19386      default:
19387         break;  /* fall through to next opc2 check */
19388      }
19389
19390      opc2 = IFIELD(theInstr, 1, 5);
19391      switch (opc2) {
19392      /* Floating Point Arith Instructions */
19393      case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
19394      case 0x19:                       // fmuls
19395         if (dis_fp_arith(theInstr)) goto decode_success;
19396         goto decode_failure;
19397      case 0x16:                       // fsqrts
19398         if (!allow_FX) goto decode_noFX;
19399         if (dis_fp_arith(theInstr)) goto decode_success;
19400         goto decode_failure;
19401      case 0x18:                       // fres
19402         if (!allow_GX) goto decode_noGX;
19403         if (dis_fp_arith(theInstr)) goto decode_success;
19404         goto decode_failure;
19405
19406      /* Floating Point Mult-Add Instructions */
19407      case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
19408      case 0x1F:                       // fnmadds
19409         if (dis_fp_multadd(theInstr)) goto decode_success;
19410         goto decode_failure;
19411
19412      case 0x1A:                       // frsqrtes
19413         if (!allow_GX) goto decode_noGX;
19414         if (dis_fp_arith(theInstr)) goto decode_success;
19415         goto decode_failure;
19416
19417      default:
19418         goto decode_failure;
19419      }
19420      break;
19421
19422   case 0x3C: // VSX instructions (except load/store)
19423   {
19424      // All of these VSX instructions use some VMX facilities, so
19425      // if allow_V is not set, we'll skip trying to decode.
19426      if (!allow_V) goto decode_noVX;
19427
19428      UInt vsxOpc2 = get_VSX60_opc2(opc2);
19429      /* The vsxOpc2 returned is the "normalized" value, representing the
19430       * instructions secondary opcode as taken from the standard secondary
19431       * opcode field [21:30] (IBM notatition), even if the actual field
19432       * is non-standard.  These normalized values are given in the opcode
19433       * appendices of the ISA 2.06 document.
19434       */
19435
19436      switch (vsxOpc2) {
19437         case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
19438         case 0x018: case 0x148: // xxsel, xxspltw
19439            if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
19440            goto decode_failure;
19441         case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
19442         case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc
19443         case 0x2C8: case 0x2E8: // xxlnand, xxleqv
19444            if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
19445            goto decode_failure;
19446         case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
19447         case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
19448         case 0x280: case 0x2A0: // xsmaxdp, xsmindp
19449         case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
19450         case 0x034: case 0x014: // xsresp, xsrsqrtesp
19451         case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
19452         case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
19453         case 0x092: case 0x232: // xsrdpi, xsrsp
19454            if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
19455            goto decode_failure;
19456         case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
19457            if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
19458            goto decode_failure;
19459         case 0x0:   case 0x020: // xsaddsp, xssubsp
19460         case 0x080:             // xsadddp
19461         case 0x060: case 0x0E0: // xsdivsp, xsdivdp
19462         case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
19463         case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
19464         case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
19465         case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
19466         case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
19467         case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
19468         case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
19469         case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
19470         case 0x040: case 0x0C0: // xsmulsp, xsmuldp
19471         case 0x0A0:             // xssubdp
19472         case 0x016: case 0x096: // xssqrtsp,xssqrtdp
19473         case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
19474            if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
19475            goto decode_failure;
19476         case 0x180: // xvadddp
19477         case 0x1E0: // xvdivdp
19478         case 0x1C0: // xvmuldp
19479         case 0x1A0: // xvsubdp
19480         case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
19481         case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
19482         case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
19483         case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
19484         case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
19485         case 0x196: // xvsqrtdp
19486            if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
19487            goto decode_failure;
19488         case 0x100: // xvaddsp
19489         case 0x160: // xvdivsp
19490         case 0x140: // xvmulsp
19491         case 0x120: // xvsubsp
19492         case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
19493         case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
19494         case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
19495         case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
19496         case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
19497         case 0x116: // xvsqrtsp
19498            if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
19499            goto decode_failure;
19500
19501         case 0x250:             // xscvuxdsp
19502         case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
19503         case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
19504         case 0x090: // xscvdpuxws
19505            // The above VSX conversion instructions employ some ISA 2.06
19506            // floating point conversion instructions under the covers,
19507            // so if allow_VX (which means "supports ISA 2.06") is not set,
19508            // we'll skip the decode.
19509            if (!allow_VX) goto decode_noVX;
19510            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
19511            goto decode_failure;
19512
19513         case 0x2B0: // xscvdpsxds
19514         case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
19515         case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
19516         case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
19517         case 0x212: case 0x216: // xscvdpsp, xscvdpspn
19518         case 0x292: case 0x296: // xscvspdp, xscvspdpn
19519         case 0x312: // xvcvdpsp
19520         case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
19521         case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
19522         case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
19523         case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
19524         case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
19525         case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
19526            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
19527            goto decode_failure;
19528
19529         case 0x18C: case 0x38C: // xvcmpeqdp[.]
19530         case 0x10C: case 0x30C: // xvcmpeqsp[.]
19531         case 0x14C: case 0x34C: // xvcmpgesp[.]
19532         case 0x12C: case 0x32C: // xvcmpgtsp[.]
19533         case 0x1CC: case 0x3CC: // xvcmpgedp[.]
19534         case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
19535             if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
19536             goto decode_failure;
19537
19538         case 0x134:  // xvresp
19539         case 0x1B4:  // xvredp
19540         case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
19541         case 0x380: case 0x3A0: // xvmaxdp, xvmindp
19542         case 0x300: case 0x320: // xvmaxsp, xvminsp
19543         case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
19544         case 0x3B2: case 0x332: // xvabsdp, xvabssp
19545         case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
19546         case 0x192: case 0x1D6: // xvrdpi, xvrdpic
19547         case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
19548         case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
19549         case 0x112: case 0x156: // xvrspi, xvrspic
19550         case 0x172: case 0x152: // xvrspim, xvrspip
19551         case 0x132: // xvrspiz
19552            if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
19553            goto decode_failure;
19554
19555         default:
19556            goto decode_failure;
19557      }
19558      break;
19559   }
19560
19561   /* 64bit Integer Stores */
19562   case 0x3E:  // std, stdu, stq
19563      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19564      goto decode_failure;
19565
19566   case 0x3F:
19567      if (!allow_F) goto decode_noF;
19568      /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
19569         so we can simply fall through the first switch statement */
19570
19571      opc2 = IFIELD(theInstr, 1, 5);
19572      switch (opc2) {
19573      /* Floating Point Arith Instructions */
19574      case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
19575      case 0x19:                       // fmul
19576         if (dis_fp_arith(theInstr)) goto decode_success;
19577         goto decode_failure;
19578      case 0x16:                       // fsqrt
19579         if (!allow_FX) goto decode_noFX;
19580         if (dis_fp_arith(theInstr)) goto decode_success;
19581         goto decode_failure;
19582      case 0x17: case 0x1A:            // fsel, frsqrte
19583         if (!allow_GX) goto decode_noGX;
19584         if (dis_fp_arith(theInstr)) goto decode_success;
19585         goto decode_failure;
19586
19587      /* Floating Point Mult-Add Instructions */
19588      case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
19589      case 0x1F:                       // fnmadd
19590         if (dis_fp_multadd(theInstr)) goto decode_success;
19591         goto decode_failure;
19592
19593      case 0x18:                       // fre
19594         if (!allow_GX) goto decode_noGX;
19595         if (dis_fp_arith(theInstr)) goto decode_success;
19596         goto decode_failure;
19597
19598      default:
19599         break; // Fall through
19600      }
19601
19602      opc2 = IFIELD(theInstr, 1, 10);
19603      switch (opc2) {
19604      /* 128-bit DFP instructions */
19605      case 0x2:    // daddq - DFP Add
19606      case 0x202:  // dsubq - DFP Subtract
19607      case 0x22:   // dmulq - DFP Mult
19608      case 0x222:  // ddivq - DFP Divide
19609         if (!allow_DFP) goto decode_noDFP;
19610         if (dis_dfp_arithq( theInstr ))
19611            goto decode_success;
19612         goto decode_failure;
19613      case 0x162:  // dxexq - DFP Extract exponent
19614      case 0x362:  // diexq - DFP Insert exponent
19615         if (!allow_DFP) goto decode_noDFP;
19616         if (dis_dfp_extract_insertq( theInstr ))
19617            goto decode_success;
19618         goto decode_failure;
19619
19620      case 0x82:   // dcmpoq, DFP comparison ordered instruction
19621      case 0x282:  // dcmpuq, DFP comparison unordered instruction
19622         if (!allow_DFP) goto decode_noDFP;
19623         if (dis_dfp_compare( theInstr ) )
19624            goto decode_success;
19625         goto decode_failure;
19626
19627      case 0x102: // dctqpq  - DFP convert to DFP extended
19628      case 0x302: // drdpq   - DFP round to dfp Long
19629      case 0x122: // dctfixq - DFP convert to fixed quad
19630      case 0x322: // dcffixq - DFP convert from fixed quad
19631         if (!allow_DFP) goto decode_noDFP;
19632         if (dis_dfp_fmt_convq( theInstr ))
19633            goto decode_success;
19634         goto decode_failure;
19635
19636      case 0x2A2: // dtstsfq - DFP number of significant digits
19637         if (!allow_DFP) goto decode_noDFP;
19638         if (dis_dfp_significant_digits(theInstr))
19639            goto decode_success;
19640         goto decode_failure;
19641
19642      case 0x142: // ddedpdq   DFP Decode DPD to BCD
19643      case 0x342: // denbcdq   DFP Encode BCD to DPD
19644         if (!allow_DFP) goto decode_noDFP;
19645         if (dis_dfp_bcdq(theInstr))
19646            goto decode_success;
19647         goto decode_failure;
19648
19649      /* Floating Point Compare Instructions */
19650      case 0x000: // fcmpu
19651      case 0x020: // fcmpo
19652         if (dis_fp_cmp(theInstr)) goto decode_success;
19653         goto decode_failure;
19654
19655      case 0x080: // ftdiv
19656      case 0x0A0: // ftsqrt
19657         if (dis_fp_tests(theInstr)) goto decode_success;
19658         goto decode_failure;
19659
19660      /* Floating Point Rounding/Conversion Instructions */
19661      case 0x00C: // frsp
19662      case 0x00E: // fctiw
19663      case 0x00F: // fctiwz
19664      case 0x32E: // fctid
19665      case 0x32F: // fctidz
19666      case 0x34E: // fcfid
19667         if (dis_fp_round(theInstr)) goto decode_success;
19668         goto decode_failure;
19669      case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
19670      case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
19671         if (!allow_VX) goto decode_noVX;
19672         if (dis_fp_round(theInstr)) goto decode_success;
19673         goto decode_failure;
19674
19675      /* Power6 rounding stuff */
19676      case 0x1E8: // frim
19677      case 0x1C8: // frip
19678      case 0x188: // frin
19679      case 0x1A8: // friz
19680         /* A hack to check for P6 capability . . . */
19681         if ((allow_F && allow_V && allow_FX && allow_GX) &&
19682             (dis_fp_round(theInstr)))
19683            goto decode_success;
19684         goto decode_failure;
19685
19686      /* Floating Point Move Instructions */
19687      case 0x008: // fcpsgn
19688      case 0x028: // fneg
19689      case 0x048: // fmr
19690      case 0x088: // fnabs
19691      case 0x108: // fabs
19692         if (dis_fp_move( theInstr )) goto decode_success;
19693         goto decode_failure;
19694
19695      case 0x3c6: case 0x346:          // fmrgew, fmrgow
19696         if (dis_fp_merge( theInstr )) goto decode_success;
19697         goto decode_failure;
19698
19699      /* Floating Point Status/Control Register Instructions */
19700      case 0x026: // mtfsb1
19701      case 0x040: // mcrfs
19702      case 0x046: // mtfsb0
19703      case 0x086: // mtfsfi
19704      case 0x247: // mffs
19705      case 0x2C7: // mtfsf
19706         // Some of the above instructions need to know more about the
19707         // ISA level supported by the host.
19708         if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
19709         goto decode_failure;
19710
19711      default:
19712         break; // Fall through...
19713      }
19714
19715      opc2 = ifieldOPClo9( theInstr );
19716      switch (opc2) {
19717      case 0x42: // dscli, DFP shift left
19718      case 0x62: // dscri, DFP shift right
19719         if (!allow_DFP) goto decode_noDFP;
19720         if (dis_dfp_shiftq( theInstr ))
19721            goto decode_success;
19722         goto decode_failure;
19723      case 0xc2:  // dtstdc, DFP test data class
19724      case 0xe2:  // dtstdg, DFP test data group
19725         if (!allow_DFP) goto decode_noDFP;
19726         if (dis_dfp_class_test( theInstr ))
19727            goto decode_success;
19728         goto decode_failure;
19729      default:
19730         break;
19731      }
19732
19733      opc2 = ifieldOPClo8( theInstr );
19734      switch (opc2) {
19735      case 0x3:   // dquaq  - DFP Quantize Quad
19736      case 0x23:  // drrndq - DFP Reround Quad
19737      case 0x43:  // dquaiq - DFP Quantize immediate Quad
19738         if (!allow_DFP) goto decode_noDFP;
19739         if (dis_dfp_quantize_sig_rrndq( theInstr ))
19740            goto decode_success;
19741         goto decode_failure;
19742      case 0xA2: // dtstexq - DFP Test exponent Quad
19743         if (!allow_DFP) goto decode_noDFP;
19744         if (dis_dfp_exponent_test( theInstr ) )
19745            goto decode_success;
19746         goto decode_failure;
19747      case 0x63:  // drintxq - DFP Round to an integer value
19748      case 0xE3:  // drintnq - DFP Round to an integer value
19749         if (!allow_DFP) goto decode_noDFP;
19750         if (dis_dfp_roundq( theInstr ))
19751            goto decode_success;
19752         goto decode_failure;
19753
19754      default:
19755         goto decode_failure;
19756      }
19757      break;
19758
19759   case 0x13:
19760      switch (opc2) {
19761
19762      /* Condition Register Logical Instructions */
19763      case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
19764      case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
19765      case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
19766         if (dis_cond_logic( theInstr )) goto decode_success;
19767         goto decode_failure;
19768
19769      /* Branch Instructions */
19770      case 0x210: case 0x010: // bcctr, bclr
19771         if (dis_branch(theInstr, abiinfo, &dres,
19772                                  resteerOkFn, callback_opaque))
19773            goto decode_success;
19774         goto decode_failure;
19775
19776      /* Memory Synchronization Instructions */
19777      case 0x096: // isync
19778         if (dis_memsync( theInstr )) goto decode_success;
19779         goto decode_failure;
19780
19781      default:
19782         goto decode_failure;
19783      }
19784      break;
19785
19786
19787   case 0x1F:
19788
19789      /* For arith instns, bit10 is the OE flag (overflow enable) */
19790
19791      opc2 = IFIELD(theInstr, 1, 9);
19792      switch (opc2) {
19793      /* Integer Arithmetic Instructions */
19794      case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
19795      case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
19796      case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
19797      case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
19798      case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
19799      case 0x0C8: // subfze
19800         if (dis_int_arith( theInstr )) goto decode_success;
19801         goto decode_failure;
19802
19803      case 0x18B: // divweu (implemented as native insn)
19804      case 0x1AB: // divwe (implemented as native insn)
19805         if (!allow_VX) goto decode_noVX;
19806         if (dis_int_arith( theInstr )) goto decode_success;
19807         goto decode_failure;
19808
19809      /* 64bit Integer Arithmetic */
19810      case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
19811      case 0x1C9: case 0x1E9: // divdu, divd
19812         if (!mode64) goto decode_failure;
19813         if (dis_int_arith( theInstr )) goto decode_success;
19814         goto decode_failure;
19815
19816      case 0x1A9: //  divde (implemented as native insn)
19817      case 0x189: //  divdeuo (implemented as native insn)
19818         if (!allow_VX) goto decode_noVX;
19819         if (!mode64) goto decode_failure;
19820         if (dis_int_arith( theInstr )) goto decode_success;
19821         goto decode_failure;
19822
19823      case 0x1FC:                         // cmpb
19824         if (dis_int_logic( theInstr )) goto decode_success;
19825         goto decode_failure;
19826
19827      default:
19828         break;  // Fall through...
19829      }
19830
19831      /* All remaining opcodes use full 10 bits. */
19832
19833      opc2 = IFIELD(theInstr, 1, 10);
19834      switch (opc2) {
19835      /* Integer Compare Instructions  */
19836      case 0x000: case 0x020: // cmp, cmpl
19837         if (dis_int_cmp( theInstr )) goto decode_success;
19838         goto decode_failure;
19839
19840      /* Integer Logical Instructions */
19841      case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
19842      case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
19843      case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
19844      case 0x19C: case 0x13C:             // orc,  xor
19845      case 0x2DF: case 0x25F:            // mftgpr, mffgpr
19846         if (dis_int_logic( theInstr )) goto decode_success;
19847         goto decode_failure;
19848
19849      case 0x28E: case 0x2AE:             // tbegin., tend.
19850      case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
19851      case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
19852      case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
19853      if (dis_transactional_memory( theInstr,
19854                                    getUIntPPCendianly( &guest_code[delta + 4]),
19855                                    abiinfo, &dres,
19856                                    resteerOkFn, callback_opaque))
19857            goto decode_success;
19858         goto decode_failure;
19859
19860      /* 64bit Integer Logical Instructions */
19861      case 0x3DA: case 0x03A: // extsw, cntlzd
19862         if (!mode64) goto decode_failure;
19863         if (dis_int_logic( theInstr )) goto decode_success;
19864         goto decode_failure;
19865
19866         /* 64bit Integer Parity Instructions */
19867      case 0xba: // prtyd
19868         if (!mode64) goto decode_failure;
19869         if (dis_int_parity( theInstr )) goto decode_success;
19870         goto decode_failure;
19871
19872      case 0x9a: // prtyw
19873         if (dis_int_parity( theInstr )) goto decode_success;
19874         goto decode_failure;
19875
19876      /* Integer Shift Instructions */
19877      case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
19878      case 0x218:                         // srw
19879         if (dis_int_shift( theInstr )) goto decode_success;
19880         goto decode_failure;
19881
19882      /* 64bit Integer Shift Instructions */
19883      case 0x01B: case 0x31A: // sld, srad
19884      case 0x33A: case 0x33B: // sradi
19885      case 0x21B:             // srd
19886         if (!mode64) goto decode_failure;
19887         if (dis_int_shift( theInstr )) goto decode_success;
19888         goto decode_failure;
19889
19890      /* Integer Load Instructions */
19891      case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
19892      case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
19893      case 0x017: case 0x037:             // lwzx,  lwzux
19894         if (dis_int_load( theInstr )) goto decode_success;
19895         goto decode_failure;
19896
19897      /* 64bit Integer Load Instructions */
19898      case 0x035: case 0x015:             // ldux,  ldx
19899      case 0x175: case 0x155:             // lwaux, lwax
19900         if (!mode64) goto decode_failure;
19901         if (dis_int_load( theInstr )) goto decode_success;
19902         goto decode_failure;
19903
19904      /* Integer Store Instructions */
19905      case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
19906      case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
19907         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19908         goto decode_failure;
19909
19910      /* 64bit Integer Store Instructions */
19911      case 0x0B5: case 0x095: // stdux, stdx
19912         if (!mode64) goto decode_failure;
19913         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19914         goto decode_failure;
19915
19916      /* Integer Load and Store with Byte Reverse Instructions */
19917      case 0x214: case 0x294: // ldbrx, stdbrx
19918         if (!mode64) goto decode_failure;
19919         if (dis_int_ldst_rev( theInstr )) goto decode_success;
19920         goto decode_failure;
19921
19922      case 0x216: case 0x316: case 0x296:    // lwbrx, lhbrx, stwbrx
19923      case 0x396:                            // sthbrx
19924         if (dis_int_ldst_rev( theInstr )) goto decode_success;
19925         goto decode_failure;
19926
19927      /* Integer Load and Store String Instructions */
19928      case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
19929      case 0x295: {                       // stswx
19930         Bool stopHere = False;
19931         Bool ok = dis_int_ldst_str( theInstr, &stopHere );
19932         if (!ok) goto decode_failure;
19933         if (stopHere) {
19934            putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
19935            dres.jk_StopHere = Ijk_Boring;
19936            dres.whatNext    = Dis_StopHere;
19937         }
19938         goto decode_success;
19939      }
19940
19941      /* Memory Synchronization Instructions */
19942      case 0x034: case 0x074:             // lbarx, lharx
19943      case 0x2B6: case 0x2D6:             // stbcx, sthcx
19944         if (!allow_isa_2_07) goto decode_noP8;
19945         if (dis_memsync( theInstr )) goto decode_success;
19946         goto decode_failure;
19947
19948      case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
19949      case 0x256:                         // sync
19950         if (dis_memsync( theInstr )) goto decode_success;
19951         goto decode_failure;
19952
19953      /* 64bit Memory Synchronization Instructions */
19954      case 0x054: case 0x0D6: // ldarx, stdcx.
19955         if (!mode64) goto decode_failure;
19956         if (dis_memsync( theInstr )) goto decode_success;
19957         goto decode_failure;
19958
19959      case 0x114: case 0x0B6: // lqarx, stqcx.
19960         if (dis_memsync( theInstr )) goto decode_success;
19961         goto decode_failure;
19962
19963      /* Processor Control Instructions */
19964      case 0x33:  case 0x73: // mfvsrd, mfvsrwz
19965      case 0xB3:  case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
19966      case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
19967      case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
19968      case 0x220:                         // mcrxrt
19969         if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
19970         goto decode_failure;
19971
19972      /* Cache Management Instructions */
19973      case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
19974      case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
19975      case 0x3D6:                         // icbi
19976         if (dis_cache_manage( theInstr, &dres, archinfo ))
19977            goto decode_success;
19978         goto decode_failure;
19979
19980//zz       /* External Control Instructions */
19981//zz       case 0x136: case 0x1B6: // eciwx, ecowx
19982//zz          DIP("external control op => not implemented\n");
19983//zz          goto decode_failure;
19984
19985      /* Trap Instructions */
19986      case 0x004:             // tw
19987         if (dis_trap(theInstr, &dres)) goto decode_success;
19988         goto decode_failure;
19989
19990      case 0x044:             // td
19991         if (!mode64) goto decode_failure;
19992         if (dis_trap(theInstr, &dres)) goto decode_success;
19993         goto decode_failure;
19994
19995      /* Floating Point Load Instructions */
19996      case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
19997      case 0x277:                         // lfdux
19998         if (!allow_F) goto decode_noF;
19999         if (dis_fp_load( theInstr )) goto decode_success;
20000         goto decode_failure;
20001
20002      /* Floating Point Store Instructions */
20003      case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
20004      case 0x2F7:                         // stfdu, stfiwx
20005         if (!allow_F) goto decode_noF;
20006         if (dis_fp_store( theInstr )) goto decode_success;
20007         goto decode_failure;
20008      case 0x3D7:                         // stfiwx
20009         if (!allow_F) goto decode_noF;
20010         if (!allow_GX) goto decode_noGX;
20011         if (dis_fp_store( theInstr )) goto decode_success;
20012         goto decode_failure;
20013
20014         /* Floating Point Double Pair Indexed Instructions */
20015      case 0x317: // lfdpx (Power6)
20016      case 0x397: // stfdpx (Power6)
20017         if (!allow_F) goto decode_noF;
20018         if (dis_fp_pair(theInstr)) goto decode_success;
20019         goto decode_failure;
20020
20021      case 0x357:                         // lfiwax
20022         if (!allow_F) goto decode_noF;
20023         if (dis_fp_load( theInstr )) goto decode_success;
20024         goto decode_failure;
20025
20026      case 0x377:                         // lfiwzx
20027         if (!allow_F) goto decode_noF;
20028         if (dis_fp_load( theInstr )) goto decode_success;
20029         goto decode_failure;
20030
20031      /* AltiVec instructions */
20032
20033      /* AV Cache Control - Data streams */
20034      case 0x156: case 0x176: case 0x336: // dst, dstst, dss
20035         if (!allow_V) goto decode_noV;
20036         if (dis_av_datastream( theInstr )) goto decode_success;
20037         goto decode_failure;
20038
20039      /* AV Load */
20040      case 0x006: case 0x026:             // lvsl, lvsr
20041      case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
20042      case 0x067: case 0x167:             // lvx, lvxl
20043         if (!allow_V) goto decode_noV;
20044         if (dis_av_load( abiinfo, theInstr )) goto decode_success;
20045         goto decode_failure;
20046
20047      /* AV Store */
20048      case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
20049      case 0x0E7: case 0x1E7:             // stvx, stvxl
20050         if (!allow_V) goto decode_noV;
20051         if (dis_av_store( theInstr )) goto decode_success;
20052         goto decode_failure;
20053
20054      /* VSX Load */
20055      case 0x00C: // lxsiwzx
20056      case 0x04C: // lxsiwax
20057      case 0x20C: // lxsspx
20058      case 0x24C: // lxsdx
20059      case 0x34C: // lxvd2x
20060      case 0x14C: // lxvdsx
20061      case 0x30C: // lxvw4x
20062        // All of these VSX load instructions use some VMX facilities, so
20063        // if allow_V is not set, we'll skip trying to decode.
20064        if (!allow_V) goto decode_noV;
20065
20066	if (dis_vx_load( theInstr )) goto decode_success;
20067          goto decode_failure;
20068
20069      /* VSX Store */
20070      case 0x08C: // stxsiwx
20071      case 0x28C: // stxsspx
20072      case 0x2CC: // stxsdx
20073      case 0x3CC: // stxvd2x
20074      case 0x38C: // stxvw4x
20075        // All of these VSX store instructions use some VMX facilities, so
20076        // if allow_V is not set, we'll skip trying to decode.
20077        if (!allow_V) goto decode_noV;
20078
20079	if (dis_vx_store( theInstr )) goto decode_success;
20080    	  goto decode_failure;
20081
20082      /* Miscellaneous ISA 2.06 instructions */
20083      case 0x1FA: // popcntd
20084      case 0x17A: // popcntw
20085      case 0x7A:  // popcntb
20086	  if (dis_int_logic( theInstr )) goto decode_success;
20087    	  goto decode_failure;
20088
20089      case 0x0FC: // bpermd
20090         if (!mode64) goto decode_failure;
20091         if (dis_int_logic( theInstr )) goto decode_success;
20092         goto decode_failure;
20093
20094      default:
20095         /* Deal with some other cases that we would otherwise have
20096            punted on. */
20097         /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
20098         /* only decode this insn when reserved bit 0 (31 in IBM's
20099            notation) is zero */
20100         if (IFIELD(theInstr, 0, 6) == (15<<1)) {
20101            UInt rT = ifieldRegDS( theInstr );
20102            UInt rA = ifieldRegA( theInstr );
20103            UInt rB = ifieldRegB( theInstr );
20104            UInt bi = ifieldRegC( theInstr );
20105            putIReg(
20106               rT,
20107               IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
20108                           rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
20109                                   : getIReg(rA),
20110                           getIReg(rB))
20111
20112            );
20113            DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
20114            goto decode_success;
20115         }
20116         goto decode_failure;
20117      }
20118      break;
20119
20120
20121   case 0x04:
20122      /* AltiVec instructions */
20123
20124      opc2 = IFIELD(theInstr, 0, 6);
20125      switch (opc2) {
20126      /* AV Mult-Add, Mult-Sum */
20127      case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
20128      case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
20129      case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
20130         if (!allow_V) goto decode_noV;
20131         if (dis_av_multarith( theInstr )) goto decode_success;
20132         goto decode_failure;
20133
20134      /* AV Permutations */
20135      case 0x2A:                       // vsel
20136      case 0x2B:                       // vperm
20137      case 0x2C:                       // vsldoi
20138         if (!allow_V) goto decode_noV;
20139         if (dis_av_permute( theInstr )) goto decode_success;
20140         goto decode_failure;
20141
20142      case 0x2D:                       // vpermxor
20143         if (!allow_isa_2_07) goto decode_noP8;
20144         if (dis_av_permute( theInstr )) goto decode_success;
20145         goto decode_failure;
20146
20147      /* AV Floating Point Mult-Add/Sub */
20148      case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
20149         if (!allow_V) goto decode_noV;
20150         if (dis_av_fp_arith( theInstr )) goto decode_success;
20151         goto decode_failure;
20152
20153      case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
20154      case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
20155         if (!allow_V) goto decode_noV;
20156         if (dis_av_quad( theInstr)) goto decode_success;
20157         goto decode_failure;
20158
20159      default:
20160         break;  // Fall through...
20161      }
20162
20163      opc2 = IFIELD(theInstr, 0, 9);
20164      switch (opc2) {
20165      /* BCD arithmetic */
20166      case 0x1: case 0x41:             // bcdadd, bcdsub
20167         if (!allow_isa_2_07) goto decode_noP8;
20168         if (dis_av_bcd( theInstr )) goto decode_success;
20169         goto decode_failure;
20170
20171      default:
20172         break;  // Fall through...
20173      }
20174
20175      opc2 = IFIELD(theInstr, 0, 11);
20176      switch (opc2) {
20177      /* AV Arithmetic */
20178      case 0x180:                         // vaddcuw
20179      case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
20180      case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
20181      case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
20182      case 0x580:                         // vsubcuw
20183      case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
20184      case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
20185      case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
20186      case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
20187      case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
20188      case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
20189      case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
20190      case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
20191      case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
20192      case 0x008: case 0x048:             // vmuloub, vmulouh
20193      case 0x108: case 0x148:             // vmulosb, vmulosh
20194      case 0x208: case 0x248:             // vmuleub, vmuleuh
20195      case 0x308: case 0x348:             // vmulesb, vmulesh
20196      case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
20197      case 0x688: case 0x788:             // vsum2sws, vsumsws
20198         if (!allow_V) goto decode_noV;
20199         if (dis_av_arith( theInstr )) goto decode_success;
20200         goto decode_failure;
20201
20202      case 0x088: case 0x089:             // vmulouw, vmuluwm
20203      case 0x0C0: case 0x0C2:             // vaddudm, vmaxud
20204      case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
20205      case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
20206      case 0x4C0:                         // vsubudm
20207         if (!allow_isa_2_07) goto decode_noP8;
20208         if (dis_av_arith( theInstr )) goto decode_success;
20209         goto decode_failure;
20210
20211      /* AV Polynomial Vector Multiply Add */
20212      case 0x408: case 0x448:            // vpmsumb, vpmsumd
20213      case 0x488: case 0x4C8:            // vpmsumw, vpmsumh
20214         if (!allow_isa_2_07) goto decode_noP8;
20215         if (dis_av_polymultarith( theInstr )) goto decode_success;
20216         goto decode_failure;
20217
20218      /* AV Rotate, Shift */
20219      case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
20220      case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
20221      case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
20222      case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
20223      case 0x1C4: case 0x2C4:             // vsl, vsr
20224      case 0x40C: case 0x44C:             // vslo, vsro
20225         if (!allow_V) goto decode_noV;
20226         if (dis_av_shift( theInstr )) goto decode_success;
20227         goto decode_failure;
20228
20229      case 0x0C4:                         // vrld
20230      case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
20231          if (!allow_isa_2_07) goto decode_noP8;
20232          if (dis_av_shift( theInstr )) goto decode_success;
20233          goto decode_failure;
20234
20235      /* AV Logic */
20236      case 0x404: case 0x444: case 0x484: // vand, vandc, vor
20237      case 0x4C4: case 0x504:             // vxor, vnor
20238         if (!allow_V) goto decode_noV;
20239         if (dis_av_logic( theInstr )) goto decode_success;
20240         goto decode_failure;
20241
20242      case 0x544:                         // vorc
20243      case 0x584: case 0x684:             // vnand, veqv
20244         if (!allow_isa_2_07) goto decode_noP8;
20245         if (dis_av_logic( theInstr )) goto decode_success;
20246         goto decode_failure;
20247
20248      /* AV Processor Control */
20249      case 0x604: case 0x644:             // mfvscr, mtvscr
20250         if (!allow_V) goto decode_noV;
20251         if (dis_av_procctl( theInstr )) goto decode_success;
20252         goto decode_failure;
20253
20254      /* AV Floating Point Arithmetic */
20255      case 0x00A: case 0x04A:             // vaddfp, vsubfp
20256      case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
20257      case 0x1CA:                         // vlogefp
20258      case 0x40A: case 0x44A:             // vmaxfp, vminfp
20259         if (!allow_V) goto decode_noV;
20260         if (dis_av_fp_arith( theInstr )) goto decode_success;
20261         goto decode_failure;
20262
20263      /* AV Floating Point Round/Convert */
20264      case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
20265      case 0x2CA:                         // vrfim
20266      case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
20267      case 0x3CA:                         // vctsxs
20268         if (!allow_V) goto decode_noV;
20269         if (dis_av_fp_convert( theInstr )) goto decode_success;
20270         goto decode_failure;
20271
20272      /* AV Merge, Splat */
20273      case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
20274      case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
20275      case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
20276      case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
20277         if (!allow_V) goto decode_noV;
20278         if (dis_av_permute( theInstr )) goto decode_success;
20279         goto decode_failure;
20280
20281      case 0x68C: case 0x78C:             // vmrgow, vmrgew
20282          if (!allow_isa_2_07) goto decode_noP8;
20283          if (dis_av_permute( theInstr )) goto decode_success;
20284          goto decode_failure;
20285
20286      /* AV Pack, Unpack */
20287      case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
20288      case 0x0CE:                         // vpkuwus
20289      case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
20290      case 0x1CE:                         // vpkswss
20291      case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
20292      case 0x2CE:                         // vupklsh
20293      case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
20294          if (!allow_V) goto decode_noV;
20295          if (dis_av_pack( theInstr )) goto decode_success;
20296          goto decode_failure;
20297
20298      case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
20299      case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
20300         if (!allow_isa_2_07) goto decode_noP8;
20301         if (dis_av_pack( theInstr )) goto decode_success;
20302         goto decode_failure;
20303
20304      case 0x508: case 0x509:             // vcipher, vcipherlast
20305      case 0x548: case 0x549:             // vncipher, vncipherlast
20306      case 0x5C8:                         // vsbox
20307         if (!allow_isa_2_07) goto decode_noP8;
20308         if (dis_av_cipher( theInstr )) goto decode_success;
20309         goto decode_failure;
20310
20311      case 0x6C2: case 0x682:             // vshasigmaw, vshasigmad
20312         if (!allow_isa_2_07) goto decode_noP8;
20313         if (dis_av_hash( theInstr )) goto decode_success;
20314         goto decode_failure;
20315
20316      case 0x702: case 0x742:             // vclzb, vclzh
20317      case 0x782: case 0x7c2:             // vclzw, vclzd
20318         if (!allow_isa_2_07) goto decode_noP8;
20319         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
20320         goto decode_failure;
20321
20322      case 0x703: case 0x743:             // vpopcntb, vpopcnth
20323      case 0x783: case 0x7c3:             // vpopcntw, vpopcntd
20324         if (!allow_isa_2_07) goto decode_noP8;
20325         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
20326         goto decode_failure;
20327
20328      case 0x50c:                         // vgbbd
20329         if (!allow_isa_2_07) goto decode_noP8;
20330         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
20331         goto decode_failure;
20332
20333      case 0x140: case 0x100:             // vaddcuq, vadduqm
20334      case 0x540: case 0x500:             // vsubcuq, vsubuqm
20335      case 0x54C:                         // vbpermq
20336         if (!allow_V) goto decode_noV;
20337         if (dis_av_quad( theInstr)) goto decode_success;
20338         goto decode_failure;
20339
20340      default:
20341         break;  // Fall through...
20342      }
20343
20344      opc2 = IFIELD(theInstr, 0, 10);
20345      switch (opc2) {
20346
20347      /* AV Compare */
20348      case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
20349      case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
20350      case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
20351         if (!allow_V) goto decode_noV;
20352         if (dis_av_cmp( theInstr )) goto decode_success;
20353         goto decode_failure;
20354
20355      case 0x0C7:                         // vcmpequd
20356      case 0x2C7:                         // vcmpgtud
20357      case 0x3C7:                         // vcmpgtsd
20358          if (!allow_isa_2_07) goto decode_noP8;
20359          if (dis_av_cmp( theInstr )) goto decode_success;
20360          goto decode_failure;
20361
20362      /* AV Floating Point Compare */
20363      case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
20364      case 0x3C6:                         // vcmpbfp
20365         if (!allow_V) goto decode_noV;
20366         if (dis_av_fp_cmp( theInstr )) goto decode_success;
20367         goto decode_failure;
20368
20369      default:
20370         goto decode_failure;
20371      }
20372      break;
20373
20374   default:
20375      goto decode_failure;
20376
20377   decode_noF:
20378      vassert(!allow_F);
20379      vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
20380		 "can't be handled by Valgrind on this host.  This instruction\n"
20381		 "requires a host that supports Floating Point instructions.\n",
20382		 theInstr);
20383      goto not_supported;
20384   decode_noV:
20385      vassert(!allow_V);
20386      vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
20387		 "that can't be handled by Valgrind.  If this instruction is an\n"
20388		 "Altivec instruction, Valgrind must be run on a host that supports"
20389		 "AltiVec instructions.  If the application was compiled for e500, then\n"
20390		 "unfortunately Valgrind does not yet support e500 instructions.\n",
20391		 theInstr);
20392      goto not_supported;
20393   decode_noVX:
20394      vassert(!allow_VX);
20395      vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
20396		 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
20397		 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
20398		 theInstr);
20399      goto not_supported;
20400   decode_noFX:
20401      vassert(!allow_FX);
20402      vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
20403		 "that can't be handled by Valgrind on this host. This instruction\n"
20404		 "requires a host that supports the General Purpose-Optional instructions.\n",
20405		 theInstr);
20406      goto not_supported;
20407   decode_noGX:
20408      vassert(!allow_GX);
20409      vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
20410		 "that can't be handled by Valgrind on this host. This instruction\n"
20411		 "requires a host that supports the Graphic-Optional instructions.\n",
20412		 theInstr);
20413      goto not_supported;
20414   decode_noDFP:
20415      vassert(!allow_DFP);
20416      vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
20417		 "that can't be handled by Valgrind on this host.  This instruction\n"
20418		 "requires a host that supports DFP instructions.\n",
20419		 theInstr);
20420      goto not_supported;
20421   decode_noP8:
20422      vassert(!allow_isa_2_07);
20423      vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
20424		 "by Valgrind on this host.  This instruction requires a host that\n"
20425		 "supports Power 8 instructions.\n",
20426		 theInstr);
20427      goto not_supported;
20428
20429
20430   decode_failure:
20431   /* All decode failures end up here. */
20432   opc2 = (theInstr) & 0x7FF;
20433   if (sigill_diag) {
20434      vex_printf("disInstr(ppc): unhandled instruction: "
20435                 "0x%x\n", theInstr);
20436      vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
20437                 opc1, opc1, opc2, opc2);
20438   }
20439
20440   not_supported:
20441   /* Tell the dispatcher that this insn cannot be decoded, and so has
20442      not been executed, and (is currently) the next to be executed.
20443      CIA should be up-to-date since it made so at the start of each
20444      insn, but nevertheless be paranoid and update it again right
20445      now. */
20446   putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
20447   dres.len         = 0;
20448   dres.whatNext    = Dis_StopHere;
20449   dres.jk_StopHere = Ijk_NoDecode;
20450   dres.continueAt  = 0;
20451   return dres;
20452   } /* switch (opc) for the main (primary) opcode switch. */
20453
20454  decode_success:
20455   /* All decode successes end up here. */
20456   switch (dres.whatNext) {
20457      case Dis_Continue:
20458         putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
20459         break;
20460      case Dis_ResteerU:
20461      case Dis_ResteerC:
20462         putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
20463         break;
20464      case Dis_StopHere:
20465         break;
20466      default:
20467         vassert(0);
20468   }
20469   DIP("\n");
20470
20471   if (dres.len == 0) {
20472      dres.len = 4;
20473   } else {
20474      vassert(dres.len == 20);
20475   }
20476   return dres;
20477}
20478
20479#undef DIP
20480#undef DIS
20481
20482
20483/*------------------------------------------------------------*/
20484/*--- Top-level fn                                         ---*/
20485/*------------------------------------------------------------*/
20486
20487/* Disassemble a single instruction into IR.  The instruction
20488   is located in host memory at &guest_code[delta]. */
20489
20490DisResult disInstr_PPC ( IRSB*        irsb_IN,
20491                         Bool         (*resteerOkFn) ( void*, Addr ),
20492                         Bool         resteerCisOk,
20493                         void*        callback_opaque,
20494                         const UChar* guest_code_IN,
20495                         Long         delta,
20496                         Addr         guest_IP,
20497                         VexArch      guest_arch,
20498                         const VexArchInfo* archinfo,
20499                         const VexAbiInfo*  abiinfo,
20500                         VexEndness   host_endness_IN,
20501                         Bool         sigill_diag_IN )
20502{
20503   IRType     ty;
20504   DisResult  dres;
20505   UInt       mask32, mask64;
20506   UInt hwcaps_guest = archinfo->hwcaps;
20507
20508   vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
20509
20510   /* global -- ick */
20511   mode64 = guest_arch == VexArchPPC64;
20512   ty = mode64 ? Ity_I64 : Ity_I32;
20513   if (!mode64 && (host_endness_IN == VexEndnessLE)) {
20514      vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
20515      dres.len         = 0;
20516      dres.whatNext    = Dis_StopHere;
20517      dres.jk_StopHere = Ijk_NoDecode;
20518      dres.continueAt   = 0;
20519      return dres;
20520   }
20521
20522   /* do some sanity checks */
20523   mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
20524            | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
20525            | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
20526
20527   mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
20528            | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
20529            | VEX_HWCAPS_PPC64_ISA2_07;
20530
20531   if (mode64) {
20532      vassert((hwcaps_guest & mask32) == 0);
20533   } else {
20534      vassert((hwcaps_guest & mask64) == 0);
20535   }
20536
20537   /* Set globals (see top of this file) */
20538   guest_code           = guest_code_IN;
20539   irsb                 = irsb_IN;
20540   host_endness         = host_endness_IN;
20541
20542   guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
20543   guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
20544
20545   dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
20546                             delta, archinfo, abiinfo, sigill_diag_IN);
20547
20548   return dres;
20549}
20550
20551
20552/*------------------------------------------------------------*/
20553/*--- Unused stuff                                         ---*/
20554/*------------------------------------------------------------*/
20555
20556///* A potentially more memcheck-friendly implementation of Clz32, with
20557//   the boundary case Clz32(0) = 32, which is what ppc requires. */
20558//
20559//static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
20560//{
20561//   /* Welcome ... to SSA R Us. */
20562//   IRTemp n1  = newTemp(Ity_I32);
20563//   IRTemp n2  = newTemp(Ity_I32);
20564//   IRTemp n3  = newTemp(Ity_I32);
20565//   IRTemp n4  = newTemp(Ity_I32);
20566//   IRTemp n5  = newTemp(Ity_I32);
20567//   IRTemp n6  = newTemp(Ity_I32);
20568//   IRTemp n7  = newTemp(Ity_I32);
20569//   IRTemp n8  = newTemp(Ity_I32);
20570//   IRTemp n9  = newTemp(Ity_I32);
20571//   IRTemp n10 = newTemp(Ity_I32);
20572//   IRTemp n11 = newTemp(Ity_I32);
20573//   IRTemp n12 = newTemp(Ity_I32);
20574//
20575//   /* First, propagate the most significant 1-bit into all lower
20576//      positions in the word. */
20577//   /* unsigned int clz ( unsigned int n )
20578//      {
20579//         n |= (n >> 1);
20580//         n |= (n >> 2);
20581//         n |= (n >> 4);
20582//         n |= (n >> 8);
20583//         n |= (n >> 16);
20584//         return bitcount(~n);
20585//      }
20586//   */
20587//   assign(n1, mkexpr(arg));
20588//   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
20589//   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
20590//   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
20591//   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
20592//   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
20593//   /* This gives a word of the form 0---01---1.  Now invert it, giving
20594//      a word of the form 1---10---0, then do a population-count idiom
20595//      (to count the 1s, which is the number of leading zeroes, or 32
20596//      if the original word was 0. */
20597//   assign(n7, unop(Iop_Not32, mkexpr(n6)));
20598//
20599//   /* unsigned int bitcount ( unsigned int n )
20600//      {
20601//         n = n - ((n >> 1) & 0x55555555);
20602//         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
20603//         n = (n + (n >> 4)) & 0x0F0F0F0F;
20604//         n = n + (n >> 8);
20605//         n = (n + (n >> 16)) & 0x3F;
20606//         return n;
20607//      }
20608//   */
20609//   assign(n8,
20610//          binop(Iop_Sub32,
20611//                mkexpr(n7),
20612//                binop(Iop_And32,
20613//                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
20614//                      mkU32(0x55555555))));
20615//   assign(n9,
20616//          binop(Iop_Add32,
20617//                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
20618//                binop(Iop_And32,
20619//                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
20620//                      mkU32(0x33333333))));
20621//   assign(n10,
20622//          binop(Iop_And32,
20623//                binop(Iop_Add32,
20624//                      mkexpr(n9),
20625//                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
20626//                mkU32(0x0F0F0F0F)));
20627//   assign(n11,
20628//          binop(Iop_Add32,
20629//                mkexpr(n10),
20630//                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
20631//   assign(n12,
20632//          binop(Iop_Add32,
20633//                mkexpr(n11),
20634//                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
20635//   return
20636//      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
20637//}
20638
20639/*--------------------------------------------------------------------*/
20640/*--- end                                         guest_ppc_toIR.c ---*/
20641/*--------------------------------------------------------------------*/
20642