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-2017 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/* The OV32 and CA32 bits were added with ISA3.0 */
243static Bool OV32_CA32_supported = False;
244
245#define SIGN_BIT  0x8000000000000000ULL
246#define SIGN_MASK 0x7fffffffffffffffULL
247#define SIGN_BIT32  0x80000000
248#define SIGN_MASK32 0x7fffffff
249
250
251/*------------------------------------------------------------*/
252/*--- Debugging output                                     ---*/
253/*------------------------------------------------------------*/
254
255#define DIP(format, args...)           \
256   if (vex_traceflags & VEX_TRACE_FE)  \
257      vex_printf(format, ## args)
258
259#define DIS(buf, format, args...)      \
260   if (vex_traceflags & VEX_TRACE_FE)  \
261      vex_sprintf(buf, format, ## args)
262
263
264/*------------------------------------------------------------*/
265/*--- Offsets of various parts of the ppc32/64 guest state ---*/
266/*------------------------------------------------------------*/
267
268#define offsetofPPCGuestState(_x) \
269   (mode64 ? offsetof(VexGuestPPC64State, _x) : \
270             offsetof(VexGuestPPC32State, _x))
271
272#define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
273#define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
274#define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
275#define OFFB_LR          offsetofPPCGuestState(guest_LR)
276#define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
277#define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
278#define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
279#define OFFB_XER_OV32    offsetofPPCGuestState(guest_XER_OV32)
280#define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
281#define OFFB_XER_CA32    offsetofPPCGuestState(guest_XER_CA32)
282#define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
283#define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
284#define OFFB_DFPROUND    offsetofPPCGuestState(guest_DFPROUND)
285#define OFFB_C_FPCC      offsetofPPCGuestState(guest_C_FPCC)
286#define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
287#define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
288#define OFFB_EMNOTE      offsetofPPCGuestState(guest_EMNOTE)
289#define OFFB_CMSTART     offsetofPPCGuestState(guest_CMSTART)
290#define OFFB_CMLEN       offsetofPPCGuestState(guest_CMLEN)
291#define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
292#define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
293#define OFFB_TFHAR       offsetofPPCGuestState(guest_TFHAR)
294#define OFFB_TEXASR      offsetofPPCGuestState(guest_TEXASR)
295#define OFFB_TEXASRU     offsetofPPCGuestState(guest_TEXASRU)
296#define OFFB_TFIAR       offsetofPPCGuestState(guest_TFIAR)
297#define OFFB_PPR         offsetofPPCGuestState(guest_PPR)
298#define OFFB_PSPB        offsetofPPCGuestState(guest_PSPB)
299
300
301/*------------------------------------------------------------*/
302/*--- Extract instruction fields                          --- */
303/*------------------------------------------------------------*/
304
305/* Extract field from insn, given idx (zero = lsb) and field length */
306#define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
307
308/* Extract primary opcode, instr[31:26] */
309static UChar ifieldOPC( UInt instr ) {
310   return toUChar( IFIELD( instr, 26, 6 ) );
311}
312
313/* Extract 10-bit secondary opcode, instr[10:1] */
314static UInt ifieldOPClo10 ( UInt instr) {
315   return IFIELD( instr, 1, 10 );
316}
317
318/* Extract 9-bit secondary opcode, instr[9:1] */
319static UInt ifieldOPClo9 ( UInt instr) {
320   return IFIELD( instr, 1, 9 );
321}
322
323/* Extract 8-bit secondary opcode, instr[8:1] */
324static UInt ifieldOPClo8 ( UInt instr) {
325   return IFIELD( instr, 1, 8 );
326}
327
328/* Extract 5-bit secondary opcode, instr[5:1] */
329static UInt ifieldOPClo5 ( UInt instr) {
330   return IFIELD( instr, 1, 5 );
331}
332
333/* Extract 2-bit secondary opcode, instr[1:0] */
334static UInt ifieldOPC0o2 ( UInt instr) {
335   return IFIELD( instr, 0, 2 );
336}
337
338/* Extract RD (destination register) field, instr[25:21] */
339static UChar ifieldRegDS( UInt instr ) {
340   return toUChar( IFIELD( instr, 21, 5 ) );
341}
342
343/* Extract XT (destination register) field, instr[0,25:21] */
344static UChar ifieldRegXT ( UInt instr )
345{
346  UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
347  UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
348  return (upper_bit << 5) | lower_bits;
349}
350
351/* Extract XS (store source register) field, instr[0,25:21] */
352static inline UChar ifieldRegXS ( UInt instr )
353{
354  return ifieldRegXT ( instr );
355}
356
357/* Extract RA (1st source register) field, instr[20:16] */
358static UChar ifieldRegA ( UInt instr ) {
359   return toUChar( IFIELD( instr, 16, 5 ) );
360}
361
362/* Extract XA (1st source register) field, instr[2,20:16] */
363static UChar ifieldRegXA ( UInt instr )
364{
365  UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
366  UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
367  return (upper_bit << 5) | lower_bits;
368}
369
370/* Extract RB (2nd source register) field, instr[15:11] */
371static UChar ifieldRegB ( UInt instr ) {
372   return toUChar( IFIELD( instr, 11, 5 ) );
373}
374
375/* Extract XB (2nd source register) field, instr[1,15:11] */
376static UChar ifieldRegXB ( UInt instr )
377{
378  UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
379  UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
380  return (upper_bit << 5) | lower_bits;
381}
382
383/* Extract RC (3rd source register) field, instr[10:6] */
384static UChar ifieldRegC ( UInt instr ) {
385   return toUChar( IFIELD( instr, 6, 5 ) );
386}
387
388/* Extract XC (3rd source register) field, instr[3,10:6] */
389static UChar ifieldRegXC ( UInt instr )
390{
391  UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
392  UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
393  return (upper_bit << 5) | lower_bits;
394}
395
396/* Extract bit 10, instr[10] */
397static UChar ifieldBIT10 ( UInt instr ) {
398   return toUChar( IFIELD( instr, 10, 1 ) );
399}
400
401/* Extract 2nd lowest bit, instr[1] */
402static UChar ifieldBIT1 ( UInt instr ) {
403   return toUChar( IFIELD( instr, 1, 1 ) );
404}
405
406/* Extract lowest bit, instr[0] */
407static UChar ifieldBIT0 ( UInt instr ) {
408   return toUChar( instr & 0x1 );
409}
410
411/* Extract unsigned bottom half, instr[15:0] */
412static UInt ifieldUIMM16 ( UInt instr ) {
413   return instr & 0xFFFF;
414}
415
416/* Extract unsigned bottom 26 bits, instr[25:0] */
417static UInt ifieldUIMM26 ( UInt instr ) {
418   return instr & 0x3FFFFFF;
419}
420
421/* Extract DM field, instr[9:8] */
422static UChar ifieldDM ( UInt instr ) {
423   return toUChar( IFIELD( instr, 8, 2 ) );
424}
425
426/* Extract SHW field, instr[9:8] */
427static inline UChar ifieldSHW ( UInt instr )
428{
429  return ifieldDM ( instr );
430}
431
432/*------------------------------------------------------------*/
433/*--- Guest-state identifiers                              ---*/
434/*------------------------------------------------------------*/
435
436typedef enum {
437    PPC_GST_CIA,    // Current Instruction Address
438    PPC_GST_LR,     // Link Register
439    PPC_GST_CTR,    // Count Register
440    PPC_GST_XER,    // Overflow, carry flags, byte count
441    PPC_GST_CR,     // Condition Register
442    PPC_GST_FPSCR,  // Floating Point Status/Control Register
443    PPC_GST_VRSAVE, // Vector Save/Restore Register
444    PPC_GST_VSCR,   // Vector Status and Control Register
445    PPC_GST_EMWARN, // Emulation warnings
446    PPC_GST_CMSTART,// For icbi: start of area to invalidate
447    PPC_GST_CMLEN,  // For icbi: length of area to invalidate
448    PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
449    PPC_GST_SPRG3_RO, // SPRG3
450    PPC_GST_TFHAR,  // Transactional Failure Handler Address Register
451    PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
452    PPC_GST_TEXASR, // Transactional EXception And Summary Register
453    PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper
454    PPC_GST_PPR,     // Program Priority register
455    PPC_GST_PPR32,   // Upper 32-bits of Program Priority register
456    PPC_GST_PSPB,    /* Problem State Priority Boost register, Note, the
457                      * register is initialized to a non-zero value.  Currently
458                      * Valgrind is not supporting the register value to
459                      * automatically decrement. Could be added later if
460                      * needed.
461                      */
462    PPC_GST_MAX
463} PPC_GST;
464
465#define MASK_FPSCR_RN     0x3ULL         // Binary floating point rounding mode
466#define MASK_FPSCR_DRN    0x700000000ULL // Decimal floating point rounding mode
467#define MASK_FPSCR_C_FPCC 0x1F000ULL     // Floating-Point Condition code FPCC
468
469#define MASK_VSCR_VALID 0x00010001
470
471
472/*------------------------------------------------------------*/
473/*---  FP Helpers                                          ---*/
474/*------------------------------------------------------------*/
475
476/* Produce the 32-bit pattern corresponding to the supplied
477   float. */
478static UInt float_to_bits ( Float f )
479{
480   union { UInt i; Float f; } u;
481   vassert(4 == sizeof(UInt));
482   vassert(4 == sizeof(Float));
483   vassert(4 == sizeof(u));
484   u.f = f;
485   return u.i;
486}
487
488
489/*------------------------------------------------------------*/
490/*--- Misc Helpers                                         ---*/
491/*------------------------------------------------------------*/
492
493/* Generate mask with 1's from 'begin' through 'end',
494   wrapping if begin > end.
495   begin->end works from right to left, 0=lsb
496*/
497static UInt MASK32( UInt begin, UInt end )
498{
499   UInt m1, m2, mask;
500   vassert(begin < 32);
501   vassert(end < 32);
502   m1   = ((UInt)(-1)) << begin;
503   m2   = ((UInt)(-1)) << end << 1;
504   mask = m1 ^ m2;
505   if (begin > end) mask = ~mask;  // wrap mask
506   return mask;
507}
508
509static ULong MASK64( UInt begin, UInt end )
510{
511   ULong m1, m2, mask;
512   vassert(begin < 64);
513   vassert(end < 64);
514   m1   = ((ULong)(-1)) << begin;
515   m2   = ((ULong)(-1)) << end << 1;
516   mask = m1 ^ m2;
517   if (begin > end) mask = ~mask;  // wrap mask
518   return mask;
519}
520
521static Addr64 nextInsnAddr( void )
522{
523   return guest_CIA_curr_instr + 4;
524}
525
526
527/*------------------------------------------------------------*/
528/*--- Helper bits and pieces for deconstructing the        ---*/
529/*--- ppc32/64 insn stream.                                ---*/
530/*------------------------------------------------------------*/
531
532/* Add a statement to the list held by "irsb". */
533static void stmt ( IRStmt* st )
534{
535   addStmtToIRSB( irsb, st );
536}
537
538/* Generate a new temporary of the given type. */
539static IRTemp newTemp ( IRType ty )
540{
541   vassert(isPlausibleIRType(ty));
542   return newIRTemp( irsb->tyenv, ty );
543}
544
545/* Various simple conversions */
546
547static UChar extend_s_5to8 ( UChar x )
548{
549   return toUChar((((Int)x) << 27) >> 27);
550}
551
552static UInt extend_s_8to32( UChar x )
553{
554   return (UInt)((((Int)x) << 24) >> 24);
555}
556
557static UInt extend_s_16to32 ( UInt x )
558{
559   return (UInt)((((Int)x) << 16) >> 16);
560}
561
562static ULong extend_s_16to64 ( UInt x )
563{
564   return (ULong)((((Long)x) << 48) >> 48);
565}
566
567static ULong extend_s_26to64 ( UInt x )
568{
569   return (ULong)((((Long)x) << 38) >> 38);
570}
571
572static ULong extend_s_32to64 ( UInt x )
573{
574   return (ULong)((((Long)x) << 32) >> 32);
575}
576
577/* Do a proper-endian load of a 32-bit word, regardless of the endianness
578   of the underlying host. */
579static UInt getUIntPPCendianly ( const UChar* p )
580{
581   UInt w = 0;
582   if (host_endness == VexEndnessBE) {
583       w = (w << 8) | p[0];
584       w = (w << 8) | p[1];
585       w = (w << 8) | p[2];
586       w = (w << 8) | p[3];
587   } else {
588       w = (w << 8) | p[3];
589       w = (w << 8) | p[2];
590       w = (w << 8) | p[1];
591       w = (w << 8) | p[0];
592   }
593   return w;
594}
595
596
597/*------------------------------------------------------------*/
598/*--- Helpers for constructing IR.                         ---*/
599/*------------------------------------------------------------*/
600
601static void assign ( IRTemp dst, IRExpr* e )
602{
603   stmt( IRStmt_WrTmp(dst, e) );
604}
605
606/* This generates a normal (non store-conditional) store. */
607static void store ( IRExpr* addr, IRExpr* data )
608{
609   IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
610   vassert(tyA == Ity_I32 || tyA == Ity_I64);
611
612   if (host_endness == VexEndnessBE)
613      stmt( IRStmt_Store(Iend_BE, addr, data) );
614   else
615      stmt( IRStmt_Store(Iend_LE, addr, data) );
616}
617
618static IRExpr* unop ( IROp op, IRExpr* a )
619{
620   return IRExpr_Unop(op, a);
621}
622
623static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
624{
625   return IRExpr_Binop(op, a1, a2);
626}
627
628static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
629{
630   return IRExpr_Triop(op, a1, a2, a3);
631}
632
633static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
634                              IRExpr* a3, IRExpr* a4 )
635{
636   return IRExpr_Qop(op, a1, a2, a3, a4);
637}
638
639static IRExpr* mkexpr ( IRTemp tmp )
640{
641   return IRExpr_RdTmp(tmp);
642}
643
644#define mkU1(_n)  IRExpr_Const(IRConst_U1(_n))
645
646static IRExpr* mkU8 ( UChar i )
647{
648   return IRExpr_Const(IRConst_U8(i));
649}
650
651static IRExpr* mkU16 ( UInt i )
652{
653   return IRExpr_Const(IRConst_U16(i));
654}
655
656static IRExpr* mkU32 ( UInt i )
657{
658   return IRExpr_Const(IRConst_U32(i));
659}
660
661static IRExpr* mkU64 ( ULong i )
662{
663   return IRExpr_Const(IRConst_U64(i));
664}
665
666static IRExpr* mkV128 ( UShort i )
667{
668   vassert(i == 0 || i == 0xffff);
669   return IRExpr_Const(IRConst_V128(i));
670}
671
672/* This generates a normal (non load-linked) load. */
673static IRExpr* load ( IRType ty, IRExpr* addr )
674{
675   if (host_endness == VexEndnessBE)
676      return IRExpr_Load(Iend_BE, ty, addr);
677   else
678      return IRExpr_Load(Iend_LE, ty, addr);
679}
680
681static IRStmt* stmt_load ( IRTemp result,
682                           IRExpr* addr, IRExpr* storedata )
683{
684   if (host_endness == VexEndnessBE)
685      return IRStmt_LLSC(Iend_BE, result, addr, storedata);
686   else
687      return IRStmt_LLSC(Iend_LE, result, addr, storedata);
688}
689
690static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
691{
692   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
693   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
694   return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
695                                          unop(Iop_1Uto32, arg2)));
696}
697
698static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
699{
700   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
701   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
702   return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
703                                           unop(Iop_1Uto32, arg2)));
704}
705
706static inline IRExpr* mkXOr4_32( IRTemp t0, IRTemp t1, IRTemp t2,
707                                 IRTemp t3 )
708{
709   return binop( Iop_Xor32,
710                 binop( Iop_Xor32, mkexpr( t0 ), mkexpr( t1 ) ),
711                 binop( Iop_Xor32, mkexpr( t2 ), mkexpr( t3 ) ) );
712}
713
714static inline IRExpr* mkOr3_V128( IRTemp t0, IRTemp t1, IRTemp t2 )
715{
716   return binop( Iop_OrV128,
717                 mkexpr( t0 ),
718                 binop( Iop_OrV128, mkexpr( t1 ), mkexpr( t2 ) ) );
719}
720
721static inline IRExpr* mkOr4_V128( IRTemp t0, IRTemp t1, IRTemp t2,
722                                  IRTemp t3 )
723{
724   return binop( Iop_OrV128,
725                 binop( Iop_OrV128, mkexpr( t0 ), mkexpr( t1 ) ),
726                 binop( Iop_OrV128, mkexpr( t2 ), mkexpr( t3 ) ) );
727}
728
729static inline IRExpr* mkOr4_V128_expr( IRExpr* t0, IRExpr* t1, IRExpr* t2,
730                                       IRExpr* t3 )
731{
732   /* arguments are already expressions */
733   return binop( Iop_OrV128,
734                 binop( Iop_OrV128, ( t0 ), ( t1 ) ),
735                 binop( Iop_OrV128, ( t2 ), ( t3 ) ) );
736}
737
738static IRExpr* mkNOT1 ( IRExpr* arg1 )
739{
740   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
741   return unop(Iop_32to1, unop(Iop_Not32, unop(Iop_1Uto32, arg1) ) );
742}
743
744/* expand V128_8Ux16 to 2x V128_16Ux8's */
745static void expand8Ux16( IRExpr* vIn,
746                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
747{
748   IRTemp ones8x16 = newTemp(Ity_V128);
749
750   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
751   vassert(vEvn && *vEvn == IRTemp_INVALID);
752   vassert(vOdd && *vOdd == IRTemp_INVALID);
753   *vEvn = newTemp(Ity_V128);
754   *vOdd = newTemp(Ity_V128);
755
756   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
757   assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
758   assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
759                        binop(Iop_ShrV128, vIn, mkU8(8))) );
760}
761
762/* expand V128_8Sx16 to 2x V128_16Sx8's */
763static void expand8Sx16( IRExpr* vIn,
764                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
765{
766   IRTemp ones8x16 = newTemp(Ity_V128);
767
768   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
769   vassert(vEvn && *vEvn == IRTemp_INVALID);
770   vassert(vOdd && *vOdd == IRTemp_INVALID);
771   *vEvn = newTemp(Ity_V128);
772   *vOdd = newTemp(Ity_V128);
773
774   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
775   assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
776   assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
777                        binop(Iop_ShrV128, vIn, mkU8(8))) );
778}
779
780/* expand V128_16Uto8 to 2x V128_32Ux4's */
781static void expand16Ux8( IRExpr* vIn,
782                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
783{
784   IRTemp ones16x8 = newTemp(Ity_V128);
785
786   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
787   vassert(vEvn && *vEvn == IRTemp_INVALID);
788   vassert(vOdd && *vOdd == IRTemp_INVALID);
789   *vEvn = newTemp(Ity_V128);
790   *vOdd = newTemp(Ity_V128);
791
792   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
793   assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
794   assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
795                        binop(Iop_ShrV128, vIn, mkU8(16))) );
796}
797
798/* expand V128_16Sto8 to 2x V128_32Sx4's */
799static void expand16Sx8( IRExpr* vIn,
800                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
801{
802   IRTemp ones16x8 = newTemp(Ity_V128);
803
804   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
805   vassert(vEvn && *vEvn == IRTemp_INVALID);
806   vassert(vOdd && *vOdd == IRTemp_INVALID);
807   *vEvn = newTemp(Ity_V128);
808   *vOdd = newTemp(Ity_V128);
809
810   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
811   assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
812   assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
813                       binop(Iop_ShrV128, vIn, mkU8(16))) );
814}
815
816/* break V128 to 4xF64's*/
817static void breakV128to4xF64( IRExpr* t128,
818                              /*OUTs*/
819                              IRTemp* t3, IRTemp* t2,
820                              IRTemp* t1, IRTemp* t0 )
821{
822   IRTemp hi64 = newTemp(Ity_I64);
823   IRTemp lo64 = newTemp(Ity_I64);
824
825   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
826   vassert(t0 && *t0 == IRTemp_INVALID);
827   vassert(t1 && *t1 == IRTemp_INVALID);
828   vassert(t2 && *t2 == IRTemp_INVALID);
829   vassert(t3 && *t3 == IRTemp_INVALID);
830   *t0 = newTemp(Ity_F64);
831   *t1 = newTemp(Ity_F64);
832   *t2 = newTemp(Ity_F64);
833   *t3 = newTemp(Ity_F64);
834
835   assign( hi64, unop(Iop_V128HIto64, t128) );
836   assign( lo64, unop(Iop_V128to64,   t128) );
837   assign( *t3,
838           unop( Iop_F32toF64,
839                 unop( Iop_ReinterpI32asF32,
840                       unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
841   assign( *t2,
842           unop( Iop_F32toF64,
843                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
844   assign( *t1,
845           unop( Iop_F32toF64,
846                 unop( Iop_ReinterpI32asF32,
847                       unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
848   assign( *t0,
849           unop( Iop_F32toF64,
850                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
851}
852
853
854/* break V128 to 4xI32's, then sign-extend to I64's */
855static void breakV128to4x64S( 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_I64);
869   *t1 = newTemp(Ity_I64);
870   *t2 = newTemp(Ity_I64);
871   *t3 = newTemp(Ity_I64);
872
873   assign( hi64, unop(Iop_V128HIto64, t128) );
874   assign( lo64, unop(Iop_V128to64,   t128) );
875   assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
876   assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
877   assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
878   assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
879}
880
881/* break V128 to 4xI32's, then zero-extend to I64's */
882static void breakV128to4x64U ( IRExpr* t128,
883                               /*OUTs*/
884                               IRTemp* t3, IRTemp* t2,
885                               IRTemp* t1, IRTemp* t0 )
886{
887   IRTemp hi64 = newTemp(Ity_I64);
888   IRTemp lo64 = newTemp(Ity_I64);
889
890   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
891   vassert(t0 && *t0 == IRTemp_INVALID);
892   vassert(t1 && *t1 == IRTemp_INVALID);
893   vassert(t2 && *t2 == IRTemp_INVALID);
894   vassert(t3 && *t3 == IRTemp_INVALID);
895   *t0 = newTemp(Ity_I64);
896   *t1 = newTemp(Ity_I64);
897   *t2 = newTemp(Ity_I64);
898   *t3 = newTemp(Ity_I64);
899
900   assign( hi64, unop(Iop_V128HIto64, t128) );
901   assign( lo64, unop(Iop_V128to64,   t128) );
902   assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
903   assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
904   assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
905   assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
906}
907
908static void breakV128to4x32( IRExpr* t128,
909                              /*OUTs*/
910                              IRTemp* t3, IRTemp* t2,
911                              IRTemp* t1, IRTemp* t0 )
912{
913   IRTemp hi64 = newTemp(Ity_I64);
914   IRTemp lo64 = newTemp(Ity_I64);
915
916   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
917   vassert(t0 && *t0 == IRTemp_INVALID);
918   vassert(t1 && *t1 == IRTemp_INVALID);
919   vassert(t2 && *t2 == IRTemp_INVALID);
920   vassert(t3 && *t3 == IRTemp_INVALID);
921   *t0 = newTemp(Ity_I32);
922   *t1 = newTemp(Ity_I32);
923   *t2 = newTemp(Ity_I32);
924   *t3 = newTemp(Ity_I32);
925
926   assign( hi64, unop(Iop_V128HIto64, t128) );
927   assign( lo64, unop(Iop_V128to64,   t128) );
928   assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
929   assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
930   assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
931   assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
932}
933
934static IRExpr* mkV128from32( IRTemp t3, IRTemp t2,
935                               IRTemp t1, IRTemp t0 )
936{
937   return
938      binop( Iop_64HLtoV128,
939             binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
940             binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
941   );
942}
943
944static IRExpr* extract_field_from_vector( IRTemp vB, IRExpr* index, UInt mask)
945{
946   /* vB is a vector, extract bits starting at index to size of mask */
947   return unop( Iop_V128to64,
948                binop( Iop_AndV128,
949                       binop( Iop_ShrV128,
950                              mkexpr( vB ),
951                              unop( Iop_64to8,
952                                    binop( Iop_Mul64, index,
953                                           mkU64( 8 ) ) ) ),
954                       binop( Iop_64HLtoV128,
955                              mkU64( 0x0 ),
956                              mkU64( mask ) ) ) );
957}
958
959/* Signed saturating narrow 64S to 32 */
960static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
961{
962   IRTemp hi32 = newTemp(Ity_I32);
963   IRTemp lo32 = newTemp(Ity_I32);
964
965   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
966
967   assign( hi32, unop(Iop_64HIto32, t64));
968   assign( lo32, unop(Iop_64to32,   t64));
969
970   return IRExpr_ITE(
971             /* if (hi32 == (lo32 >>s 31)) */
972             binop(Iop_CmpEQ32, mkexpr(hi32),
973                   binop( Iop_Sar32, mkexpr(lo32), mkU8(31))),
974             /* then: within signed-32 range: lo half good enough */
975             mkexpr(lo32),
976             /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
977             binop(Iop_Add32, mkU32(0x7FFFFFFF),
978                   binop(Iop_Shr32, mkexpr(hi32), mkU8(31))));
979}
980
981/* Unsigned saturating narrow 64S to 32 */
982static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
983{
984   IRTemp hi32 = newTemp(Ity_I32);
985   IRTemp lo32 = newTemp(Ity_I32);
986
987   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
988
989   assign( hi32, unop(Iop_64HIto32, t64));
990   assign( lo32, unop(Iop_64to32,   t64));
991
992   return IRExpr_ITE(
993            /* if (top 32 bits of t64 are 0) */
994            binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)),
995            /* then: within unsigned-32 range: lo half good enough */
996            mkexpr(lo32),
997            /* else: positive saturate -> 0xFFFFFFFF */
998            mkU32(0xFFFFFFFF));
999}
1000
1001/* Signed saturate narrow 64->32, combining to V128 */
1002static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
1003                                 IRExpr* t1, IRExpr* t0 )
1004{
1005   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
1006   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
1007   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
1008   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
1009   return binop(Iop_64HLtoV128,
1010                binop(Iop_32HLto64,
1011                      mkQNarrow64Sto32( t3 ),
1012                      mkQNarrow64Sto32( t2 )),
1013                binop(Iop_32HLto64,
1014                      mkQNarrow64Sto32( t1 ),
1015                      mkQNarrow64Sto32( t0 )));
1016}
1017
1018/* Unsigned saturate narrow 64->32, combining to V128 */
1019static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
1020                                 IRExpr* t1, IRExpr* t0 )
1021{
1022   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
1023   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
1024   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
1025   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
1026   return binop(Iop_64HLtoV128,
1027                binop(Iop_32HLto64,
1028                      mkQNarrow64Uto32( t3 ),
1029                      mkQNarrow64Uto32( t2 )),
1030                binop(Iop_32HLto64,
1031                      mkQNarrow64Uto32( t1 ),
1032                      mkQNarrow64Uto32( t0 )));
1033}
1034
1035/* Simulate irops Iop_MullOdd*, since we don't have them  */
1036#define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
1037      binop(Iop_MullEven8Ux16, \
1038            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
1039            binop(Iop_ShrV128, expr_vB, mkU8(8)))
1040
1041#define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
1042      binop(Iop_MullEven8Sx16, \
1043            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
1044            binop(Iop_ShrV128, expr_vB, mkU8(8)))
1045
1046#define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
1047      binop(Iop_MullEven16Ux8, \
1048            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
1049            binop(Iop_ShrV128, expr_vB, mkU8(16)))
1050
1051#define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
1052      binop(Iop_MullEven32Ux4, \
1053            binop(Iop_ShrV128, expr_vA, mkU8(32)), \
1054            binop(Iop_ShrV128, expr_vB, mkU8(32)))
1055
1056#define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
1057      binop(Iop_MullEven16Sx8, \
1058            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
1059            binop(Iop_ShrV128, expr_vB, mkU8(16)))
1060
1061#define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
1062      binop(Iop_MullEven32Sx4, \
1063            binop(Iop_ShrV128, expr_vA, mkU8(32)), \
1064            binop(Iop_ShrV128, expr_vB, mkU8(32)))
1065
1066
1067static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
1068{
1069   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1070   return unop(Iop_32Sto64, unop(Iop_64to32, src));
1071}
1072
1073static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
1074{
1075   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1076   return unop(Iop_32Uto64, unop(Iop_64to32, src));
1077}
1078
1079static IROp mkSzOp ( IRType ty, IROp op8 )
1080{
1081   Int adj;
1082   vassert(ty == Ity_I8  || ty == Ity_I16 ||
1083           ty == Ity_I32 || ty == Ity_I64);
1084   vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
1085           op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
1086           op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
1087           op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
1088           op8 == Iop_Not8 );
1089   adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
1090   return adj + op8;
1091}
1092
1093/* Make sure we get valid 32 and 64bit addresses */
1094static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
1095{
1096   vassert(ty == Ity_I32 || ty == Ity_I64);
1097   return ( ty == Ity_I64 ?
1098            (Addr64)addr :
1099            (Addr64)extend_s_32to64( toUInt(addr) ) );
1100}
1101
1102/* sz, ULong -> IRExpr */
1103static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
1104{
1105   vassert(ty == Ity_I32 || ty == Ity_I64);
1106   return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
1107}
1108
1109/* sz, ULong -> IRConst */
1110static IRConst* mkSzConst ( IRType ty, ULong imm64 )
1111{
1112   vassert(ty == Ity_I32 || ty == Ity_I64);
1113   return ( ty == Ity_I64 ?
1114            IRConst_U64(imm64) :
1115            IRConst_U32((UInt)imm64) );
1116}
1117
1118/* Sign extend imm16 -> IRExpr* */
1119static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
1120{
1121   vassert(ty == Ity_I32 || ty == Ity_I64);
1122   return ( ty == Ity_I64 ?
1123            mkU64(extend_s_16to64(imm16)) :
1124            mkU32(extend_s_16to32(imm16)) );
1125}
1126
1127/* Sign extend imm32 -> IRExpr* */
1128static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
1129{
1130   vassert(ty == Ity_I32 || ty == Ity_I64);
1131   return ( ty == Ity_I64 ?
1132            mkU64(extend_s_32to64(imm32)) :
1133            mkU32(imm32) );
1134}
1135
1136/* IR narrows I32/I64 -> I8/I16/I32 */
1137static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
1138{
1139   vassert(ty == Ity_I32 || ty == Ity_I64);
1140   return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
1141}
1142
1143static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
1144{
1145   vassert(ty == Ity_I32 || ty == Ity_I64);
1146   return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
1147}
1148
1149static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
1150{
1151   vassert(ty == Ity_I32 || ty == Ity_I64);
1152   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
1153}
1154
1155/* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
1156static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
1157{
1158   IROp op;
1159   vassert(ty == Ity_I32 || ty == Ity_I64);
1160   if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
1161   else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
1162   return unop(op, src);
1163}
1164
1165static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
1166{
1167   IROp op;
1168   vassert(ty == Ity_I32 || ty == Ity_I64);
1169   if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
1170   else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
1171   return unop(op, src);
1172}
1173
1174static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
1175{
1176   vassert(ty == Ity_I32 || ty == Ity_I64);
1177   if (ty == Ity_I32)
1178      return src;
1179   return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
1180}
1181
1182
1183static Int integerGuestRegOffset ( UInt archreg )
1184{
1185   vassert(archreg < 32);
1186
1187   // jrs: probably not necessary; only matters if we reference sub-parts
1188   // of the ppc registers, but that isn't the case
1189   // later: this might affect Altivec though?
1190
1191   switch (archreg) {
1192   case  0: return offsetofPPCGuestState(guest_GPR0);
1193   case  1: return offsetofPPCGuestState(guest_GPR1);
1194   case  2: return offsetofPPCGuestState(guest_GPR2);
1195   case  3: return offsetofPPCGuestState(guest_GPR3);
1196   case  4: return offsetofPPCGuestState(guest_GPR4);
1197   case  5: return offsetofPPCGuestState(guest_GPR5);
1198   case  6: return offsetofPPCGuestState(guest_GPR6);
1199   case  7: return offsetofPPCGuestState(guest_GPR7);
1200   case  8: return offsetofPPCGuestState(guest_GPR8);
1201   case  9: return offsetofPPCGuestState(guest_GPR9);
1202   case 10: return offsetofPPCGuestState(guest_GPR10);
1203   case 11: return offsetofPPCGuestState(guest_GPR11);
1204   case 12: return offsetofPPCGuestState(guest_GPR12);
1205   case 13: return offsetofPPCGuestState(guest_GPR13);
1206   case 14: return offsetofPPCGuestState(guest_GPR14);
1207   case 15: return offsetofPPCGuestState(guest_GPR15);
1208   case 16: return offsetofPPCGuestState(guest_GPR16);
1209   case 17: return offsetofPPCGuestState(guest_GPR17);
1210   case 18: return offsetofPPCGuestState(guest_GPR18);
1211   case 19: return offsetofPPCGuestState(guest_GPR19);
1212   case 20: return offsetofPPCGuestState(guest_GPR20);
1213   case 21: return offsetofPPCGuestState(guest_GPR21);
1214   case 22: return offsetofPPCGuestState(guest_GPR22);
1215   case 23: return offsetofPPCGuestState(guest_GPR23);
1216   case 24: return offsetofPPCGuestState(guest_GPR24);
1217   case 25: return offsetofPPCGuestState(guest_GPR25);
1218   case 26: return offsetofPPCGuestState(guest_GPR26);
1219   case 27: return offsetofPPCGuestState(guest_GPR27);
1220   case 28: return offsetofPPCGuestState(guest_GPR28);
1221   case 29: return offsetofPPCGuestState(guest_GPR29);
1222   case 30: return offsetofPPCGuestState(guest_GPR30);
1223   case 31: return offsetofPPCGuestState(guest_GPR31);
1224   default: break;
1225   }
1226   vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1227}
1228
1229static IRExpr* getIReg ( UInt archreg )
1230{
1231   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1232   vassert(archreg < 32);
1233   return IRExpr_Get( integerGuestRegOffset(archreg), ty );
1234}
1235
1236/* Ditto, but write to a reg instead. */
1237static void putIReg ( UInt archreg, IRExpr* e )
1238{
1239   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1240   vassert(archreg < 32);
1241   vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
1242   stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
1243}
1244
1245
1246/* Floating point egisters are mapped to VSX registers[0..31]. */
1247static Int floatGuestRegOffset ( UInt archreg )
1248{
1249   vassert(archreg < 32);
1250
1251   if (host_endness == VexEndnessLE) {
1252      switch (archreg) {
1253         case  0: return offsetofPPCGuestState(guest_VSR0) + 8;
1254         case  1: return offsetofPPCGuestState(guest_VSR1) + 8;
1255         case  2: return offsetofPPCGuestState(guest_VSR2) + 8;
1256         case  3: return offsetofPPCGuestState(guest_VSR3) + 8;
1257         case  4: return offsetofPPCGuestState(guest_VSR4) + 8;
1258         case  5: return offsetofPPCGuestState(guest_VSR5) + 8;
1259         case  6: return offsetofPPCGuestState(guest_VSR6) + 8;
1260         case  7: return offsetofPPCGuestState(guest_VSR7) + 8;
1261         case  8: return offsetofPPCGuestState(guest_VSR8) + 8;
1262         case  9: return offsetofPPCGuestState(guest_VSR9) + 8;
1263         case 10: return offsetofPPCGuestState(guest_VSR10) + 8;
1264         case 11: return offsetofPPCGuestState(guest_VSR11) + 8;
1265         case 12: return offsetofPPCGuestState(guest_VSR12) + 8;
1266         case 13: return offsetofPPCGuestState(guest_VSR13) + 8;
1267         case 14: return offsetofPPCGuestState(guest_VSR14) + 8;
1268         case 15: return offsetofPPCGuestState(guest_VSR15) + 8;
1269         case 16: return offsetofPPCGuestState(guest_VSR16) + 8;
1270         case 17: return offsetofPPCGuestState(guest_VSR17) + 8;
1271         case 18: return offsetofPPCGuestState(guest_VSR18) + 8;
1272         case 19: return offsetofPPCGuestState(guest_VSR19) + 8;
1273         case 20: return offsetofPPCGuestState(guest_VSR20) + 8;
1274         case 21: return offsetofPPCGuestState(guest_VSR21) + 8;
1275         case 22: return offsetofPPCGuestState(guest_VSR22) + 8;
1276         case 23: return offsetofPPCGuestState(guest_VSR23) + 8;
1277         case 24: return offsetofPPCGuestState(guest_VSR24) + 8;
1278         case 25: return offsetofPPCGuestState(guest_VSR25) + 8;
1279         case 26: return offsetofPPCGuestState(guest_VSR26) + 8;
1280         case 27: return offsetofPPCGuestState(guest_VSR27) + 8;
1281         case 28: return offsetofPPCGuestState(guest_VSR28) + 8;
1282         case 29: return offsetofPPCGuestState(guest_VSR29) + 8;
1283         case 30: return offsetofPPCGuestState(guest_VSR30) + 8;
1284         case 31: return offsetofPPCGuestState(guest_VSR31) + 8;
1285         default: break;
1286      }
1287   } else {
1288      switch (archreg) {
1289         case  0: return offsetofPPCGuestState(guest_VSR0);
1290         case  1: return offsetofPPCGuestState(guest_VSR1);
1291         case  2: return offsetofPPCGuestState(guest_VSR2);
1292         case  3: return offsetofPPCGuestState(guest_VSR3);
1293         case  4: return offsetofPPCGuestState(guest_VSR4);
1294         case  5: return offsetofPPCGuestState(guest_VSR5);
1295         case  6: return offsetofPPCGuestState(guest_VSR6);
1296         case  7: return offsetofPPCGuestState(guest_VSR7);
1297         case  8: return offsetofPPCGuestState(guest_VSR8);
1298         case  9: return offsetofPPCGuestState(guest_VSR9);
1299         case 10: return offsetofPPCGuestState(guest_VSR10);
1300         case 11: return offsetofPPCGuestState(guest_VSR11);
1301         case 12: return offsetofPPCGuestState(guest_VSR12);
1302         case 13: return offsetofPPCGuestState(guest_VSR13);
1303         case 14: return offsetofPPCGuestState(guest_VSR14);
1304         case 15: return offsetofPPCGuestState(guest_VSR15);
1305         case 16: return offsetofPPCGuestState(guest_VSR16);
1306         case 17: return offsetofPPCGuestState(guest_VSR17);
1307         case 18: return offsetofPPCGuestState(guest_VSR18);
1308         case 19: return offsetofPPCGuestState(guest_VSR19);
1309         case 20: return offsetofPPCGuestState(guest_VSR20);
1310         case 21: return offsetofPPCGuestState(guest_VSR21);
1311         case 22: return offsetofPPCGuestState(guest_VSR22);
1312         case 23: return offsetofPPCGuestState(guest_VSR23);
1313         case 24: return offsetofPPCGuestState(guest_VSR24);
1314         case 25: return offsetofPPCGuestState(guest_VSR25);
1315         case 26: return offsetofPPCGuestState(guest_VSR26);
1316         case 27: return offsetofPPCGuestState(guest_VSR27);
1317         case 28: return offsetofPPCGuestState(guest_VSR28);
1318         case 29: return offsetofPPCGuestState(guest_VSR29);
1319         case 30: return offsetofPPCGuestState(guest_VSR30);
1320         case 31: return offsetofPPCGuestState(guest_VSR31);
1321         default: break;
1322      }
1323   }
1324   vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1325}
1326
1327static IRExpr* getFReg ( UInt archreg )
1328{
1329   vassert(archreg < 32);
1330   return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1331}
1332
1333/* Ditto, but write to a reg instead. */
1334static void putFReg ( UInt archreg, IRExpr* e )
1335{
1336   vassert(archreg < 32);
1337   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1338   stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1339}
1340
1341/* get Decimal float value.  Note, they share floating point register file. */
1342static IRExpr* getDReg(UInt archreg) {
1343   IRExpr *e;
1344   vassert( archreg < 32 );
1345   e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
1346   return e;
1347}
1348static IRExpr* getDReg32(UInt archreg) {
1349   IRExpr *e;
1350   vassert( archreg < 32 );
1351   e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
1352   return e;
1353}
1354
1355/* Read a floating point register pair and combine their contents into a
1356 128-bit value */
1357static IRExpr *getDReg_pair(UInt archreg) {
1358   IRExpr *high = getDReg( archreg );
1359   IRExpr *low = getDReg( archreg + 1 );
1360
1361   return binop( Iop_D64HLtoD128, high, low );
1362}
1363
1364/* Ditto, but write to a reg instead. */
1365static void putDReg32(UInt archreg, IRExpr* e) {
1366   vassert( archreg < 32 );
1367   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
1368   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1369}
1370
1371static void putDReg(UInt archreg, IRExpr* e) {
1372   vassert( archreg < 32 );
1373   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
1374   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1375}
1376
1377/* Write a 128-bit floating point value into a register pair. */
1378static void putDReg_pair(UInt archreg, IRExpr *e) {
1379   IRTemp low = newTemp( Ity_D64 );
1380   IRTemp high = newTemp( Ity_D64 );
1381
1382   vassert( archreg < 32 );
1383   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
1384
1385   assign( low, unop( Iop_D128LOtoD64, e ) );
1386   assign( high, unop( Iop_D128HItoD64, e ) );
1387
1388   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
1389   stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
1390}
1391
1392static Int vsxGuestRegOffset ( UInt archreg )
1393{
1394   vassert(archreg < 64);
1395   switch (archreg) {
1396   case  0: return offsetofPPCGuestState(guest_VSR0);
1397   case  1: return offsetofPPCGuestState(guest_VSR1);
1398   case  2: return offsetofPPCGuestState(guest_VSR2);
1399   case  3: return offsetofPPCGuestState(guest_VSR3);
1400   case  4: return offsetofPPCGuestState(guest_VSR4);
1401   case  5: return offsetofPPCGuestState(guest_VSR5);
1402   case  6: return offsetofPPCGuestState(guest_VSR6);
1403   case  7: return offsetofPPCGuestState(guest_VSR7);
1404   case  8: return offsetofPPCGuestState(guest_VSR8);
1405   case  9: return offsetofPPCGuestState(guest_VSR9);
1406   case 10: return offsetofPPCGuestState(guest_VSR10);
1407   case 11: return offsetofPPCGuestState(guest_VSR11);
1408   case 12: return offsetofPPCGuestState(guest_VSR12);
1409   case 13: return offsetofPPCGuestState(guest_VSR13);
1410   case 14: return offsetofPPCGuestState(guest_VSR14);
1411   case 15: return offsetofPPCGuestState(guest_VSR15);
1412   case 16: return offsetofPPCGuestState(guest_VSR16);
1413   case 17: return offsetofPPCGuestState(guest_VSR17);
1414   case 18: return offsetofPPCGuestState(guest_VSR18);
1415   case 19: return offsetofPPCGuestState(guest_VSR19);
1416   case 20: return offsetofPPCGuestState(guest_VSR20);
1417   case 21: return offsetofPPCGuestState(guest_VSR21);
1418   case 22: return offsetofPPCGuestState(guest_VSR22);
1419   case 23: return offsetofPPCGuestState(guest_VSR23);
1420   case 24: return offsetofPPCGuestState(guest_VSR24);
1421   case 25: return offsetofPPCGuestState(guest_VSR25);
1422   case 26: return offsetofPPCGuestState(guest_VSR26);
1423   case 27: return offsetofPPCGuestState(guest_VSR27);
1424   case 28: return offsetofPPCGuestState(guest_VSR28);
1425   case 29: return offsetofPPCGuestState(guest_VSR29);
1426   case 30: return offsetofPPCGuestState(guest_VSR30);
1427   case 31: return offsetofPPCGuestState(guest_VSR31);
1428   case 32: return offsetofPPCGuestState(guest_VSR32);
1429   case 33: return offsetofPPCGuestState(guest_VSR33);
1430   case 34: return offsetofPPCGuestState(guest_VSR34);
1431   case 35: return offsetofPPCGuestState(guest_VSR35);
1432   case 36: return offsetofPPCGuestState(guest_VSR36);
1433   case 37: return offsetofPPCGuestState(guest_VSR37);
1434   case 38: return offsetofPPCGuestState(guest_VSR38);
1435   case 39: return offsetofPPCGuestState(guest_VSR39);
1436   case 40: return offsetofPPCGuestState(guest_VSR40);
1437   case 41: return offsetofPPCGuestState(guest_VSR41);
1438   case 42: return offsetofPPCGuestState(guest_VSR42);
1439   case 43: return offsetofPPCGuestState(guest_VSR43);
1440   case 44: return offsetofPPCGuestState(guest_VSR44);
1441   case 45: return offsetofPPCGuestState(guest_VSR45);
1442   case 46: return offsetofPPCGuestState(guest_VSR46);
1443   case 47: return offsetofPPCGuestState(guest_VSR47);
1444   case 48: return offsetofPPCGuestState(guest_VSR48);
1445   case 49: return offsetofPPCGuestState(guest_VSR49);
1446   case 50: return offsetofPPCGuestState(guest_VSR50);
1447   case 51: return offsetofPPCGuestState(guest_VSR51);
1448   case 52: return offsetofPPCGuestState(guest_VSR52);
1449   case 53: return offsetofPPCGuestState(guest_VSR53);
1450   case 54: return offsetofPPCGuestState(guest_VSR54);
1451   case 55: return offsetofPPCGuestState(guest_VSR55);
1452   case 56: return offsetofPPCGuestState(guest_VSR56);
1453   case 57: return offsetofPPCGuestState(guest_VSR57);
1454   case 58: return offsetofPPCGuestState(guest_VSR58);
1455   case 59: return offsetofPPCGuestState(guest_VSR59);
1456   case 60: return offsetofPPCGuestState(guest_VSR60);
1457   case 61: return offsetofPPCGuestState(guest_VSR61);
1458   case 62: return offsetofPPCGuestState(guest_VSR62);
1459   case 63: return offsetofPPCGuestState(guest_VSR63);
1460   default: break;
1461   }
1462   vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1463}
1464
1465/* Vector registers are mapped to VSX registers[32..63]. */
1466static Int vectorGuestRegOffset ( UInt archreg )
1467{
1468   vassert(archreg < 32);
1469
1470   switch (archreg) {
1471   case  0: return offsetofPPCGuestState(guest_VSR32);
1472   case  1: return offsetofPPCGuestState(guest_VSR33);
1473   case  2: return offsetofPPCGuestState(guest_VSR34);
1474   case  3: return offsetofPPCGuestState(guest_VSR35);
1475   case  4: return offsetofPPCGuestState(guest_VSR36);
1476   case  5: return offsetofPPCGuestState(guest_VSR37);
1477   case  6: return offsetofPPCGuestState(guest_VSR38);
1478   case  7: return offsetofPPCGuestState(guest_VSR39);
1479   case  8: return offsetofPPCGuestState(guest_VSR40);
1480   case  9: return offsetofPPCGuestState(guest_VSR41);
1481   case 10: return offsetofPPCGuestState(guest_VSR42);
1482   case 11: return offsetofPPCGuestState(guest_VSR43);
1483   case 12: return offsetofPPCGuestState(guest_VSR44);
1484   case 13: return offsetofPPCGuestState(guest_VSR45);
1485   case 14: return offsetofPPCGuestState(guest_VSR46);
1486   case 15: return offsetofPPCGuestState(guest_VSR47);
1487   case 16: return offsetofPPCGuestState(guest_VSR48);
1488   case 17: return offsetofPPCGuestState(guest_VSR49);
1489   case 18: return offsetofPPCGuestState(guest_VSR50);
1490   case 19: return offsetofPPCGuestState(guest_VSR51);
1491   case 20: return offsetofPPCGuestState(guest_VSR52);
1492   case 21: return offsetofPPCGuestState(guest_VSR53);
1493   case 22: return offsetofPPCGuestState(guest_VSR54);
1494   case 23: return offsetofPPCGuestState(guest_VSR55);
1495   case 24: return offsetofPPCGuestState(guest_VSR56);
1496   case 25: return offsetofPPCGuestState(guest_VSR57);
1497   case 26: return offsetofPPCGuestState(guest_VSR58);
1498   case 27: return offsetofPPCGuestState(guest_VSR59);
1499   case 28: return offsetofPPCGuestState(guest_VSR60);
1500   case 29: return offsetofPPCGuestState(guest_VSR61);
1501   case 30: return offsetofPPCGuestState(guest_VSR62);
1502   case 31: return offsetofPPCGuestState(guest_VSR63);
1503   default: break;
1504   }
1505   vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1506}
1507
1508static IRExpr* getVReg ( UInt archreg )
1509{
1510   vassert(archreg < 32);
1511   return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1512}
1513
1514/* Get contents of 128-bit reg guest register */
1515static IRExpr* getF128Reg ( UInt archreg )
1516{
1517   vassert(archreg < 64);
1518   return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_F128 );
1519}
1520
1521/* Ditto, but write to a reg instead. */
1522static void putF128Reg ( UInt archreg, IRExpr* e )
1523{
1524   vassert(archreg < 64);
1525   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F128);
1526   stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1527}
1528
1529/* Ditto, but write to a reg instead. */
1530static void putVReg ( UInt archreg, IRExpr* e )
1531{
1532   vassert(archreg < 32);
1533   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1534   stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1535}
1536
1537/* Get contents of VSX guest register */
1538static IRExpr* getVSReg ( UInt archreg )
1539{
1540   vassert(archreg < 64);
1541   return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
1542}
1543
1544/* Ditto, but write to a VSX reg instead. */
1545static void putVSReg ( UInt archreg, IRExpr* e )
1546{
1547   vassert(archreg < 64);
1548   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1549   stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
1550}
1551
1552
1553static Int guestCR321offset ( UInt cr )
1554{
1555   switch (cr) {
1556   case 0: return offsetofPPCGuestState(guest_CR0_321 );
1557   case 1: return offsetofPPCGuestState(guest_CR1_321 );
1558   case 2: return offsetofPPCGuestState(guest_CR2_321 );
1559   case 3: return offsetofPPCGuestState(guest_CR3_321 );
1560   case 4: return offsetofPPCGuestState(guest_CR4_321 );
1561   case 5: return offsetofPPCGuestState(guest_CR5_321 );
1562   case 6: return offsetofPPCGuestState(guest_CR6_321 );
1563   case 7: return offsetofPPCGuestState(guest_CR7_321 );
1564   default: vpanic("guestCR321offset(ppc)");
1565   }
1566}
1567
1568static Int guestCR0offset ( UInt cr )
1569{
1570   switch (cr) {
1571   case 0: return offsetofPPCGuestState(guest_CR0_0 );
1572   case 1: return offsetofPPCGuestState(guest_CR1_0 );
1573   case 2: return offsetofPPCGuestState(guest_CR2_0 );
1574   case 3: return offsetofPPCGuestState(guest_CR3_0 );
1575   case 4: return offsetofPPCGuestState(guest_CR4_0 );
1576   case 5: return offsetofPPCGuestState(guest_CR5_0 );
1577   case 6: return offsetofPPCGuestState(guest_CR6_0 );
1578   case 7: return offsetofPPCGuestState(guest_CR7_0 );
1579   default: vpanic("guestCR3offset(ppc)");
1580   }
1581}
1582
1583typedef enum {
1584   _placeholder0,
1585   _placeholder1,
1586   _placeholder2,
1587   BYTE,
1588   HWORD,
1589   WORD,
1590   DWORD
1591} _popcount_data_type;
1592
1593/* Generate an IR sequence to do a popcount operation on the supplied
1594   IRTemp, and return a new IRTemp holding the result.  'ty' may be
1595   Ity_I32 or Ity_I64 only. */
1596static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type )
1597{
1598  /* Do count across 2^data_type bits,
1599     byte:        data_type = 3
1600     half word:   data_type = 4
1601     word:        data_type = 5
1602     double word: data_type = 6  (not supported for 32-bit type)
1603    */
1604   Int shift[6];
1605   _popcount_data_type idx, i;
1606   IRTemp mask[6];
1607   IRTemp old = IRTemp_INVALID;
1608   IRTemp nyu = IRTemp_INVALID;
1609
1610   vassert(ty == Ity_I64 || ty == Ity_I32);
1611
1612   if (ty == Ity_I32) {
1613
1614      for (idx = 0; idx < WORD; idx++) {
1615         mask[idx]  = newTemp(ty);
1616         shift[idx] = 1 << idx;
1617      }
1618      assign(mask[0], mkU32(0x55555555));
1619      assign(mask[1], mkU32(0x33333333));
1620      assign(mask[2], mkU32(0x0F0F0F0F));
1621      assign(mask[3], mkU32(0x00FF00FF));
1622      assign(mask[4], mkU32(0x0000FFFF));
1623      old = src;
1624      for (i = 0; i < data_type; i++) {
1625         nyu = newTemp(ty);
1626         assign(nyu,
1627                binop(Iop_Add32,
1628                      binop(Iop_And32,
1629                            mkexpr(old),
1630                            mkexpr(mask[i])),
1631                      binop(Iop_And32,
1632                            binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1633                            mkexpr(mask[i]))));
1634         old = nyu;
1635      }
1636      return nyu;
1637   }
1638
1639// else, ty == Ity_I64
1640   vassert(mode64);
1641
1642   for (i = 0; i < DWORD; i++) {
1643      mask[i] = newTemp( Ity_I64 );
1644      shift[i] = 1 << i;
1645   }
1646   assign( mask[0], mkU64( 0x5555555555555555ULL ) );
1647   assign( mask[1], mkU64( 0x3333333333333333ULL ) );
1648   assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
1649   assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
1650   assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
1651   assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
1652   old = src;
1653   for (i = 0; i < data_type; i++) {
1654      nyu = newTemp( Ity_I64 );
1655      assign( nyu,
1656              binop( Iop_Add64,
1657                     binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
1658                     binop( Iop_And64,
1659                            binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
1660                            mkexpr( mask[i] ) ) ) );
1661      old = nyu;
1662   }
1663   return nyu;
1664}
1665
1666/* Special purpose population count function for
1667 * vpopcntd in 32-bit mode.
1668 */
1669static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 )
1670{
1671   Int i, shift[6];
1672   IRTemp mask[6];
1673   IRTemp old = IRTemp_INVALID;
1674   IRTemp nyu1 = IRTemp_INVALID;
1675   IRTemp nyu2 = IRTemp_INVALID;
1676   IRTemp retval = newTemp(Ity_I64);
1677
1678   vassert(!mode64);
1679
1680   for (i = 0; i < WORD; i++) {
1681      mask[i]  = newTemp(Ity_I32);
1682      shift[i] = 1 << i;
1683   }
1684   assign(mask[0], mkU32(0x55555555));
1685   assign(mask[1], mkU32(0x33333333));
1686   assign(mask[2], mkU32(0x0F0F0F0F));
1687   assign(mask[3], mkU32(0x00FF00FF));
1688   assign(mask[4], mkU32(0x0000FFFF));
1689   old = src1;
1690   for (i = 0; i < WORD; i++) {
1691      nyu1 = newTemp(Ity_I32);
1692      assign(nyu1,
1693             binop(Iop_Add32,
1694                   binop(Iop_And32,
1695                         mkexpr(old),
1696                         mkexpr(mask[i])),
1697                   binop(Iop_And32,
1698                         binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1699                         mkexpr(mask[i]))));
1700      old = nyu1;
1701   }
1702
1703   old = src2;
1704   for (i = 0; i < WORD; i++) {
1705      nyu2 = newTemp(Ity_I32);
1706      assign(nyu2,
1707             binop(Iop_Add32,
1708                   binop(Iop_And32,
1709                         mkexpr(old),
1710                         mkexpr(mask[i])),
1711                   binop(Iop_And32,
1712                         binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1713                         mkexpr(mask[i]))));
1714      old = nyu2;
1715   }
1716   assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2))));
1717   return retval;
1718}
1719
1720
1721// ROTL(src32/64, rot_amt5/6)
1722static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1723                                          IRExpr* rot_amt )
1724{
1725   IRExpr *mask, *rot;
1726   vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1727
1728   if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1729      // rot = (src << rot_amt) | (src >> (64-rot_amt))
1730      mask = binop(Iop_And8, rot_amt, mkU8(63));
1731      rot  = binop(Iop_Or64,
1732                binop(Iop_Shl64, src, mask),
1733                binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1734   } else {
1735      // rot = (src << rot_amt) | (src >> (32-rot_amt))
1736      mask = binop(Iop_And8, rot_amt, mkU8(31));
1737      rot  = binop(Iop_Or32,
1738                binop(Iop_Shl32, src, mask),
1739                binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
1740   }
1741   /* Note: the ITE not merely an optimisation; it's needed
1742      because otherwise the Shr is a shift by the word size when
1743      mask denotes zero.  For rotates by immediates, a lot of
1744      this junk gets folded out. */
1745   return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)),
1746                      /* non-zero rotate */ rot,
1747                      /*     zero rotate */ src);
1748}
1749
1750/* Standard effective address calc: (rA + rB) */
1751static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1752{
1753   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1754   vassert(rA < 32);
1755   vassert(rB < 32);
1756   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1757}
1758
1759/* Standard effective address calc: (rA + simm) */
1760static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1761{
1762   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1763   vassert(rA < 32);
1764   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
1765                mkSzExtendS16(ty, simm16));
1766}
1767
1768/* Standard effective address calc: (rA|0) */
1769static IRExpr* ea_rAor0 ( UInt rA )
1770{
1771   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1772   vassert(rA < 32);
1773   if (rA == 0) {
1774      return mkSzImm(ty, 0);
1775   } else {
1776      return getIReg(rA);
1777   }
1778}
1779
1780/* Standard effective address calc: (rA|0) + rB */
1781static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1782{
1783   vassert(rA < 32);
1784   vassert(rB < 32);
1785   return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1786}
1787
1788/* Standard effective address calc: (rA|0) + simm16 */
1789static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
1790{
1791   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1792   vassert(rA < 32);
1793   if (rA == 0) {
1794      return mkSzExtendS16(ty, simm16);
1795   } else {
1796      return ea_rA_simm( rA, simm16 );
1797   }
1798}
1799
1800
1801/* Align effective address */
1802static IRExpr* addr_align( IRExpr* addr, UChar align )
1803{
1804   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1805   ULong mask;
1806   switch (align) {
1807   case 1:  return addr;                    // byte aligned
1808   case 2:  mask = ~0ULL << 1; break;       // half-word aligned
1809   case 4:  mask = ~0ULL << 2; break;       // word aligned
1810   case 16: mask = ~0ULL << 4; break;       // quad-word aligned
1811   default:
1812      vex_printf("addr_align: align = %u\n", align);
1813      vpanic("addr_align(ppc)");
1814   }
1815
1816   vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1817   return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
1818}
1819
1820
1821/* Exit the trace if ADDR (intended to be a guest memory address) is
1822   not ALIGN-aligned, generating a request for a SIGBUS followed by a
1823   restart of the current insn. */
1824static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1825{
1826   vassert(align == 2 || align == 4 || align == 8 || align == 16);
1827   if (mode64) {
1828      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1829      stmt(
1830         IRStmt_Exit(
1831            binop(Iop_CmpNE64,
1832                  binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1833                  mkU64(0)),
1834            Ijk_SigBUS,
1835            IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
1836         )
1837      );
1838   } else {
1839      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1840      stmt(
1841         IRStmt_Exit(
1842            binop(Iop_CmpNE32,
1843                  binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1844                  mkU32(0)),
1845            Ijk_SigBUS,
1846            IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
1847         )
1848      );
1849   }
1850}
1851
1852
1853/* Generate AbiHints which mark points at which the ELF or PowerOpen
1854   ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1855   N) becomes undefined.  That is at function calls and returns.  ELF
1856   ppc32 doesn't have this "feature" (how fortunate for it).  nia is
1857   the address of the next instruction to be executed.
1858*/
1859static void make_redzone_AbiHint ( const VexAbiInfo* vbi,
1860                                   IRTemp nia, const HChar* who )
1861{
1862   Int szB = vbi->guest_stack_redzone_size;
1863   if (0) vex_printf("AbiHint: %s\n", who);
1864   vassert(szB >= 0);
1865   if (szB > 0) {
1866      if (mode64) {
1867         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1868         stmt( IRStmt_AbiHint(
1869                  binop(Iop_Sub64, getIReg(1), mkU64(szB)),
1870                  szB,
1871                  mkexpr(nia)
1872         ));
1873      } else {
1874         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1875         stmt( IRStmt_AbiHint(
1876                  binop(Iop_Sub32, getIReg(1), mkU32(szB)),
1877                  szB,
1878                  mkexpr(nia)
1879         ));
1880      }
1881   }
1882}
1883
1884
1885/*------------------------------------------------------------*/
1886/*--- Helpers for condition codes.                         ---*/
1887/*------------------------------------------------------------*/
1888
1889/* Condition register layout.
1890
1891   In the hardware, CR is laid out like this.  The leftmost end is the
1892   most significant bit in the register; however the IBM documentation
1893   numbers the bits backwards for some reason.
1894
1895   CR0      CR1    ..........   CR6       CR7
1896   0 .. 3   .......................  28 .. 31    (IBM bit numbering)
1897   31  28                             3    0     (normal bit numbering)
1898
1899   Each CR field is 4 bits:  [<,>,==,SO]
1900
1901   Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1902
1903   Indexing from BI to guest state:
1904
1905     let    n = BI / 4
1906          off = BI % 4
1907     this references CR n:
1908
1909        off==0   ->  guest_CRn_321 >> 3
1910        off==1   ->  guest_CRn_321 >> 2
1911        off==2   ->  guest_CRn_321 >> 1
1912        off==3   ->  guest_CRn_SO
1913
1914   Bear in mind the only significant bit in guest_CRn_SO is bit 0
1915   (normal notation) and in guest_CRn_321 the significant bits are
1916   3, 2 and 1 (normal notation).
1917*/
1918
1919static void putCR321 ( UInt cr, IRExpr* e )
1920{
1921   vassert(cr < 8);
1922   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1923   stmt( IRStmt_Put(guestCR321offset(cr), e) );
1924}
1925
1926static void putCR0 ( UInt cr, IRExpr* e )
1927{
1928   vassert(cr < 8);
1929   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1930   stmt( IRStmt_Put(guestCR0offset(cr), e) );
1931}
1932
1933static void putC ( IRExpr* e )
1934{
1935   /* The assumption is that the value of the Floating-Point Result
1936    * Class Descriptor bit (C) is passed in the lower four bits of a
1937    * 32 bit value.
1938    *
1939    * Note, the C and FPCC bits which are fields in the FPSCR
1940    * register are stored in their own memory location of
1941    * memory.  The FPCC bits are in the lower 4 bits.  The C bit needs
1942    * to be shifted to bit 4 in the memory location that holds C and FPCC.
1943    * Note not all of the FPSCR register bits are supported.  We are
1944    * only writing C bit.
1945    */
1946   IRExpr* tmp;
1947
1948   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
1949
1950   /* Get the FPCC bit field */
1951   tmp = binop( Iop_And32,
1952                mkU32( 0xF ),
1953                unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ) );
1954
1955   stmt( IRStmt_Put( OFFB_C_FPCC,
1956                     unop( Iop_32to8,
1957                           binop( Iop_Or32, tmp,
1958                                  binop( Iop_Shl32,
1959                                         binop( Iop_And32, mkU32( 0x1 ), e ),
1960                                         mkU8( 4 ) ) ) ) ) );
1961}
1962
1963static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1964{
1965   vassert(cr < 8);
1966   return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1967}
1968
1969static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1970{
1971   vassert(cr < 8);
1972   return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1973}
1974
1975/* Fetch the specified CR bit (as per IBM/hardware notation) and
1976   return it at the bottom of an I32; the top 31 bits are guaranteed
1977   to be zero. */
1978static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1979{
1980   UInt n   = bi / 4;
1981   UInt off = bi % 4;
1982   vassert(bi < 32);
1983   if (off == 3) {
1984      /* Fetch the SO bit for this CR field */
1985      /* Note: And32 is redundant paranoia iff guest state only has 0
1986         or 1 in that slot. */
1987      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1988   } else {
1989      /* Fetch the <, > or == bit for this CR field */
1990      return binop( Iop_And32,
1991                    binop( Iop_Shr32,
1992                           unop(Iop_8Uto32, getCR321(n)),
1993                           mkU8(toUChar(3-off)) ),
1994                    mkU32(1) );
1995   }
1996}
1997
1998/* Dually, write the least significant bit of BIT to the specified CR
1999   bit.  Indexing as per getCRbit. */
2000static void putCRbit ( UInt bi, IRExpr* bit )
2001{
2002   UInt    n, off;
2003   IRExpr* safe;
2004   vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
2005   safe = binop(Iop_And32, bit, mkU32(1));
2006   n   = bi / 4;
2007   off = bi % 4;
2008   vassert(bi < 32);
2009   if (off == 3) {
2010      /* This is the SO bit for this CR field */
2011      putCR0(n, unop(Iop_32to8, safe));
2012   } else {
2013      off = 3 - off;
2014      vassert(off == 1 || off == 2 || off == 3);
2015      putCR321(
2016         n,
2017         unop( Iop_32to8,
2018               binop( Iop_Or32,
2019                      /* old value with field masked out */
2020                      binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
2021                                       mkU32(~(1 << off))),
2022                      /* new value in the right place */
2023                      binop(Iop_Shl32, safe, mkU8(toUChar(off)))
2024               )
2025         )
2026      );
2027   }
2028}
2029
2030/* Fetch the specified CR bit (as per IBM/hardware notation) and
2031   return it somewhere in an I32; it does not matter where, but
2032   whichever bit it is, all other bits are guaranteed to be zero.  In
2033   other words, the I32-typed expression will be zero if the bit is
2034   zero and nonzero if the bit is 1.  Write into *where the index
2035   of where the bit will be. */
2036
2037static
2038IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
2039{
2040   UInt n   = bi / 4;
2041   UInt off = bi % 4;
2042   vassert(bi < 32);
2043   if (off == 3) {
2044      /* Fetch the SO bit for this CR field */
2045      /* Note: And32 is redundant paranoia iff guest state only has 0
2046         or 1 in that slot. */
2047      *where = 0;
2048      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
2049   } else {
2050      /* Fetch the <, > or == bit for this CR field */
2051      *where = 3-off;
2052      return binop( Iop_And32,
2053                    unop(Iop_8Uto32, getCR321(n)),
2054                    mkU32(1 << (3-off)) );
2055   }
2056}
2057
2058/* Set the CR0 flags following an arithmetic operation.
2059   (Condition Register CR0 Field Definition, PPC32 p60)
2060*/
2061static IRExpr* getXER_SO ( void );
2062static void set_CR0 ( IRExpr* result )
2063{
2064   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
2065           typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
2066   if (mode64) {
2067      putCR321( 0, unop(Iop_64to8,
2068                        binop(Iop_CmpORD64S, result, mkU64(0))) );
2069   } else {
2070      putCR321( 0, unop(Iop_32to8,
2071                        binop(Iop_CmpORD32S, result, mkU32(0))) );
2072   }
2073   putCR0( 0, getXER_SO() );
2074}
2075
2076
2077/* Set the CR6 flags following an AltiVec compare operation.
2078 * NOTE: This also works for VSX single-precision compares.
2079 * */
2080static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
2081{
2082   /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
2083      all_ones  = (v[0] && v[1] && v[2] && v[3])
2084      all_zeros = ~(v[0] || v[1] || v[2] || v[3])
2085   */
2086   IRTemp v0 = newTemp(Ity_V128);
2087   IRTemp v1 = newTemp(Ity_V128);
2088   IRTemp v2 = newTemp(Ity_V128);
2089   IRTemp v3 = newTemp(Ity_V128);
2090   IRTemp rOnes  = newTemp(Ity_I8);
2091   IRTemp rZeros = newTemp(Ity_I8);
2092
2093   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
2094
2095   assign( v0, result );
2096   assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
2097   assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
2098   assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
2099
2100   assign( rZeros, unop(Iop_1Uto8,
2101       binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
2102             unop(Iop_Not32,
2103                  unop(Iop_V128to32,
2104                       binop(Iop_OrV128,
2105                             binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
2106                             binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
2107                  ))) );
2108
2109   if (test_all_ones) {
2110      assign( rOnes, unop(Iop_1Uto8,
2111         binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
2112               unop(Iop_V128to32,
2113                    binop(Iop_AndV128,
2114                          binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
2115                          binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
2116                    ))) );
2117      putCR321( 6, binop(Iop_Or8,
2118                         binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
2119                         binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
2120   } else {
2121      putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
2122   }
2123   putCR0( 6, mkU8(0) );
2124}
2125
2126
2127static IRExpr * create_DCM ( IRType size, IRTemp NaN, IRTemp inf, IRTemp zero,
2128                             IRTemp dnorm, IRTemp pos)
2129{
2130   /* This is a general function for creating the DCM for a 32-bit or
2131      64-bit expression based on the passes size.
2132   */
2133   IRTemp neg;
2134   IROp opAND, opOR, opSHL, opXto1, op1UtoX;
2135
2136   vassert( ( size == Ity_I32 ) || ( size == Ity_I64 ) );
2137
2138   if ( size == Ity_I32 ) {
2139      opSHL = Iop_Shl32;
2140      opAND = Iop_And32;
2141      opOR  = Iop_Or32;
2142      opXto1 = Iop_32to1;
2143      op1UtoX = Iop_1Uto32;
2144      neg = newTemp( Ity_I32 );
2145
2146   } else {
2147      opSHL = Iop_Shl64;
2148      opAND = Iop_And64;
2149      opOR  = Iop_Or64;
2150      opXto1 = Iop_64to1;
2151      op1UtoX = Iop_1Uto64;
2152      neg = newTemp( Ity_I64 );
2153   }
2154
2155   assign( neg, unop( op1UtoX, mkNOT1( unop( opXto1,
2156                                             mkexpr ( pos ) ) ) ) );
2157
2158   return binop( opOR,
2159                 binop( opSHL, mkexpr( NaN ), mkU8( 6 ) ),
2160                 binop( opOR,
2161                        binop( opOR,
2162                               binop( opOR,
2163                                      binop( opSHL,
2164                                             binop( opAND,
2165                                                    mkexpr( pos ),
2166                                                    mkexpr( inf ) ),
2167                                             mkU8( 5 ) ),
2168                                      binop( opSHL,
2169                                             binop( opAND,
2170                                                    mkexpr( neg ),
2171                                                    mkexpr( inf ) ),
2172                                             mkU8( 4 ) ) ),
2173                               binop( opOR,
2174                                      binop( opSHL,
2175                                             binop( opAND,
2176                                                    mkexpr( pos ),
2177                                                    mkexpr( zero ) ),
2178                                             mkU8( 3 ) ),
2179                                      binop( opSHL,
2180                                             binop( opAND,
2181                                                    mkexpr( neg ),
2182                                                    mkexpr( zero ) ),
2183                                             mkU8( 2 ) ) ) ),
2184                        binop( opOR,
2185                               binop( opSHL,
2186                                      binop( opAND,
2187                                             mkexpr( pos ),
2188                                             mkexpr( dnorm ) ),
2189                                      mkU8( 1 ) ),
2190                               binop( opAND,
2191                                      mkexpr( neg ),
2192                                      mkexpr( dnorm ) ) ) ) );
2193}
2194
2195/*------------------------------------------------------------*/
2196/*--- Helpers for XER flags.                               ---*/
2197/*------------------------------------------------------------*/
2198
2199static void putXER_SO ( IRExpr* e )
2200{
2201   IRExpr* so;
2202   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2203   so = binop(Iop_And8, e, mkU8(1));
2204   stmt( IRStmt_Put( OFFB_XER_SO, so ) );
2205}
2206
2207static void putXER_OV ( IRExpr* e )
2208{
2209   /* Interface to write XER[OV] */
2210   IRExpr* ov;
2211   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2212   ov = binop(Iop_And8, e, mkU8(1));
2213   stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
2214}
2215
2216static void putXER_OV32 ( IRExpr* e )
2217{
2218   /*Interface to write XER[OV32] */
2219   IRExpr* ov;
2220   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2221   ov = binop(Iop_And8, e, mkU8(1));
2222
2223   /* The OV32 bit was added to XER in ISA 3.0.  Do not write unless we
2224    * ISA 3.0 or beyond is supported. */
2225   if( OV32_CA32_supported )
2226      stmt( IRStmt_Put( OFFB_XER_OV32, ov ) );
2227}
2228
2229static void putXER_CA ( IRExpr* e )
2230{
2231   /* Interface to write XER[CA] */
2232   IRExpr* ca;
2233   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2234   ca = binop(Iop_And8, e, mkU8(1));
2235   stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
2236}
2237
2238static void putXER_CA32 ( IRExpr* e )
2239{
2240   /* Interface to write XER[CA32] */
2241   IRExpr* ca;
2242   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2243   ca = binop(Iop_And8, e, mkU8(1));
2244
2245   /* The CA32 bit was added to XER in ISA 3.0.  Do not write unless we
2246    * ISA 3.0 or beyond is supported. */
2247   if( OV32_CA32_supported )
2248      stmt( IRStmt_Put( OFFB_XER_CA32, ca ) );
2249}
2250
2251static void putXER_BC ( IRExpr* e )
2252{
2253   IRExpr* bc;
2254   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2255   bc = binop(Iop_And8, e, mkU8(0x7F));
2256   stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
2257}
2258
2259static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
2260{
2261   return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
2262}
2263
2264static IRExpr* /* :: Ity_I32 */ getXER_SO_32 ( void )
2265{
2266   return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
2267}
2268
2269static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
2270{
2271   return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
2272}
2273
2274static IRExpr* /* :: Ity_I8 */ getXER_OV32 ( void )
2275{
2276   return IRExpr_Get( OFFB_XER_OV32, Ity_I8 );
2277}
2278
2279static IRExpr* /* :: Ity_I32 */ getXER_OV_32 ( void )
2280{
2281   /* get XER[OV], 32-bit interface */
2282   return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
2283}
2284
2285static IRExpr* /* :: Ity_I32 */ getXER_OV32_32 ( void )
2286{
2287   /* get XER[OV32], 32-bit interface */
2288   return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV32()), mkU32(1) );
2289}
2290
2291static IRExpr* /* :: Ity_I32 */ getXER_CA_32 ( void )
2292{
2293   /* get XER[CA], 32-bit interface */
2294   IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
2295   return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
2296}
2297
2298static IRExpr* /* :: Ity_I32 */ getXER_CA32_32 ( void )
2299{
2300   /* get XER[CA32], 32-bit interface */
2301   IRExpr* ca = IRExpr_Get( OFFB_XER_CA32, Ity_I8 );
2302   return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
2303}
2304
2305static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
2306{
2307   return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2308}
2309
2310static IRExpr* /* :: Ity_I32 */ getXER_BC_32 ( void )
2311{
2312   IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2313   return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
2314}
2315
2316
2317/* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
2318   %XER.SO accordingly. */
2319
2320static IRExpr* calculate_XER_OV_32( UInt op, IRExpr* res,
2321                                    IRExpr* argL, IRExpr* argR )
2322{
2323   IRTemp  t64;
2324   IRExpr* xer_ov;
2325
2326#  define INT32_MIN 0x80000000
2327
2328#  define XOR2(_aa,_bb) \
2329      binop(Iop_Xor32,(_aa),(_bb))
2330
2331#  define XOR3(_cc,_dd,_ee) \
2332      binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
2333
2334#  define AND3(_ff,_gg,_hh) \
2335      binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
2336
2337#define NOT(_jj) \
2338      unop(Iop_Not32, (_jj))
2339
2340   switch (op) {
2341   case /* 0  */ PPCG_FLAG_OP_ADD:
2342   case /* 1  */ PPCG_FLAG_OP_ADDE:
2343      /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
2344      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2345      xer_ov
2346         = AND3( XOR3(argL,argR,mkU32(-1)),
2347                 XOR2(argL,res),
2348                 mkU32(INT32_MIN) );
2349      /* xer_ov can only be 0 or 1<<31 */
2350      xer_ov
2351         = binop(Iop_Shr32, xer_ov, mkU8(31) );
2352      break;
2353
2354   case /* 2  */ PPCG_FLAG_OP_DIVW:
2355      /* (argL == INT32_MIN && argR == -1) || argR == 0 */
2356      xer_ov
2357         = mkOR1(
2358              mkAND1(
2359                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
2360                 binop(Iop_CmpEQ32, argR, mkU32(-1))
2361              ),
2362              binop(Iop_CmpEQ32, argR, mkU32(0) )
2363           );
2364      xer_ov
2365         = unop(Iop_1Uto32, xer_ov);
2366      break;
2367
2368   case /* 3  */ PPCG_FLAG_OP_DIVWU:
2369      /* argR == 0 */
2370      xer_ov
2371         = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
2372      break;
2373
2374   case /* 4  */ PPCG_FLAG_OP_MULLW:
2375      /* OV true if result can't be represented in 32 bits
2376         i.e sHi != sign extension of sLo */
2377      t64 = newTemp(Ity_I64);
2378      assign( t64, binop(Iop_MullS32, argL, argR) );
2379      xer_ov
2380         = binop( Iop_CmpNE32,
2381                  unop(Iop_64HIto32, mkexpr(t64)),
2382                  binop( Iop_Sar32,
2383                         unop(Iop_64to32, mkexpr(t64)),
2384                         mkU8(31))
2385                  );
2386      xer_ov
2387         = unop(Iop_1Uto32, xer_ov);
2388      break;
2389
2390   case /* 5  */ PPCG_FLAG_OP_NEG:
2391      /* argL == INT32_MIN */
2392      xer_ov
2393         = unop( Iop_1Uto32,
2394                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
2395      break;
2396
2397   case /* 6  */ PPCG_FLAG_OP_SUBF:
2398   case /* 7  */ PPCG_FLAG_OP_SUBFC:
2399   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2400      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
2401      xer_ov
2402         = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
2403                 XOR2(NOT(argL),res),
2404                 mkU32(INT32_MIN) );
2405      /* xer_ov can only be 0 or 1<<31 */
2406      xer_ov
2407         = binop(Iop_Shr32, xer_ov, mkU8(31) );
2408      break;
2409
2410   case PPCG_FLAG_OP_DIVWEU:
2411      xer_ov
2412               = binop( Iop_Or32,
2413                        unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2414                        unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
2415      break;
2416
2417   case PPCG_FLAG_OP_DIVWE:
2418
2419      /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
2420       * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
2421       * an overflow is implied.
2422       */
2423      xer_ov = binop( Iop_Or32,
2424                      unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2425                      unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
2426                              mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
2427                                      binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
2428      break;
2429
2430
2431
2432   default:
2433      vex_printf("calculate_XER_OV_32: op = %u\n", op);
2434      vpanic("calculate_XER_OV_32(ppc)");
2435   }
2436
2437   return xer_ov;
2438
2439#  undef INT32_MIN
2440#  undef AND3
2441#  undef XOR3
2442#  undef XOR2
2443#  undef NOT
2444}
2445
2446static void set_XER_OV_OV32_32( UInt op, IRExpr* res,
2447                                IRExpr* argL, IRExpr* argR )
2448{
2449   IRExpr* xer_ov;
2450
2451   vassert(op < PPCG_FLAG_OP_NUMBER);
2452   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
2453   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
2454   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
2455
2456   xer_ov = calculate_XER_OV_32( op, res, argL, argR );
2457
2458   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2459   putXER_OV( unop(Iop_32to8, xer_ov) );
2460   putXER_OV32( unop(Iop_32to8, xer_ov) );
2461}
2462
2463static IRExpr* calculate_XER_OV_64( UInt op, IRExpr* res,
2464                                 IRExpr* argL, IRExpr* argR )
2465{
2466   IRExpr* xer_ov;
2467
2468#  define INT64_MIN 0x8000000000000000ULL
2469
2470#  define XOR2(_aa,_bb) \
2471      binop(Iop_Xor64,(_aa),(_bb))
2472
2473#  define XOR3(_cc,_dd,_ee) \
2474      binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
2475
2476#  define AND3(_ff,_gg,_hh) \
2477      binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
2478
2479#define NOT(_jj) \
2480      unop(Iop_Not64, (_jj))
2481
2482   switch (op) {
2483   case /* 0  */ PPCG_FLAG_OP_ADD:
2484   case /* 1  */ PPCG_FLAG_OP_ADDE:
2485      /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
2486      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2487      xer_ov
2488         = AND3( XOR3(argL,argR,mkU64(-1)),
2489                 XOR2(argL,res),
2490                 mkU64(INT64_MIN) );
2491      /* xer_ov can only be 0 or 1<<63 */
2492      xer_ov
2493         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2494      break;
2495
2496   case /* 2  */ PPCG_FLAG_OP_DIVW:
2497      /* (argL == INT64_MIN && argR == -1) || argR == 0 */
2498      xer_ov
2499         = mkOR1(
2500              mkAND1(
2501                 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
2502                 binop(Iop_CmpEQ64, argR, mkU64(-1))
2503              ),
2504              binop(Iop_CmpEQ64, argR, mkU64(0) )
2505           );
2506      break;
2507
2508   case /* 3  */ PPCG_FLAG_OP_DIVWU:
2509      /* argR == 0 */
2510      xer_ov
2511         = binop(Iop_CmpEQ64, argR, mkU64(0));
2512      break;
2513
2514   case /* 4  */ PPCG_FLAG_OP_MULLW: {
2515      /* OV true if result can't be represented in 64 bits
2516         i.e sHi != sign extension of sLo */
2517      xer_ov
2518         = binop( Iop_CmpNE32,
2519                  unop(Iop_64HIto32, res),
2520                  binop( Iop_Sar32,
2521                         unop(Iop_64to32, res),
2522                         mkU8(31))
2523                  );
2524      break;
2525   }
2526
2527   case /* 5  */ PPCG_FLAG_OP_NEG:
2528      /* argL == INT64_MIN */
2529      xer_ov
2530         = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
2531      break;
2532
2533   case /* 6  */ PPCG_FLAG_OP_SUBF:
2534   case /* 7  */ PPCG_FLAG_OP_SUBFC:
2535   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2536      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2537      xer_ov
2538         = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
2539                 XOR2(NOT(argL),res),
2540                 mkU64(INT64_MIN) );
2541      /* xer_ov can only be 0 or 1<<63 */
2542      xer_ov
2543         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2544      break;
2545
2546   case /* 14 */ PPCG_FLAG_OP_DIVDE:
2547
2548      /* If argR == 0, we must set the OV bit.  But there's another condition
2549       * where we can get overflow set for divde . . . when the
2550       * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
2551       * both dividend and divisor are non-zero, it implies an overflow.
2552       */
2553      xer_ov
2554                  = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2555                           mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
2556                                   mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
2557                                           binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
2558      break;
2559
2560   case /* 17 */ PPCG_FLAG_OP_DIVDEU:
2561     /* If argR == 0 or if argL >= argR, set OV. */
2562     xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2563                         binop( Iop_CmpLE64U, argR, argL ) );
2564     break;
2565
2566   case /* 18 */ PPCG_FLAG_OP_MULLD: {
2567      IRTemp  t128;
2568      /* OV true if result can't be represented in 64 bits
2569         i.e sHi != sign extension of sLo */
2570      t128 = newTemp(Ity_I128);
2571      assign( t128, binop(Iop_MullS64, argL, argR) );
2572      xer_ov
2573         = binop( Iop_CmpNE64,
2574                  unop(Iop_128HIto64, mkexpr(t128)),
2575                  binop( Iop_Sar64,
2576                         unop(Iop_128to64, mkexpr(t128)),
2577                         mkU8(63))
2578                  );
2579      break;
2580   }
2581
2582   default:
2583      vex_printf("calculate_XER_OV_64: op = %u\n", op);
2584      vpanic("calculate_XER_OV_64(ppc64)");
2585   }
2586
2587   return xer_ov;
2588
2589#  undef INT64_MIN
2590#  undef AND3
2591#  undef XOR3
2592#  undef XOR2
2593#  undef NOT
2594}
2595
2596static void set_XER_OV_64( UInt op, IRExpr* res,
2597                           IRExpr* argL, IRExpr* argR )
2598{
2599   IRExpr* xer_ov;
2600   vassert(op < PPCG_FLAG_OP_NUMBER);
2601   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
2602   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
2603   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
2604
2605   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2606   xer_ov = calculate_XER_OV_64( op, res, argL, argR);
2607   putXER_OV( unop(Iop_1Uto8, xer_ov) );
2608
2609   /* Update the summary overflow */
2610   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2611}
2612
2613static void update_SO( void ) {
2614   /* Update the summary overflow bit */
2615   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2616}
2617
2618static void copy_OV_to_OV32( void ) {
2619   /* Update the OV32 to match OV */
2620   putXER_OV32( getXER_OV() );
2621}
2622
2623static void set_XER_OV_OV32 ( IRType ty, UInt op, IRExpr* res,
2624                              IRExpr* argL, IRExpr* argR )
2625{
2626   if (ty == Ity_I32) {
2627      set_XER_OV_OV32_32( op, res, argL, argR );
2628   } else {
2629      IRExpr* xer_ov_32;
2630      set_XER_OV_64( op, res, argL, argR );
2631      xer_ov_32 = calculate_XER_OV_32( op, unop(Iop_64to32, res),
2632                                       unop(Iop_64to32, argL),
2633                                       unop(Iop_64to32, argR));
2634      putXER_OV32( unop(Iop_32to8, xer_ov_32) );
2635   }
2636}
2637
2638static void set_XER_OV_OV32_SO ( IRType ty, UInt op, IRExpr* res,
2639                                 IRExpr* argL, IRExpr* argR )
2640{
2641   if (ty == Ity_I32) {
2642      set_XER_OV_OV32_32( op, res, argL, argR );
2643   } else {
2644      IRExpr* xer_ov_32;
2645      set_XER_OV_64( op, res, argL, argR );
2646      xer_ov_32 = calculate_XER_OV_32( op, unop(Iop_64to32, res),
2647                                       unop(Iop_64to32, argL),
2648                                       unop(Iop_64to32, argR));
2649      putXER_OV32( unop(Iop_32to8, xer_ov_32) );
2650   }
2651   update_SO();
2652}
2653
2654
2655
2656/* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2657   value being OLDCA.  Set %XER.CA accordingly. */
2658
2659static IRExpr* calculate_XER_CA_32 ( UInt op, IRExpr* res,
2660                                     IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2661{
2662   IRExpr* xer_ca;
2663
2664   switch (op) {
2665   case /* 0 */ PPCG_FLAG_OP_ADD:
2666      /* res <u argL */
2667      xer_ca
2668         = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
2669      break;
2670
2671   case /* 1 */ PPCG_FLAG_OP_ADDE:
2672      /* res <u argL || (old_ca==1 && res==argL) */
2673      xer_ca
2674         = mkOR1(
2675              binop(Iop_CmpLT32U, res, argL),
2676              mkAND1(
2677                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2678                 binop(Iop_CmpEQ32, res, argL)
2679              )
2680           );
2681      xer_ca
2682         = unop(Iop_1Uto32, xer_ca);
2683      break;
2684
2685   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2686      /* res <u argR || (old_ca==1 && res==argR) */
2687      xer_ca
2688         = mkOR1(
2689              binop(Iop_CmpLT32U, res, argR),
2690              mkAND1(
2691                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2692                 binop(Iop_CmpEQ32, res, argR)
2693              )
2694           );
2695      xer_ca
2696         = unop(Iop_1Uto32, xer_ca);
2697      break;
2698
2699   case /* 7 */ PPCG_FLAG_OP_SUBFC:
2700   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2701      /* res <=u argR */
2702      xer_ca
2703         = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
2704      break;
2705
2706   case /* 10 */ PPCG_FLAG_OP_SRAW:
2707      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2708         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2709         bit of argL. */
2710      /* This term valid for shift amount < 32 only */
2711      xer_ca
2712         = binop(
2713              Iop_And32,
2714              binop(Iop_Sar32, argL, mkU8(31)),
2715              binop( Iop_And32,
2716                     argL,
2717                     binop( Iop_Sub32,
2718                            binop(Iop_Shl32, mkU32(1),
2719                                             unop(Iop_32to8,argR)),
2720                            mkU32(1) )
2721                     )
2722              );
2723      xer_ca
2724         = IRExpr_ITE(
2725              /* shift amt > 31 ? */
2726              binop(Iop_CmpLT32U, mkU32(31), argR),
2727              /* yes -- get sign bit of argL */
2728              binop(Iop_Shr32, argL, mkU8(31)),
2729              /* no -- be like srawi */
2730              unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)))
2731           );
2732      break;
2733
2734   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2735      /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2736         0.  Since the shift amount is known to be in the range
2737         0 .. 31 inclusive the following seems viable:
2738         xer.ca == 1 iff the following is nonzero:
2739         (argL >>s 31)           -- either all 0s or all 1s
2740         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2741      xer_ca
2742         = binop(
2743              Iop_And32,
2744              binop(Iop_Sar32, argL, mkU8(31)),
2745              binop( Iop_And32,
2746                     argL,
2747                     binop( Iop_Sub32,
2748                            binop(Iop_Shl32, mkU32(1),
2749                                             unop(Iop_32to8,argR)),
2750                            mkU32(1) )
2751                     )
2752              );
2753      xer_ca
2754         = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2755      break;
2756
2757   default:
2758      vex_printf("set_XER_CA: op = %u\n", op);
2759      vpanic("set_XER_CA(ppc)");
2760   }
2761
2762   return xer_ca;
2763}
2764
2765static void set_XER_CA_32 ( UInt op, IRExpr* res,
2766                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2767{
2768   IRExpr* xer_ca;
2769   vassert(op < PPCG_FLAG_OP_NUMBER);
2770   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
2771   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
2772   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
2773   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
2774
2775   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2776      seems reasonable given that it's always generated by
2777      getXER_CA_32(), which masks it accordingly.  In any case it being
2778      0 or 1 is an invariant of the ppc guest state representation;
2779      if it has any other value, that invariant has been violated. */
2780
2781   xer_ca = calculate_XER_CA_32( op, res, argL, argR, oldca);
2782
2783   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2784   putXER_CA( unop(Iop_32to8, xer_ca) );
2785}
2786
2787static IRExpr* calculate_XER_CA_64 ( UInt op, IRExpr* res,
2788                                     IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2789{
2790   IRExpr* xer_ca;
2791
2792   switch (op) {
2793   case /* 0 */ PPCG_FLAG_OP_ADD:
2794      /* res <u argL */
2795      xer_ca
2796         = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2797      break;
2798
2799   case /* 1 */ PPCG_FLAG_OP_ADDE:
2800      /* res <u argL || (old_ca==1 && res==argL) */
2801      xer_ca
2802         = mkOR1(
2803              binop(Iop_CmpLT64U, res, argL),
2804              mkAND1(
2805                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2806                 binop(Iop_CmpEQ64, res, argL)
2807                 )
2808              );
2809      xer_ca
2810         = unop(Iop_1Uto32, xer_ca);
2811      break;
2812
2813   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2814      /* res <u argR || (old_ca==1 && res==argR) */
2815      xer_ca
2816         = mkOR1(
2817              binop(Iop_CmpLT64U, res, argR),
2818              mkAND1(
2819                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2820                 binop(Iop_CmpEQ64, res, argR)
2821              )
2822           );
2823      xer_ca
2824         = unop(Iop_1Uto32, xer_ca);
2825      break;
2826
2827   case /* 7 */ PPCG_FLAG_OP_SUBFC:
2828   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2829      /* res <=u argR */
2830      xer_ca
2831         = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2832      break;
2833
2834
2835   case /* 10 */ PPCG_FLAG_OP_SRAW:
2836      /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2837         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2838         bit of argL. */
2839         /* This term valid for shift amount < 31 only */
2840
2841      xer_ca
2842         = binop(
2843              Iop_And64,
2844              binop(Iop_Sar64, argL, mkU8(31)),
2845              binop( Iop_And64,
2846                     argL,
2847                     binop( Iop_Sub64,
2848                            binop(Iop_Shl64, mkU64(1),
2849                                             unop(Iop_64to8,argR)),
2850                            mkU64(1) )
2851              )
2852           );
2853      xer_ca
2854         = IRExpr_ITE(
2855              /* shift amt > 31 ? */
2856              binop(Iop_CmpLT64U, mkU64(31), argR),
2857              /* yes -- get sign bit of argL */
2858              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2859              /* no -- be like srawi */
2860              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2861          );
2862      break;
2863
2864   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2865      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2866         Since the shift amount is known to be in the range 0 .. 31
2867         inclusive the following seems viable:
2868         xer.ca == 1 iff the following is nonzero:
2869         (argL >>s 31)           -- either all 0s or all 1s
2870         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2871
2872      xer_ca
2873         = binop(
2874              Iop_And64,
2875              binop(Iop_Sar64, argL, mkU8(31)),
2876              binop( Iop_And64,
2877                     argL,
2878                     binop( Iop_Sub64,
2879                            binop(Iop_Shl64, mkU64(1),
2880                                             unop(Iop_64to8,argR)),
2881                            mkU64(1) )
2882              )
2883           );
2884      xer_ca
2885         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2886      break;
2887
2888
2889   case /* 12 */ PPCG_FLAG_OP_SRAD:
2890      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2891         If it is <= 63, behave like SRADI; else XER.CA is the sign
2892         bit of argL. */
2893         /* This term valid for shift amount < 63 only */
2894
2895      xer_ca
2896         = binop(
2897              Iop_And64,
2898              binop(Iop_Sar64, argL, mkU8(63)),
2899              binop( Iop_And64,
2900                     argL,
2901                     binop( Iop_Sub64,
2902                            binop(Iop_Shl64, mkU64(1),
2903                                             unop(Iop_64to8,argR)),
2904                            mkU64(1) )
2905              )
2906           );
2907      xer_ca
2908         = IRExpr_ITE(
2909              /* shift amt > 63 ? */
2910              binop(Iop_CmpLT64U, mkU64(63), argR),
2911              /* yes -- get sign bit of argL */
2912              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2913              /* no -- be like sradi */
2914              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2915           );
2916      break;
2917
2918
2919   case /* 13 */ PPCG_FLAG_OP_SRADI:
2920      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2921         Since the shift amount is known to be in the range 0 .. 63
2922         inclusive, the following seems viable:
2923         xer.ca == 1 iff the following is nonzero:
2924         (argL >>s 63)           -- either all 0s or all 1s
2925         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2926
2927      xer_ca
2928         = binop(
2929              Iop_And64,
2930              binop(Iop_Sar64, argL, mkU8(63)),
2931              binop( Iop_And64,
2932                     argL,
2933                     binop( Iop_Sub64,
2934                            binop(Iop_Shl64, mkU64(1),
2935                                             unop(Iop_64to8,argR)),
2936                            mkU64(1) )
2937              )
2938           );
2939      xer_ca
2940         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2941      break;
2942
2943   default:
2944      vex_printf("set_XER_CA: op = %u\n", op);
2945      vpanic("set_XER_CA(ppc64)");
2946   }
2947
2948   return xer_ca;
2949}
2950
2951static void set_XER_CA_64 ( UInt op, IRExpr* res,
2952                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2953{
2954   IRExpr* xer_ca;
2955   vassert(op < PPCG_FLAG_OP_NUMBER);
2956   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
2957   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
2958   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
2959   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
2960
2961   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2962      seems reasonable given that it's always generated by
2963      getXER_CA_32(), which masks it accordingly.  In any case it being
2964      0 or 1 is an invariant of the ppc guest state representation;
2965      if it has any other value, that invariant has been violated. */
2966
2967   xer_ca = calculate_XER_CA_64( op, res, argL, argR, oldca );
2968
2969   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2970   putXER_CA( unop(Iop_32to8, xer_ca) );
2971}
2972
2973static void set_XER_CA_CA32 ( IRType ty, UInt op, IRExpr* res,
2974                              IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2975{
2976   if (ty == Ity_I32) {
2977      set_XER_CA_32( op, res, argL, argR, oldca );
2978   } else {
2979      set_XER_CA_64( op, res, argL, argR, oldca );
2980   }
2981}
2982
2983
2984
2985/*------------------------------------------------------------*/
2986/*--- Read/write to guest-state                           --- */
2987/*------------------------------------------------------------*/
2988
2989static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
2990{
2991   IRType ty = mode64 ? Ity_I64 : Ity_I32;
2992   switch (reg) {
2993   case PPC_GST_SPRG3_RO:
2994      return IRExpr_Get( OFFB_SPRG3_RO, ty );
2995
2996   case PPC_GST_CIA:
2997      return IRExpr_Get( OFFB_CIA, ty );
2998
2999   case PPC_GST_LR:
3000      return IRExpr_Get( OFFB_LR, ty );
3001
3002   case PPC_GST_CTR:
3003      return IRExpr_Get( OFFB_CTR, ty );
3004
3005   case PPC_GST_VRSAVE:
3006      return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
3007
3008   case PPC_GST_VSCR:
3009      return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
3010                              mkU32(MASK_VSCR_VALID));
3011
3012   case PPC_GST_CR: {
3013      /* Synthesise the entire CR into a single word.  Expensive. */
3014#     define FIELD(_n)                                               \
3015         binop(Iop_Shl32,                                            \
3016               unop(Iop_8Uto32,                                      \
3017                    binop(Iop_Or8,                                   \
3018                          binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
3019                          binop(Iop_And8, getCR0(_n), mkU8(1))       \
3020                    )                                                \
3021               ),                                                    \
3022               mkU8(4 * (7-(_n)))                                    \
3023         )
3024      return binop(Iop_Or32,
3025                   binop(Iop_Or32,
3026                         binop(Iop_Or32, FIELD(0), FIELD(1)),
3027                         binop(Iop_Or32, FIELD(2), FIELD(3))
3028                         ),
3029                   binop(Iop_Or32,
3030                         binop(Iop_Or32, FIELD(4), FIELD(5)),
3031                         binop(Iop_Or32, FIELD(6), FIELD(7))
3032                         )
3033                   );
3034#     undef FIELD
3035   }
3036
3037   case PPC_GST_XER:
3038      return binop(Iop_Or32,
3039                   binop(Iop_Or32,
3040                         binop(Iop_Or32,
3041                               binop( Iop_Shl32, getXER_SO_32(), mkU8(31)),
3042                               binop( Iop_Shl32, getXER_OV_32(), mkU8(30))),
3043                         binop(Iop_Or32,
3044                               binop( Iop_Shl32, getXER_CA_32(), mkU8(29)),
3045                               getXER_BC_32())),
3046                   binop(Iop_Or32,
3047                         binop( Iop_Shl32, getXER_OV32_32(), mkU8(19)),
3048                         binop( Iop_Shl32, getXER_CA32_32(), mkU8(18))));
3049
3050   case PPC_GST_TFHAR:
3051      return IRExpr_Get( OFFB_TFHAR, ty );
3052
3053   case PPC_GST_TEXASR:
3054      return IRExpr_Get( OFFB_TEXASR, ty );
3055
3056   case PPC_GST_TEXASRU:
3057      return IRExpr_Get( OFFB_TEXASRU, ty );
3058
3059   case PPC_GST_TFIAR:
3060      return IRExpr_Get( OFFB_TFIAR, ty );
3061
3062   case PPC_GST_PPR:
3063      return IRExpr_Get( OFFB_PPR, ty );
3064
3065   case PPC_GST_PPR32:
3066      return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) );
3067
3068   case PPC_GST_PSPB:
3069      return IRExpr_Get( OFFB_PSPB, ty );
3070
3071   default:
3072      vex_printf("getGST(ppc): reg = %u", reg);
3073      vpanic("getGST(ppc)");
3074   }
3075}
3076
3077/* Get a masked word from the given reg */
3078static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, ULong mask )
3079{
3080   IRTemp val = newTemp(Ity_I32);
3081   vassert( reg < PPC_GST_MAX );
3082
3083   switch (reg) {
3084
3085   case PPC_GST_FPSCR: {
3086      /* Vex-generated code expects the FPSCR to be set as follows:
3087         all exceptions masked, round-to-nearest.
3088         This corresponds to a FPSCR value of 0x0. */
3089
3090      /* In the lower 32 bits of FPSCR, we're keeping track of the binary
3091       * floating point rounding mode and Floating-point Condition code, so
3092       * if the mask isn't asking for either of these, just return 0x0.
3093       */
3094      if ( mask & ( MASK_FPSCR_C_FPCC | MASK_FPSCR_RN ) ) {
3095         assign( val, binop( Iop_Or32,
3096                             unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ),
3097                             binop( Iop_Shl32,
3098                                    unop( Iop_8Uto32,
3099                                          IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ),
3100                                    mkU8( 12 ) ) ) );
3101      } else {
3102         assign( val, mkU32(0x0) );
3103      }
3104
3105      break;
3106   }
3107
3108   default:
3109      vex_printf("getGST_masked(ppc): reg = %u", reg);
3110      vpanic("getGST_masked(ppc)");
3111   }
3112
3113   if ( mask != 0xFFFFFFFF ) {
3114      return binop(Iop_And32, mkexpr(val), mkU32(mask));
3115   } else {
3116      return mkexpr(val);
3117   }
3118}
3119
3120/* Get a masked word from the given reg */
3121static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
3122   IRExpr * val;
3123   vassert( reg < PPC_GST_MAX );
3124
3125   switch (reg) {
3126
3127   case PPC_GST_FPSCR: {
3128      /* In the upper 32 bits of FPSCR, we're only keeping track
3129       * of the decimal floating point rounding mode, so if the mask
3130       * isn't asking for this, just return 0x0.
3131       */
3132      if (mask & MASK_FPSCR_DRN) {
3133         val = binop( Iop_And32,
3134                      unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
3135                      unop( Iop_64HIto32, mkU64( mask ) ) );
3136      } else {
3137         val = mkU32( 0x0ULL );
3138      }
3139      break;
3140   }
3141
3142   default:
3143      vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
3144      vpanic( "getGST_masked_upper(ppc)" );
3145   }
3146   return val;
3147}
3148
3149
3150/* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
3151   and return it at the bottom of an I32; the top 27 bits are
3152   guaranteed to be zero. */
3153static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
3154{
3155   UInt shft, mask;
3156
3157   vassert( fld < 8 );
3158   vassert( reg < PPC_GST_MAX );
3159
3160   shft = 4*(7-fld);
3161   mask = 0xF<<shft;
3162
3163   switch (reg) {
3164   case PPC_GST_XER:
3165      vassert(fld ==7);
3166      return binop(Iop_Or32,
3167                   binop(Iop_Or32,
3168                         binop(Iop_Shl32, getXER_SO_32(), mkU8(3)),
3169                         binop(Iop_Shl32, getXER_OV_32(), mkU8(2))),
3170                   binop(      Iop_Shl32, getXER_CA_32(), mkU8(1)));
3171      break;
3172
3173   default:
3174      if (shft == 0)
3175         return getGST_masked( reg, mask );
3176      else
3177         return binop(Iop_Shr32,
3178                      getGST_masked( reg, mask ),
3179                      mkU8(toUChar( shft )));
3180   }
3181}
3182
3183static void putGST ( PPC_GST reg, IRExpr* src )
3184{
3185   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3186   IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
3187   vassert( reg < PPC_GST_MAX );
3188   switch (reg) {
3189   case PPC_GST_IP_AT_SYSCALL:
3190      vassert( ty_src == ty );
3191      stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
3192      break;
3193   case PPC_GST_CIA:
3194      vassert( ty_src == ty );
3195      stmt( IRStmt_Put( OFFB_CIA, src ) );
3196      break;
3197   case PPC_GST_LR:
3198      vassert( ty_src == ty );
3199      stmt( IRStmt_Put( OFFB_LR, src ) );
3200      break;
3201   case PPC_GST_CTR:
3202      vassert( ty_src == ty );
3203      stmt( IRStmt_Put( OFFB_CTR, src ) );
3204      break;
3205   case PPC_GST_VRSAVE:
3206      vassert( ty_src == Ity_I32 );
3207      stmt( IRStmt_Put( OFFB_VRSAVE,src));
3208      break;
3209   case PPC_GST_VSCR:
3210      vassert( ty_src == Ity_I32 );
3211      stmt( IRStmt_Put( OFFB_VSCR,
3212                        binop(Iop_And32, src,
3213                              mkU32(MASK_VSCR_VALID)) ) );
3214      break;
3215   case PPC_GST_XER:
3216      vassert( ty_src == Ity_I32 );
3217      putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
3218      putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
3219      putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
3220      putXER_OV32( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(19))) );
3221      putXER_CA32( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(18))) );
3222      putXER_BC( unop(Iop_32to8, src) );
3223      break;
3224
3225   case PPC_GST_EMWARN:
3226      vassert( ty_src == Ity_I32 );
3227      stmt( IRStmt_Put( OFFB_EMNOTE,src) );
3228      break;
3229
3230   case PPC_GST_CMSTART:
3231      vassert( ty_src == ty );
3232      stmt( IRStmt_Put( OFFB_CMSTART, src) );
3233      break;
3234
3235   case PPC_GST_CMLEN:
3236      vassert( ty_src == ty );
3237      stmt( IRStmt_Put( OFFB_CMLEN, src) );
3238      break;
3239
3240   case PPC_GST_TEXASR:
3241      vassert( ty_src == Ity_I64 );
3242      stmt( IRStmt_Put( OFFB_TEXASR, src ) );
3243      break;
3244
3245   case PPC_GST_TEXASRU:
3246      vassert( ty_src == Ity_I32 );
3247      stmt( IRStmt_Put( OFFB_TEXASRU, src ) );
3248      break;
3249
3250   case PPC_GST_TFIAR:
3251      vassert( ty_src == Ity_I64 );
3252      stmt( IRStmt_Put( OFFB_TFIAR, src ) );
3253      break;
3254   case PPC_GST_TFHAR:
3255      vassert( ty_src == Ity_I64 );
3256      stmt( IRStmt_Put( OFFB_TFHAR, src ) );
3257      break;
3258
3259   case PPC_GST_PPR32:
3260   case PPC_GST_PPR:
3261      {
3262         /* The Program Priority Register (PPR) stores the priority in
3263          * bits [52:50].  The user setable priorities are:
3264          *
3265          *    001  very low
3266          *    010  low
3267          *    011  medium low
3268          *    100  medium
3269          *    101  medium high
3270          *
3271          * If the argument is not between 0b001 and 0b100 the priority is set
3272          * to 0b100.  The priority can only be set to 0b101 if the the Problem
3273          * State Boost Register is non-zero.  The value of the PPR is not
3274          * changed if the input is not valid.
3275          */
3276
3277         IRTemp not_valid = newTemp(Ity_I64);
3278         IRTemp has_perm = newTemp(Ity_I64);
3279         IRTemp new_src  = newTemp(Ity_I64);
3280         IRTemp PSPB_val = newTemp(Ity_I64);
3281         IRTemp value    = newTemp(Ity_I64);
3282
3283         vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 ));
3284         assign( PSPB_val, binop( Iop_32HLto64,
3285                                  mkU32( 0 ),
3286                                  IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) );
3287         if( reg == PPC_GST_PPR32 ) {
3288            vassert( ty_src == Ity_I32 );
3289            assign( value, binop( Iop_32HLto64,
3290                                  mkU32(0),
3291                                  binop( Iop_And32,
3292                                         binop( Iop_Shr32, src,  mkU8( 18 ) ),
3293                                         mkU32( 0x7 ) ) ) );
3294         } else {
3295            vassert( ty_src == Ity_I64 );
3296            assign( value, binop( Iop_And64,
3297                                  binop( Iop_Shr64, src,  mkU8( 50 ) ),
3298                                  mkU64( 0x7 ) ) );
3299         }
3300         assign( has_perm,
3301                 binop( Iop_And64,
3302                        unop( Iop_1Sto64,
3303                              binop( Iop_CmpEQ64,
3304                                     mkexpr( PSPB_val ),
3305                                     mkU64( 0 ) ) ),
3306                        unop( Iop_1Sto64,
3307                              binop( Iop_CmpEQ64,
3308                                     mkU64( 0x5 ),
3309                                     mkexpr( value ) ) ) ) );
3310         assign( not_valid,
3311                 binop( Iop_Or64,
3312                        unop( Iop_1Sto64,
3313                              binop( Iop_CmpEQ64,
3314                                     mkexpr( value ),
3315                                     mkU64( 0 ) ) ),
3316                        unop( Iop_1Sto64,
3317                              binop( Iop_CmpLT64U,
3318                                     mkU64( 0x5 ),
3319                                     mkexpr( value ) ) ) ) );
3320         assign( new_src,
3321                 binop( Iop_Or64,
3322                        binop( Iop_And64,
3323                               unop( Iop_Not64,
3324                                     mkexpr( not_valid ) ),
3325                               src ),
3326                        binop( Iop_And64,
3327                               mkexpr( not_valid ),
3328                               binop( Iop_Or64,
3329                                      binop( Iop_And64,
3330                                             mkexpr( has_perm),
3331                                             binop( Iop_Shl64,
3332                                                    mkexpr( value ),
3333                                                    mkU8( 50 ) ) ),
3334                                      binop( Iop_And64,
3335                                             IRExpr_Get( OFFB_PPR, ty ),
3336                                             unop( Iop_Not64,
3337                                                   mkexpr( has_perm )
3338                                                   ) ) ) ) ) );
3339
3340                 /* make sure we only set the valid bit field [52:50] */
3341                 stmt( IRStmt_Put( OFFB_PPR,
3342                                   binop( Iop_And64,
3343                                          mkexpr( new_src ),
3344                                          mkU64( 0x1C000000000000) ) ) );
3345      break;
3346      }
3347   default:
3348      vex_printf("putGST(ppc): reg = %u", reg);
3349      vpanic("putGST(ppc)");
3350   }
3351}
3352
3353/* Write masked src to the given reg */
3354static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
3355{
3356   IRType ty = mode64 ? Ity_I64 : Ity_I32;
3357   vassert( reg < PPC_GST_MAX );
3358   vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
3359
3360   switch (reg) {
3361   case PPC_GST_FPSCR: {
3362      /* Allow writes to either binary or decimal floating point
3363         Rounding Mode.
3364      */
3365      /* If any part of |mask| covers FPSCR.RN, update the bits of
3366         FPSCR.RN by copying in |src| for locations where the
3367         corresponding bit in |mask| is 1, and leaving it unchanged
3368         for corresponding |mask| zero bits. */
3369      if (mask & MASK_FPSCR_RN) {
3370         stmt(
3371            IRStmt_Put(
3372               OFFB_FPROUND,
3373               unop(
3374                  Iop_32to8,
3375                  binop(
3376                     Iop_Or32,
3377                     binop(
3378                        Iop_And32,
3379                        unop(Iop_64to32, src),
3380                        mkU32(MASK_FPSCR_RN & mask)
3381                     ),
3382                     binop(
3383                        Iop_And32,
3384                        unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)),
3385                        mkU32(MASK_FPSCR_RN & ~mask)
3386                     )
3387                  )
3388               )
3389            )
3390         );
3391      }
3392
3393      if (mask & MASK_FPSCR_C_FPCC) {
3394         /* FPCC bits are in [47:51] */
3395         stmt(
3396            IRStmt_Put(
3397               OFFB_C_FPCC,
3398               unop(
3399                    Iop_32to8,
3400                    binop(Iop_Shr32,
3401                          binop(
3402                                Iop_Or32,
3403                                binop(
3404                                      Iop_And32,
3405                                      unop(Iop_64to32, src),
3406                                      mkU32(MASK_FPSCR_C_FPCC & mask) ),
3407                                binop(
3408                                      Iop_And32,
3409                                      unop(Iop_8Uto32,
3410                                           IRExpr_Get(OFFB_C_FPCC,Ity_I8)),
3411                                      mkU32(MASK_FPSCR_C_FPCC & ~mask)
3412                                      ) ),
3413                          mkU8( 12 ) )
3414                    ) ) );
3415      }
3416
3417      /* Similarly, update FPSCR.DRN if any bits of |mask|
3418         corresponding to FPSCR.DRN are set. */
3419      if (mask & MASK_FPSCR_DRN) {
3420         stmt(
3421            IRStmt_Put(
3422               OFFB_DFPROUND,
3423               unop(
3424                  Iop_32to8,
3425                  binop(
3426                     Iop_Or32,
3427                     binop(
3428                        Iop_And32,
3429                        unop(Iop_64HIto32, src),
3430                        mkU32((MASK_FPSCR_DRN & mask) >> 32)
3431                     ),
3432                     binop(
3433                        Iop_And32,
3434                        unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)),
3435                        mkU32((MASK_FPSCR_DRN & ~mask) >> 32)
3436                     )
3437                  )
3438               )
3439            )
3440         );
3441      }
3442
3443      /* Give EmNote for attempted writes to:
3444         - Exception Controls
3445         - Non-IEEE Mode
3446      */
3447      if (mask & 0xFC) {  // Exception Control, Non-IEE mode
3448         VexEmNote ew = EmWarn_PPCexns;
3449
3450         /* If any of the src::exception_control bits are actually set,
3451            side-exit to the next insn, reporting the warning,
3452            so that Valgrind's dispatcher sees the warning. */
3453         putGST( PPC_GST_EMWARN, mkU32(ew) );
3454         stmt(
3455            IRStmt_Exit(
3456               binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
3457               Ijk_EmWarn,
3458               mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
3459      }
3460
3461      /* Ignore all other writes */
3462      break;
3463   }
3464
3465   default:
3466      vex_printf("putGST_masked(ppc): reg = %u", reg);
3467      vpanic("putGST_masked(ppc)");
3468   }
3469}
3470
3471/* Write the least significant nibble of src to the specified
3472   REG[FLD] (as per IBM/hardware notation). */
3473static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
3474{
3475   UInt shft;
3476   ULong mask;
3477
3478   vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
3479   vassert( fld < 16 );
3480   vassert( reg < PPC_GST_MAX );
3481
3482   if (fld < 8)
3483      shft = 4*(7-fld);
3484   else
3485      shft = 4*(15-fld);
3486   mask = 0xF;
3487   mask = mask << shft;
3488
3489   switch (reg) {
3490   case PPC_GST_CR:
3491      putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
3492      putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
3493      break;
3494
3495   default:
3496      {
3497         IRExpr * src64 = unop( Iop_32Uto64, src );
3498
3499         if (shft == 0) {
3500            putGST_masked( reg, src64, mask );
3501         } else {
3502            putGST_masked( reg,
3503                           binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
3504                           mask );
3505         }
3506      }
3507   }
3508}
3509
3510static void putFPCC ( IRExpr* e )
3511{
3512   /* The assumption is that the value of the FPCC are passed in the lower
3513    * four bits of a 32 bit value.
3514    *
3515    * Note, the C and FPCC bits which are a field of the FPSCR
3516    * register are stored in their own "register" in
3517    * memory.  The FPCC bits are in the lower 4 bits.  We don't need to
3518    * shift it to the bits to their location in the FPSCR register.  Note,
3519    * not all of the FPSCR register bits are supported.  We are writing all
3520    * of the bits in the FPCC field but not the C field.
3521    */
3522   IRExpr* tmp;
3523
3524   vassert( typeOfIRExpr( irsb->tyenv, e ) == Ity_I32 );
3525   /* Get the C bit field */
3526   tmp = binop( Iop_And32,
3527                mkU32( 0x10 ),
3528                unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ) );
3529
3530   stmt( IRStmt_Put( OFFB_C_FPCC,
3531                     unop( Iop_32to8,
3532                           binop( Iop_Or32, tmp,
3533                                  binop( Iop_And32, mkU32( 0xF ), e ) ) ) ) );
3534
3535}
3536
3537static IRExpr* /* ::Ity_I32 */  getC ( void )
3538{
3539   /* Note, the Floating-Point Result Class Descriptor (C) bit is a field of
3540    * the FPSCR registered are stored in its own "register" in guest state
3541    * with the FPCC bit field.   C | FPCC
3542    */
3543   IRTemp val = newTemp(Ity_I32);
3544
3545   assign( val, binop( Iop_Shr32,
3546                       unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ),
3547                       mkU8( 4 ) ) );
3548   return mkexpr(val);
3549}
3550
3551static IRExpr* /* ::Ity_I32 */  getFPCC ( void )
3552{
3553   /* Note, the FPCC bits are a field of the FPSCR
3554    * register are stored in their own "register" in
3555    * guest state with the C bit field.   C | FPCC
3556    */
3557   IRTemp val = newTemp( Ity_I32 );
3558
3559   assign( val, binop( Iop_And32, unop( Iop_8Uto32,
3560                                        IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ),
3561                       mkU32( 0xF ) ));
3562   return mkexpr(val);
3563}
3564
3565/*------------------------------------------------------------*/
3566/* Helpers for VSX instructions that do floating point
3567 * operations and need to determine if a src contains a
3568 * special FP value.
3569 *
3570 *------------------------------------------------------------*/
3571
3572#define NONZERO_FRAC_MASK 0x000fffffffffffffULL
3573#define FP_FRAC_PART(x) binop( Iop_And64, \
3574                               mkexpr( x ), \
3575                               mkU64( NONZERO_FRAC_MASK ) )
3576
3577#define NONZERO_FRAC_MASK32 0x007fffffULL
3578#define FP_FRAC_PART32(x) binop( Iop_And32,   \
3579                                 mkexpr( x ), \
3580                                 mkU32( NONZERO_FRAC_MASK32 ) )
3581
3582// Returns exponent part of floating point src as I32
3583static IRExpr * fp_exp_part( IRType size, IRTemp src )
3584{
3585   IRExpr *shift_by, *mask, *tsrc;
3586
3587   vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
3588            || ( size == Ity_I64 ) );
3589
3590   if( size == Ity_I16 ) {
3591      /* The 16-bit floating point value is in the lower 16-bits
3592       * of the 32-bit input value.
3593       */
3594      tsrc  = mkexpr( src );
3595      mask  = mkU32( 0x1F );
3596      shift_by = mkU8( 10 );
3597
3598   } else if( size == Ity_I32 ) {
3599      tsrc  = mkexpr( src );
3600      mask  = mkU32( 0xFF );
3601      shift_by = mkU8( 23 );
3602
3603   } else if( size == Ity_I64 ) {
3604      tsrc  = unop( Iop_64HIto32, mkexpr( src ) );
3605      mask  = mkU32( 0x7FF );
3606      shift_by = mkU8( 52 - 32 );
3607
3608   } else {
3609      /*NOTREACHED*/
3610      vassert(0); // Stops gcc complaining at "-Og"
3611   }
3612
3613   return binop( Iop_And32, binop( Iop_Shr32, tsrc, shift_by ), mask );
3614}
3615
3616/* The following functions check the floating point value to see if it
3617   is zero, infinity, NaN, Normalized, Denormalized.
3618*/
3619/* 16-bit floating point number is stored in the lower 16-bits of 32-bit value */
3620#define I16_EXP_MASK       0x7C00
3621#define I16_FRACTION_MASK  0x03FF
3622#define I32_EXP_MASK       0x7F800000
3623#define I32_FRACTION_MASK  0x007FFFFF
3624#define I64_EXP_MASK       0x7FF0000000000000ULL
3625#define I64_FRACTION_MASK  0x000FFFFFFFFFFFFFULL
3626#define V128_EXP_MASK      0x7FFF000000000000ULL
3627#define V128_FRACTION_MASK 0x0000FFFFFFFFFFFFULL  /* upper 64-bit fractional mask */
3628
3629void setup_value_check_args( IRType size, IRTemp *exp_mask, IRTemp *frac_mask,
3630                             IRTemp *zero );
3631
3632void setup_value_check_args( IRType size, IRTemp *exp_mask, IRTemp *frac_mask,
3633                             IRTemp *zero ) {
3634
3635   vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
3636            || ( size == Ity_I64 ) || ( size == Ity_V128 ) );
3637
3638   if( size == Ity_I16 ) {
3639      /* The 16-bit floating point value is in the lower 16-bits of
3640         the 32-bit input value */
3641      *frac_mask = newTemp( Ity_I32 );
3642      *exp_mask  = newTemp( Ity_I32 );
3643      *zero  = newTemp( Ity_I32 );
3644      assign( *exp_mask, mkU32( I16_EXP_MASK ) );
3645      assign( *frac_mask, mkU32( I16_FRACTION_MASK ) );
3646      assign( *zero, mkU32( 0 ) );
3647
3648   } else if( size == Ity_I32 ) {
3649      *frac_mask = newTemp( Ity_I32 );
3650      *exp_mask  = newTemp( Ity_I32 );
3651      *zero  = newTemp( Ity_I32 );
3652      assign( *exp_mask, mkU32( I32_EXP_MASK ) );
3653      assign( *frac_mask, mkU32( I32_FRACTION_MASK ) );
3654      assign( *zero, mkU32( 0 ) );
3655
3656   } else if( size == Ity_I64 ) {
3657      *frac_mask = newTemp( Ity_I64 );
3658      *exp_mask  = newTemp( Ity_I64 );
3659      *zero  = newTemp( Ity_I64 );
3660      assign( *exp_mask, mkU64( I64_EXP_MASK ) );
3661      assign( *frac_mask, mkU64( I64_FRACTION_MASK ) );
3662      assign( *zero, mkU64( 0 ) );
3663
3664   } else {
3665      /* V128 is converted to upper and lower 64 bit values, */
3666      /* uses 64-bit operators and temps */
3667      *frac_mask = newTemp( Ity_I64 );
3668      *exp_mask  = newTemp( Ity_I64 );
3669      *zero  = newTemp( Ity_I64 );
3670      assign( *exp_mask, mkU64( V128_EXP_MASK ) );
3671      /* upper 64-bit fractional mask */
3672      assign( *frac_mask, mkU64( V128_FRACTION_MASK ) );
3673      assign( *zero, mkU64( 0 ) );
3674   }
3675}
3676
3677/* Helper function for the various function which check the value of
3678   the floating point value.
3679*/
3680static IRExpr * exponent_compare( IRType size, IRTemp src,
3681                                  IRTemp exp_mask, IRExpr *exp_val )
3682{
3683   IROp opAND, opCmpEQ;
3684
3685   if( ( size == Ity_I16 ) || ( size == Ity_I32 ) )  {
3686      /* The 16-bit floating point value is in the lower 16-bits of
3687         the 32-bit input value */
3688      opAND = Iop_And32;
3689      opCmpEQ = Iop_CmpEQ32;
3690
3691   } else {
3692      opAND = Iop_And64;
3693      opCmpEQ = Iop_CmpEQ64;
3694   }
3695
3696   if( size == Ity_V128 ) {
3697      return binop( opCmpEQ,
3698                    binop ( opAND,
3699                            unop( Iop_V128HIto64, mkexpr( src ) ),
3700                            mkexpr( exp_mask ) ),
3701                    exp_val );
3702
3703   } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) )  {
3704      return binop( opCmpEQ,
3705                    binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ),
3706                    exp_val );
3707   } else {
3708      /* 64-bit operands */
3709
3710      if (mode64) {
3711         return binop( opCmpEQ,
3712                       binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ),
3713                       exp_val );
3714      } else {
3715         /* No support for 64-bit compares in 32-bit mode, need to do upper
3716          * and lower parts using 32-bit compare operators.
3717          */
3718         return
3719            mkAND1( binop( Iop_CmpEQ32,
3720                           binop ( Iop_And32,
3721                                   unop(Iop_64HIto32, mkexpr( src ) ),
3722                                   unop(Iop_64HIto32, mkexpr( exp_mask ) ) ),
3723                           unop(Iop_64HIto32, exp_val ) ),
3724                    binop( Iop_CmpEQ32,
3725                           binop ( Iop_And32,
3726                                   unop(Iop_64to32, mkexpr( src ) ),
3727                                   unop(Iop_64to32, mkexpr( exp_mask ) ) ),
3728                           unop(Iop_64to32, exp_val ) ) );
3729      }
3730   }
3731}
3732
3733static IRExpr *fractional_part_compare( IRType size, IRTemp src,
3734                                        IRTemp frac_mask, IRExpr *zero )
3735{
3736   IROp opAND, opCmpEQ;
3737
3738   if( ( size == Ity_I16 ) || ( size == Ity_I32 ) )  {
3739      /*The 16-bit floating point value is in the lower 16-bits of
3740        the 32-bit input value */
3741      opAND = Iop_And32;
3742      opCmpEQ = Iop_CmpEQ32;
3743
3744   } else {
3745      opAND = Iop_And64;
3746      opCmpEQ = Iop_CmpEQ64;
3747   }
3748
3749   if( size == Ity_V128 ) {
3750      /* 128-bit, note we only care if the fractional part is zero so take upper
3751         52-bits of fractional part and lower 64-bits and OR them together and test
3752         for zero.  This keeps the temp variables and operators all 64-bit.
3753      */
3754      return binop( opCmpEQ,
3755                    binop( Iop_Or64,
3756                           binop( opAND,
3757                                  unop( Iop_V128HIto64, mkexpr( src ) ),
3758                                  mkexpr( frac_mask ) ),
3759                           unop( Iop_V128to64, mkexpr( src ) ) ),
3760                    zero );
3761
3762   } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) )  {
3763         return binop( opCmpEQ,
3764                       binop( opAND,  mkexpr( src ), mkexpr( frac_mask ) ),
3765                       zero );
3766   } else {
3767      if (mode64) {
3768         return binop( opCmpEQ,
3769                       binop( opAND,  mkexpr( src ), mkexpr( frac_mask ) ),
3770                       zero );
3771      } else {
3772         /* No support for 64-bit compares in 32-bit mode, need to do upper
3773          * and lower parts using 32-bit compare operators.
3774          */
3775         return
3776            mkAND1( binop( Iop_CmpEQ32,
3777                           binop ( Iop_And32,
3778                                   unop(Iop_64HIto32, mkexpr( src ) ),
3779                                   unop(Iop_64HIto32, mkexpr( frac_mask ) ) ),
3780                           mkU32 ( 0 ) ),
3781                    binop( Iop_CmpEQ32,
3782                           binop ( Iop_And32,
3783                                   unop(Iop_64to32, mkexpr( src ) ),
3784                                   unop(Iop_64to32, mkexpr( frac_mask ) ) ),
3785                           mkU32 ( 0 ) ) );
3786      }
3787   }
3788}
3789
3790// Infinity: exp has all bits set, and fraction is zero; s = 0/1
3791static IRExpr * is_Inf( IRType size, IRTemp src )
3792{
3793   IRExpr *max_exp, *zero_frac;
3794   IRTemp exp_mask, frac_mask, zero;
3795
3796   setup_value_check_args( size, &exp_mask, &frac_mask, &zero );
3797
3798   /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
3799   max_exp = exponent_compare( size, src, exp_mask, mkexpr( exp_mask ) );
3800
3801   /* check fractional part is all zeros */
3802   zero_frac = fractional_part_compare( size, src, frac_mask, mkexpr( zero ) );
3803
3804   return  mkAND1( max_exp, zero_frac );
3805}
3806
3807// Zero: exp is zero and fraction is zero; s = 0/1
3808static IRExpr * is_Zero( IRType size, IRTemp src )
3809{
3810   IRExpr *zero_exp, *zero_frac;
3811   IRTemp exp_mask, frac_mask, zero;
3812
3813   setup_value_check_args( size, &exp_mask, &frac_mask, &zero );
3814
3815   /* check the exponent is all zeros, i.e. (exp AND exp_mask) = zero */
3816   zero_exp = exponent_compare( size, src, exp_mask, mkexpr( zero ) );
3817
3818   /* check fractional part is all zeros */
3819   zero_frac = fractional_part_compare( size, src, frac_mask, mkexpr( zero ) );
3820
3821   return  mkAND1( zero_exp, zero_frac );
3822}
3823
3824/*  SNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '1'
3825 *  QNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '0'
3826 */
3827static IRExpr * is_NaN( IRType size, IRTemp src )
3828{
3829   IRExpr *max_exp, *not_zero_frac;
3830   IRTemp exp_mask, frac_mask, zero;
3831
3832   setup_value_check_args( size, &exp_mask, &frac_mask, &zero );
3833
3834   /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
3835   max_exp = exponent_compare( size, src, exp_mask, mkexpr( exp_mask ) );
3836
3837   /* check fractional part is not zero */
3838   not_zero_frac = unop( Iop_Not1,
3839                         fractional_part_compare( size, src, frac_mask,
3840                                                  mkexpr( zero ) ) );
3841
3842   return  mkAND1( max_exp, not_zero_frac );
3843}
3844
3845/* Denormalized number has a zero exponent and non zero fraction. */
3846static IRExpr * is_Denorm( IRType size, IRTemp src )
3847{
3848   IRExpr *zero_exp, *not_zero_frac;
3849   IRTemp exp_mask, frac_mask, zero;
3850
3851   setup_value_check_args( size, &exp_mask, &frac_mask, &zero );
3852
3853   /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
3854   zero_exp = exponent_compare( size, src, exp_mask, mkexpr( zero ) );
3855
3856   /* check fractional part is not zero */
3857   not_zero_frac = unop( Iop_Not1,
3858                         fractional_part_compare( size, src, frac_mask,
3859                                                  mkexpr( zero ) ) );
3860
3861   return  mkAND1( zero_exp, not_zero_frac );
3862}
3863
3864/* Normalized number has exponent between 1 and max_exp -1, or in other words
3865   the exponent is not zero and not equal to the max exponent value. */
3866static IRExpr * is_Norm( IRType size, IRTemp src )
3867{
3868   IRExpr *not_zero_exp, *not_max_exp;
3869   IRTemp exp_mask, zero;
3870
3871   vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
3872            || ( size == Ity_I64 ) || ( size == Ity_V128 ) );
3873
3874   if( size == Ity_I16 ) {
3875      /* The 16-bit floating point value is in the lower 16-bits of
3876         the 32-bit input value */
3877      exp_mask = newTemp( Ity_I32 );
3878      zero = newTemp( Ity_I32 );
3879      assign( exp_mask, mkU32( I16_EXP_MASK ) );
3880      assign( zero,  mkU32( 0 ) );
3881
3882   } else if( size == Ity_I32 ) {
3883      exp_mask = newTemp( Ity_I32 );
3884      zero = newTemp( Ity_I32 );
3885      assign( exp_mask, mkU32( I32_EXP_MASK ) );
3886      assign( zero, mkU32( 0 ) );
3887
3888   } else if( size == Ity_I64 ) {
3889      exp_mask = newTemp( Ity_I64 );
3890      zero = newTemp( Ity_I64 );
3891      assign( exp_mask, mkU64( I64_EXP_MASK ) );
3892      assign( zero, mkU64( 0 ) );
3893
3894   } else {
3895      /* V128 is converted to upper and lower 64 bit values, */
3896      /* uses 64-bit operators and temps */
3897      exp_mask = newTemp( Ity_I64 );
3898      zero = newTemp( Ity_I64 );
3899      assign( exp_mask, mkU64( V128_EXP_MASK ) );
3900      assign( zero, mkU64( 0 ) );
3901   }
3902
3903   not_zero_exp = unop( Iop_Not1,
3904                        exponent_compare( size, src,
3905                                          exp_mask, mkexpr( zero ) ) );
3906   not_max_exp = unop( Iop_Not1,
3907                       exponent_compare( size, src,
3908                                         exp_mask, mkexpr( exp_mask ) ) );
3909
3910   return  mkAND1( not_zero_exp, not_max_exp );
3911}
3912
3913
3914static IRExpr * create_FPCC( IRTemp NaN,   IRTemp inf,
3915                             IRTemp zero,  IRTemp norm,
3916                             IRTemp dnorm, IRTemp pos,
3917                             IRTemp neg ) {
3918   IRExpr *bit0, *bit1, *bit2, *bit3;
3919
3920   /* If the result is NaN then must force bits 1, 2 and 3 to zero
3921    * to get correct result.
3922    */
3923   bit0 = unop( Iop_1Uto32, mkOR1( mkexpr( NaN ), mkexpr( inf ) ) );
3924   bit1 = unop( Iop_1Uto32, mkAND1( mkNOT1( mkexpr( NaN ) ), mkexpr( zero ) ) );
3925   bit2 = unop( Iop_1Uto32,
3926                mkAND1( mkNOT1( mkexpr( NaN ) ),
3927                        mkAND1( mkOR1( mkOR1( mkAND1( mkexpr( pos ),
3928                                                      mkexpr( dnorm ) ),
3929                                              mkAND1( mkexpr( pos ),
3930                                                      mkexpr( norm ) ) ),
3931                                       mkAND1( mkexpr( pos ),
3932                                               mkexpr( inf ) ) ),
3933                                mkAND1( mkNOT1 ( mkexpr( zero ) ),
3934                                        mkNOT1( mkexpr( NaN ) ) ) ) ) );
3935   bit3 = unop( Iop_1Uto32,
3936                mkAND1( mkNOT1( mkexpr( NaN ) ),
3937                        mkAND1( mkOR1( mkOR1( mkAND1( mkexpr( neg ),
3938                                                      mkexpr( dnorm ) ),
3939                                              mkAND1( mkexpr( neg ),
3940                                                      mkexpr( norm ) ) ),
3941                                       mkAND1( mkexpr( neg ),
3942                                               mkexpr( inf ) ) ),
3943                                mkAND1( mkNOT1 ( mkexpr( zero ) ),
3944                                        mkNOT1( mkexpr( NaN ) ) ) ) ) );
3945
3946   return binop( Iop_Or32,
3947                 binop( Iop_Or32,
3948                        bit0,
3949                        binop( Iop_Shl32, bit1, mkU8( 1 ) ) ),
3950                 binop( Iop_Or32,
3951                        binop( Iop_Shl32, bit2, mkU8( 2 ) ),
3952                        binop( Iop_Shl32, bit3, mkU8( 3 ) ) ) );
3953}
3954
3955static IRExpr * create_C( IRTemp NaN,   IRTemp zero,
3956                          IRTemp dnorm, IRTemp pos,
3957                          IRTemp neg )
3958{
3959
3960   return unop( Iop_1Uto32,
3961                mkOR1( mkOR1( mkexpr( NaN ),
3962                              mkAND1( mkexpr( neg ), mkexpr( dnorm ) ) ),
3963                       mkOR1( mkAND1( mkexpr( neg ), mkexpr( zero ) ),
3964                              mkAND1( mkexpr( pos ), mkexpr( dnorm ) ) ) ) );
3965}
3966
3967static void generate_store_FPRF( IRType size, IRTemp src )
3968{
3969   IRExpr *FPCC, *C;
3970   IRTemp NaN = newTemp( Ity_I1 ), inf = newTemp( Ity_I1 );
3971   IRTemp dnorm = newTemp( Ity_I1 ), norm = newTemp( Ity_I1 );
3972   IRTemp pos = newTemp( Ity_I1 ),  neg = newTemp( Ity_I1 );
3973   IRTemp zero = newTemp( Ity_I1 );
3974
3975   IRTemp sign_bit = newTemp( Ity_I1 );
3976   IRTemp value;
3977
3978   vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
3979            || ( size == Ity_I64 ) || ( size == Ity_F128 ) );
3980
3981   vassert( ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) )   == Ity_I32 )
3982            || ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_I64 )
3983            || ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_F128 ) );
3984
3985   if( size == Ity_I16 ) {
3986      /* The 16-bit floating point value is in the lower 16-bits of
3987         the 32-bit input value */
3988      value = newTemp( Ity_I32 );
3989      assign( value, mkexpr( src ) );
3990      assign( sign_bit,
3991              unop ( Iop_32to1,
3992                     binop( Iop_And32,
3993                            binop( Iop_Shr32, mkexpr( value ), mkU8( 15 ) ),
3994                            mkU32( 0x1 ) ) ) );
3995
3996   } else if( size == Ity_I32 ) {
3997      value = newTemp( size );
3998      assign( value, mkexpr( src ) );
3999      assign( sign_bit,
4000              unop ( Iop_32to1,
4001                     binop( Iop_And32,
4002                            binop( Iop_Shr32, mkexpr( value ), mkU8( 31 ) ),
4003                            mkU32( 0x1 ) ) ) );
4004
4005   } else if( size == Ity_I64 ) {
4006      value = newTemp( size );
4007      assign( value, mkexpr( src ) );
4008      assign( sign_bit,
4009              unop ( Iop_64to1,
4010                     binop( Iop_And64,
4011                            binop( Iop_Shr64, mkexpr( value ), mkU8( 63 ) ),
4012                            mkU64( 0x1 ) ) ) );
4013
4014   } else {
4015   /* Move the F128 bit pattern to an integer V128 bit pattern */
4016      value = newTemp( Ity_V128 );
4017      assign( value,
4018              binop( Iop_64HLtoV128,
4019                     unop( Iop_ReinterpF64asI64,
4020                           unop( Iop_F128HItoF64, mkexpr( src ) ) ),
4021                     unop( Iop_ReinterpF64asI64,
4022                           unop( Iop_F128LOtoF64, mkexpr( src ) ) ) ) );
4023
4024      size = Ity_V128;
4025      assign( sign_bit,
4026              unop ( Iop_64to1,
4027                     binop( Iop_And64,
4028                            binop( Iop_Shr64,
4029                                   unop( Iop_V128HIto64, mkexpr( value ) ),
4030                                   mkU8( 63 ) ),
4031                            mkU64( 0x1 ) ) ) );
4032   }
4033
4034   /* Calculate the floating point result field FPRF */
4035   assign( NaN, is_NaN( size, value ) );
4036   assign( inf, is_Inf( size, value ) );
4037   assign( zero, is_Zero( size, value ) );
4038   assign( norm, is_Norm( size, value ) );
4039   assign( dnorm, is_Denorm( size, value ) );
4040   assign( pos, mkAND1( mkNOT1( mkexpr( sign_bit ) ), mkU1( 1 ) ) );
4041   assign( neg, mkAND1( mkexpr( sign_bit ), mkU1( 1 ) ) );
4042
4043   /* create the FPRF bit field
4044    *
4045    *   FPRF field[4:0]   type of value
4046    *      10001           QNaN
4047    *      01001           - infininity
4048    *      01000           - Normalized
4049    *      11000           - Denormalized
4050    *      10010           - zero
4051    *      00010           + zero
4052    *      10100           + Denormalized
4053    *      00100           + Normalized
4054    *      00101           + infinity
4055    */
4056   FPCC = create_FPCC( NaN, inf, zero, norm, dnorm, pos, neg );
4057   C = create_C( NaN, zero, dnorm, pos, neg );
4058
4059   /* Write the C and FPCC fields of the FPRF field */
4060   putC( C );
4061   putFPCC( FPCC );
4062}
4063
4064/* This function takes an Ity_I32 input argument interpreted
4065   as a single-precision floating point value. If src is a
4066   SNaN, it is changed to a QNaN and returned; otherwise,
4067   the original value is returned. */
4068static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src)
4069{
4070#define SNAN_MASK32 0x00400000
4071   IRTemp tmp = newTemp(Ity_I32);
4072   IRTemp mask = newTemp(Ity_I32);
4073   IRTemp is_SNAN = newTemp(Ity_I1);
4074
4075   vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 );
4076   assign(tmp, src);
4077
4078   /* check if input is SNaN, if it is convert to QNaN */
4079   assign( is_SNAN,
4080           mkAND1( is_NaN( Ity_I32, tmp ),
4081                   binop( Iop_CmpEQ32,
4082                          binop( Iop_And32, mkexpr( tmp ),
4083                                 mkU32( SNAN_MASK32 ) ),
4084                          mkU32( 0 ) ) ) );
4085   /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
4086   assign ( mask, binop( Iop_And32,
4087                         unop( Iop_1Sto32, mkexpr( is_SNAN ) ),
4088                         mkU32( SNAN_MASK32 ) ) );
4089   return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) );
4090}
4091
4092
4093/* This helper function performs the negation part of operations of the form:
4094 *    "Negate Multiply-<op>"
4095 *  where "<op>" is either "Add" or "Sub".
4096 *
4097 * This function takes one argument -- the floating point intermediate result (converted to
4098 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
4099 * the operation described above.
4100 */
4101static IRTemp getNegatedResult(IRTemp intermediateResult)
4102{
4103   ULong signbit_mask = 0x8000000000000000ULL;
4104   IRTemp signbit_32 = newTemp(Ity_I32);
4105   IRTemp resultantSignbit = newTemp(Ity_I1);
4106   IRTemp negatedResult = newTemp(Ity_I64);
4107   assign( signbit_32, binop( Iop_Shr32,
4108                          unop( Iop_64HIto32,
4109                                 binop( Iop_And64, mkexpr( intermediateResult ),
4110                                        mkU64( signbit_mask ) ) ),
4111                                 mkU8( 31 ) ) );
4112   /* We negate the signbit if and only if the intermediate result from the
4113    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
4114    */
4115   assign( resultantSignbit,
4116        unop( Iop_Not1,
4117              binop( Iop_CmpEQ32,
4118                     binop( Iop_Xor32,
4119                            mkexpr( signbit_32 ),
4120                            unop( Iop_1Uto32, is_NaN( Ity_I64,
4121                                                      intermediateResult ) ) ),
4122                     mkU32( 1 ) ) ) );
4123
4124   assign( negatedResult,
4125        binop( Iop_Or64,
4126               binop( Iop_And64,
4127                      mkexpr( intermediateResult ),
4128                      mkU64( ~signbit_mask ) ),
4129               binop( Iop_32HLto64,
4130                      binop( Iop_Shl32,
4131                             unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
4132                             mkU8( 31 ) ),
4133                      mkU32( 0 ) ) ) );
4134
4135   return negatedResult;
4136}
4137
4138/* This helper function performs the negation part of operations of the form:
4139 *    "Negate Multiply-<op>"
4140 *  where "<op>" is either "Add" or "Sub".
4141 *
4142 * This function takes one argument -- the floating point intermediate result (converted to
4143 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
4144 * the operation described above.
4145 */
4146static IRTemp getNegatedResult_32(IRTemp intermediateResult)
4147{
4148   UInt signbit_mask = 0x80000000;
4149   IRTemp signbit_32 = newTemp(Ity_I32);
4150   IRTemp resultantSignbit = newTemp(Ity_I1);
4151   IRTemp negatedResult = newTemp(Ity_I32);
4152   assign( signbit_32, binop( Iop_Shr32,
4153                                 binop( Iop_And32, mkexpr( intermediateResult ),
4154                                        mkU32( signbit_mask ) ),
4155                                 mkU8( 31 ) ) );
4156   /* We negate the signbit if and only if the intermediate result from the
4157    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
4158    */
4159   assign( resultantSignbit,
4160        unop( Iop_Not1,
4161              binop( Iop_CmpEQ32,
4162                     binop( Iop_Xor32,
4163                            mkexpr( signbit_32 ),
4164                            unop( Iop_1Uto32, is_NaN( Ity_I32,
4165                                                      intermediateResult ) ) ),
4166                     mkU32( 1 ) ) ) );
4167
4168   assign( negatedResult,
4169           binop( Iop_Or32,
4170                  binop( Iop_And32,
4171                         mkexpr( intermediateResult ),
4172                         mkU32( ~signbit_mask ) ),
4173                  binop( Iop_Shl32,
4174                         unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
4175                         mkU8( 31 ) ) ) );
4176
4177   return negatedResult;
4178}
4179
4180/* This function takes two quad_precision floating point numbers of type
4181   V128 and return 1 if src_A > src_B, 0 otherwise. */
4182static IRExpr * Quad_precision_gt ( IRTemp src_A, IRTemp  src_B )
4183{
4184#define FRAC_MASK64Hi 0x0000ffffffffffffULL
4185#define MASK 0x7FFFFFFFFFFFFFFFULL    /* exclude sign bit in upper 64 bits */
4186#define EXP_MASK 0x7fff
4187
4188   IRType ty = Ity_I64;
4189   IRTemp sign_A = newTemp( ty );
4190   IRTemp sign_B = newTemp( ty );
4191   IRTemp exp_A = newTemp( ty );
4192   IRTemp exp_B = newTemp( ty );
4193   IRTemp frac_A_hi = newTemp( ty );
4194   IRTemp frac_B_hi = newTemp( ty );
4195   IRTemp frac_A_lo = newTemp( ty );
4196   IRTemp frac_B_lo = newTemp( ty );
4197
4198
4199   /* extract exponents, and fractional parts so they can be compared */
4200   assign( sign_A, binop( Iop_Shr64,
4201                          unop( Iop_V128HIto64, mkexpr( src_A ) ),
4202                          mkU8( 63 ) ) );
4203   assign( sign_B, binop( Iop_Shr64,
4204                          unop( Iop_V128HIto64, mkexpr( src_B ) ),
4205                          mkU8( 63 ) ) );
4206   assign( exp_A, binop( Iop_And64,
4207                         binop( Iop_Shr64,
4208                                unop( Iop_V128HIto64, mkexpr( src_A ) ),
4209                                mkU8( 48 ) ),
4210                         mkU64( EXP_MASK ) ) );
4211   assign( exp_B, binop( Iop_And64,
4212                         binop( Iop_Shr64,
4213                                unop( Iop_V128HIto64, mkexpr( src_B ) ),
4214                                mkU8( 48 ) ),
4215                         mkU64( EXP_MASK ) ) );
4216   assign( frac_A_hi, binop( Iop_And64,
4217                             unop( Iop_V128HIto64, mkexpr( src_A ) ),
4218                             mkU64( FRAC_MASK64Hi ) ) );
4219   assign( frac_B_hi, binop( Iop_And64,
4220                             unop( Iop_V128HIto64, mkexpr( src_B ) ),
4221                             mkU64( FRAC_MASK64Hi ) ) );
4222   assign( frac_A_lo, unop( Iop_V128to64, mkexpr( src_A ) ) );
4223   assign( frac_B_lo, unop( Iop_V128to64, mkexpr( src_B ) ) );
4224
4225   IRExpr * A_zero =  mkAND1( binop( Iop_CmpEQ64,
4226                                     binop( Iop_And64,
4227                                            unop( Iop_V128HIto64,
4228                                                  mkexpr( src_A ) ),
4229                                            mkU64( MASK ) ),
4230                                     mkU64( 0 ) ),
4231                              binop( Iop_CmpEQ64,
4232                                     unop( Iop_V128to64, mkexpr( src_A ) ),
4233                                     mkU64( 0 ) ) );
4234   IRExpr * B_zero =  mkAND1( binop( Iop_CmpEQ64,
4235                                     binop( Iop_And64,
4236                                            unop( Iop_V128HIto64,
4237                                                  mkexpr( src_B ) ),
4238                                            mkU64( MASK ) ),
4239                                     mkU64( 0 ) ),
4240                              binop( Iop_CmpEQ64,
4241                                     unop( Iop_V128to64, mkexpr( src_B ) ),
4242                                     mkU64( 0 ) ) );
4243   IRExpr * A_B_zero = mkAND1( A_zero, B_zero );
4244
4245   /* Compare numbers */
4246   IRExpr * both_pos = mkAND1( binop( Iop_CmpEQ64, mkexpr( sign_A ),
4247                                      mkU64( 0 ) ),
4248                               binop( Iop_CmpEQ64, mkexpr( sign_B ),
4249                                      mkU64( 0 ) ) );
4250   IRExpr * both_neg = mkAND1( binop( Iop_CmpEQ64, mkexpr( sign_A ),
4251                                      mkU64( 1 ) ),
4252                               binop( Iop_CmpEQ64, mkexpr( sign_B ),
4253                                      mkU64( 1 ) ) );
4254   IRExpr * sign_eq = binop( Iop_CmpEQ64, mkexpr( sign_A ), mkexpr( sign_B ) );
4255   IRExpr * sign_gt = binop( Iop_CmpLT64U, mkexpr( sign_A ),
4256                             mkexpr( sign_B ) ); /* A pos, B neg */
4257
4258   IRExpr * exp_eq = binop( Iop_CmpEQ64, mkexpr( exp_A ), mkexpr( exp_B ) );
4259   IRExpr * exp_gt = binop( Iop_CmpLT64U, mkexpr( exp_B ), mkexpr( exp_A ) );
4260   IRExpr * exp_lt = binop( Iop_CmpLT64U, mkexpr( exp_A ), mkexpr( exp_B ) );
4261
4262   IRExpr * frac_hi_eq = binop( Iop_CmpEQ64, mkexpr( frac_A_hi),
4263                                mkexpr( frac_B_hi ) );
4264   IRExpr * frac_hi_gt = binop( Iop_CmpLT64U, mkexpr( frac_B_hi ),
4265                                mkexpr( frac_A_hi ) );
4266   IRExpr * frac_hi_lt = binop( Iop_CmpLT64U, mkexpr( frac_A_hi ),
4267                                mkexpr( frac_B_hi ) );
4268
4269   IRExpr * frac_lo_gt = binop( Iop_CmpLT64U, mkexpr( frac_B_lo ),
4270                                mkexpr( frac_A_lo ) );
4271   IRExpr * frac_lo_lt = binop( Iop_CmpLT64U, mkexpr( frac_A_lo ),
4272                                mkexpr( frac_B_lo ) );
4273
4274   /* src_A and src_B both positive */
4275   IRExpr *pos_cmp = mkOR1( exp_gt,
4276                            mkAND1( exp_eq,
4277                                    mkOR1( frac_hi_gt,
4278                                           mkAND1( frac_hi_eq, frac_lo_gt ) )
4279                                    ) );
4280
4281   /* src_A and src_B both negative */
4282   IRExpr *neg_cmp = mkOR1( exp_lt,
4283                            mkAND1( exp_eq,
4284                                    mkOR1( frac_hi_lt,
4285                                           mkAND1( frac_hi_eq, frac_lo_lt ) )
4286                                    ) );
4287
4288   /* Need to check the case where one value is a positive
4289    * zero and the other value is a negative zero
4290    */
4291   return mkAND1( mkNOT1( A_B_zero ),
4292                  mkOR1( sign_gt,
4293                         mkAND1( sign_eq,
4294                                 mkOR1( mkAND1( both_pos, pos_cmp ),
4295                                        mkAND1( both_neg, neg_cmp ) ) ) ) );
4296}
4297
4298/*-----------------------------------------------------------
4299 * Helpers for VX instructions that work on National decimal values,
4300 * Zoned decimal values and BCD values.
4301 *
4302 *------------------------------------------------------------*/
4303static IRExpr * is_National_decimal (IRTemp src)
4304{
4305   /* The src is a 128-bit value containing a sign code in half word 7
4306    * and seven digits in halfwords 0 to 6 (IBM numbering).  A valid
4307    * national decimal value has the following:
4308    *   - the sign code must be 0x002B (positive) or 0x002D (negative)
4309    *   - the digits must be in the range 0x0030 to 0x0039
4310    */
4311   Int i;
4312   IRExpr * valid_pos_sign;
4313   IRExpr * valid_neg_sign;
4314   IRTemp valid_num[8];
4315   IRTemp digit[7];
4316
4317   valid_pos_sign = binop( Iop_CmpEQ64,
4318                           binop( Iop_And64,
4319                                  mkU64( 0xFFFF ),
4320                                  unop( Iop_V128to64, mkexpr( src ) ) ),
4321                           mkU64( 0x002B ) );
4322
4323   valid_neg_sign = binop( Iop_CmpEQ64,
4324                           binop( Iop_And64,
4325                                  mkU64( 0xFFFF ),
4326                                  unop( Iop_V128to64, mkexpr( src ) ) ),
4327                           mkU64( 0x002D ) );
4328
4329   valid_num[0] = newTemp( Ity_I1 );
4330   digit[0] = newTemp( Ity_I64 );
4331   assign( valid_num[0], mkU1( 1 ) );   // Assume true to start
4332
4333   for(i = 0; i < 7; i++) {
4334      valid_num[i+1] = newTemp( Ity_I1 );
4335      digit[i] = newTemp( Ity_I64 );
4336      assign( digit[i], binop( Iop_And64,
4337                               unop( Iop_V128to64,
4338                                     binop( Iop_ShrV128,
4339                                            mkexpr( src ),
4340                                            mkU8( (7-i)*16 ) ) ),
4341                               mkU64( 0xFFFF ) ) );
4342
4343      assign( valid_num[i+1],
4344              mkAND1( mkexpr( valid_num[i] ),
4345                      mkAND1( binop( Iop_CmpLE64U,
4346                                     mkexpr( digit[i] ),
4347                                     mkU64( 0x39 ) ),
4348                              binop( Iop_CmpLE64U,
4349                                     mkU64( 0x30 ),
4350                                     mkexpr( digit[i] ) ) ) ) );
4351   }
4352
4353   return mkAND1( mkOR1( valid_pos_sign, valid_neg_sign),
4354                  mkexpr( valid_num[7] ) );
4355}
4356
4357static IRExpr * is_Zoned_decimal (IRTemp src, UChar ps)
4358{
4359   /* The src is a 128-bit value containing a sign code the least significant
4360    * two bytes. The upper pairs of bytes contain digits.  A valid Zoned
4361    * decimal value has the following:
4362    *   - the sign code must be between 0x0X to 0xFX inclusive (X - don't care)
4363    *   - bits [0:3] of each digit must be equal to 0x3
4364    *   - bits [4:7] of each digit must be between 0x0 and 0x9
4365    *
4366    *  If ps = 0
4367    *     Positive sign codes are: 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xA, 0xB
4368    *       (note 0bX0XX XXXX  is positive)
4369    *
4370    *     Negative sign codes are 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF
4371    *       (note 0bX1XX XXXX  is negative)
4372    *
4373    *  If ps = 1, then the sign code must be in the range 0xA to 0xF
4374    *     Positive sign codes are: 0xA, 0xC, 0xE, 0xF
4375    *
4376    *     Negative sign codes are 0xB, 0xD
4377    */
4378   Int i, mask_hi, mask_lo;
4379   IRExpr *valid_range;
4380   IRTemp valid_num[16];
4381   IRTemp digit[15];
4382
4383   /* check the range of the sign value based on the value of ps */
4384   valid_range = mkOR1(
4385                       mkAND1( binop( Iop_CmpEQ64,
4386                                      mkU64( 1 ),
4387                                      mkU64( ps ) ),
4388                               mkAND1( binop( Iop_CmpLE64U,
4389                                              binop( Iop_And64,
4390                                                     mkU64( 0xF0 ),
4391                                                     unop( Iop_V128to64,
4392                                                           mkexpr( src ) ) ),
4393
4394                                              mkU64( 0xF0 ) ),
4395                                       binop( Iop_CmpLE64U,
4396                                              mkU64( 0xA0 ),
4397                                              binop( Iop_And64,
4398                                                     mkU64( 0xF0 ),
4399                                                     unop( Iop_V128to64,
4400                                                           mkexpr( src ) ))))),
4401                       binop( Iop_CmpEQ64,
4402                              mkU64( 0 ),
4403                              mkU64( ps ) ) );
4404
4405   valid_num[0] = newTemp( Ity_I1 );
4406   assign( valid_num[0], mkU1( 1) );   // Assume true to start
4407
4408   if (ps == 0) {
4409      mask_hi = 0x39;
4410      mask_lo = 0x30;
4411   } else {
4412      mask_hi = 0xF9;
4413      mask_lo = 0xF0;
4414   }
4415
4416   for(i = 0; i < 15; i++) {
4417      valid_num[i+1] = newTemp( Ity_I1 );
4418      digit[i] = newTemp( Ity_I64 );
4419      assign( digit[i], binop( Iop_And64,
4420                               unop( Iop_V128to64,
4421                                     binop( Iop_ShrV128,
4422                                            mkexpr( src ),
4423                                            mkU8( (15-i)*8 ) ) ),
4424                               mkU64( 0xFF ) ) );
4425
4426      assign( valid_num[i+1],
4427              mkAND1( mkexpr( valid_num[i] ),
4428                      mkAND1( binop( Iop_CmpLE64U,
4429                                     mkexpr( digit[i] ),
4430                                     mkU64( mask_hi ) ),
4431                              binop( Iop_CmpLE64U,
4432                                     mkU64( mask_lo ),
4433                                     mkexpr( digit[i] ) ) ) ) );
4434   }
4435
4436   return mkAND1( valid_range, mkexpr( valid_num[15] ) );
4437}
4438
4439static IRExpr * CmpGT128U ( IRExpr *src1, IRExpr *src2 )
4440{
4441   /* Unsigend compare of two 128-bit values */
4442   IRExpr *pos_upper_gt, *pos_upper_eq, *pos_lower_gt;
4443
4444   pos_upper_gt = binop( Iop_CmpLT64U,
4445                         unop( Iop_V128HIto64, src2 ),
4446                         unop( Iop_V128HIto64, src1 ) );
4447   pos_upper_eq = binop( Iop_CmpEQ64,
4448                         unop( Iop_V128HIto64, src1 ),
4449                         unop( Iop_V128HIto64, src2 ) );
4450   pos_lower_gt = binop( Iop_CmpLT64U,
4451                         unop( Iop_V128to64, src2),
4452                         unop( Iop_V128to64, src1) );
4453   return mkOR1( pos_upper_gt,
4454                 mkAND1( pos_upper_eq,
4455                         pos_lower_gt ) );
4456}
4457
4458
4459static IRExpr * is_BCDstring128 ( const VexAbiInfo* vbi,
4460                                  UInt Signed, IRExpr *src )
4461{
4462
4463   IRTemp valid = newTemp( Ity_I64 );
4464
4465   /* The src is a 128-bit value containing a MAX_DIGITS BCD digits and
4466    * a sign. The upper bytes are BCD values between 0x0 and 0x9.  The sign
4467    * byte is the least significant byte. This function returns 64-bit 1
4468    * value if sign and digits are valid, 0 otherwise.
4469    *
4470    * This function was originally written using IR code.  It has been
4471    * replaced with a clean helper due to the large amount of IR code
4472    * needed by this function.
4473    */
4474   assign( valid,
4475           mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4476                          "is_BCDstring128_helper",
4477                          fnptr_to_fnentry( vbi, &is_BCDstring128_helper ),
4478                          mkIRExprVec_3( mkU64( Signed ),
4479                                         unop( Iop_V128HIto64, src ),
4480                                         unop( Iop_V128to64, src ) ) ) );
4481   return mkexpr( valid );
4482}
4483
4484static IRExpr * BCDstring_zero (IRExpr *src)
4485{
4486   /* The src is a 128-bit value containing a BCD string.  The function
4487    * returns a 1 if the BCD string values are all zero, 0 otherwise.
4488    */
4489   IRTemp tsrc = newTemp( Ity_V128 );
4490   assign( tsrc, src);
4491
4492   if ( mode64 ) {
4493      return mkAND1( binop( Iop_CmpEQ64,
4494                            mkU64( 0 ),
4495                            unop( Iop_V128HIto64,
4496                                  mkexpr( tsrc ) ) ),
4497                     binop( Iop_CmpEQ64,
4498                            mkU64( 0 ),
4499                            unop( Iop_V128to64,
4500                                  mkexpr( tsrc ) ) ) );
4501   } else {
4502      /* make this work in 32-bit mode */
4503      return mkAND1(
4504                    mkAND1( binop( Iop_CmpEQ32,
4505                                   mkU32( 0 ),
4506                                   unop( Iop_64HIto32,
4507                                         unop( Iop_V128HIto64,
4508                                               mkexpr( tsrc ) ) ) ),
4509                            binop( Iop_CmpEQ32,
4510                                   mkU32( 0 ),
4511                                   unop( Iop_64to32,
4512                                         unop( Iop_V128HIto64,
4513                                               mkexpr( tsrc ) ) ) ) ),
4514                    mkAND1( binop( Iop_CmpEQ32,
4515                                   mkU32( 0 ),
4516                                   unop( Iop_64HIto32,
4517                                         unop( Iop_V128to64,
4518                                               mkexpr( tsrc ) ) ) ),
4519                            binop( Iop_CmpEQ32,
4520                                   mkU32( 0 ),
4521                                   unop( Iop_64to32,
4522                                         unop( Iop_V128to64,
4523                                               mkexpr( tsrc ) ) ) ) ) );
4524   }
4525}
4526
4527static IRExpr * check_BCD_round (IRExpr *src, IRTemp shift)
4528{
4529   /* The src is a 128-bit value containing 31 BCD digits with the sign in
4530    * the least significant byte. The bytes are BCD values between 0x0 and 0x9.
4531    * This routine checks the BCD digit in position shift (counting from
4532    * the least significant digit). If the digit is greater then five,
4533    * a 1 is returned indicating the string needs to be rounded up,
4534    * otherwise, 0 is returned.  The value of shift (I64) is the index of
4535    * the BCD digit times four bits.
4536    */
4537   return  binop( Iop_CmpLE64U,
4538                  mkU64( 6 ),
4539                  binop( Iop_And64,
4540                         unop( Iop_V128to64,
4541                               binop( Iop_ShrV128,
4542                                      src,
4543                                      unop( Iop_64to8, mkexpr( shift ) ) ) ),
4544                         mkU64( 0xF ) ) );
4545}
4546
4547static IRTemp increment_BCDstring ( const VexAbiInfo* vbi,
4548                                    IRExpr *src, IRExpr *carry_in )
4549{
4550   /* The src is a 128-bit value containing 31 BCD digits with the sign in
4551    * the least significant byte. The bytes are BCD values between 0x0 and 0x9.
4552    * This function returns the BCD string incremented by 1.
4553    *
4554    * Call a clean helper to do the computation as it requires a lot of
4555    * IR code to do this.
4556    *
4557    * The helper function takes a 32-bit BCD string, in a 64-bit value, and
4558    * increments the string by the 32-bi carry in value.
4559    *
4560    * The incremented value is returned in the lower 32-bits of the result.
4561    * The carry out is returned in bits [35:32] of the result.  The
4562    * helper function will be called for each of the four 32-bit strings
4563    * that make up the src string passing the returned carry out to the
4564    * next call.
4565    */
4566   IRTemp bcd_result  = newTemp( Ity_V128 );
4567   IRTemp bcd_result0 = newTemp( Ity_I64 );
4568   IRTemp bcd_result1 = newTemp( Ity_I64 );
4569   IRTemp bcd_result2 = newTemp( Ity_I64 );
4570   IRTemp bcd_result3 = newTemp( Ity_I64 );
4571   IRExpr *bcd_string0, *bcd_string1, *bcd_string2, *bcd_string3;
4572
4573   bcd_string0 = binop( Iop_And64,
4574                        mkU64( 0xFFFFFFFF ), unop( Iop_V128to64, src ) );
4575   bcd_string1 = binop( Iop_Shr64, unop( Iop_V128to64, src ), mkU8( 32 ) );
4576   bcd_string2 = binop( Iop_And64,
4577                        mkU64( 0xFFFFFFFF ), unop( Iop_V128HIto64, src ) );
4578   bcd_string3 = binop( Iop_Shr64, unop( Iop_V128HIto64, src ), mkU8( 32 ) );
4579
4580   assign( bcd_result0,
4581           mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4582                          "increment_BCDstring32_helper",
4583                          fnptr_to_fnentry( vbi,
4584                                            &increment_BCDstring32_helper ),
4585                          mkIRExprVec_3( mkU64( True /*Signed*/ ),
4586                                         bcd_string0,
4587                                         binop( Iop_32HLto64, mkU32( 0 ),
4588                                                carry_in ) ) ) );
4589
4590   assign( bcd_result1,
4591           mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4592                          "increment_BCDstring32_helper",
4593                          fnptr_to_fnentry( vbi,
4594                                            &increment_BCDstring32_helper ),
4595                          mkIRExprVec_3( mkU64( False /*Unsigned*/ ),
4596                                         bcd_string1,
4597                                         binop( Iop_Shr64,
4598                                                mkexpr( bcd_result0 ),
4599                                                mkU8( 32 ) ) ) ) );
4600   assign( bcd_result2,
4601           mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4602                          "increment_BCDstring32_helper",
4603                          fnptr_to_fnentry( vbi,
4604                                            &increment_BCDstring32_helper ),
4605                          mkIRExprVec_3( mkU64( False /*Unsigned*/ ),
4606                                         bcd_string2,
4607                                         binop( Iop_Shr64,
4608                                                mkexpr( bcd_result1 ),
4609                                                mkU8( 32 ) ) ) ) );
4610   assign( bcd_result3,
4611           mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4612                          "increment_BCDstring32_helper",
4613                          fnptr_to_fnentry( vbi,
4614                                            &increment_BCDstring32_helper ),
4615                          mkIRExprVec_3( mkU64( False /*Unsigned*/ ),
4616                                         bcd_string3,
4617                                         binop( Iop_Shr64,
4618                                                mkexpr( bcd_result2 ),
4619                                                mkU8( 32 ) ) ) ) );
4620
4621   /* Put the 128-bit result together from the intermediate results. Remember
4622    * to mask out the carry out from the upper 32 bits of the results.
4623    */
4624   assign( bcd_result,
4625           binop( Iop_64HLtoV128,
4626                  binop( Iop_Or64,
4627                         binop( Iop_And64,
4628                                mkU64( 0xFFFFFFFF ), mkexpr (bcd_result2 ) ),
4629                         binop( Iop_Shl64,
4630                                mkexpr (bcd_result3 ), mkU8( 32 ) ) ),
4631                  binop( Iop_Or64,
4632                         binop( Iop_And64,
4633                                mkU64( 0xFFFFFFFF ), mkexpr (bcd_result0 ) ),
4634                         binop( Iop_Shl64,
4635                                mkexpr (bcd_result1 ), mkU8( 32 ) ) ) ) );
4636   return bcd_result;
4637}
4638
4639static IRExpr * convert_to_zoned ( const VexAbiInfo* vbi,
4640                                   IRExpr *src, IRExpr *upper_byte )
4641{
4642   /* The function takes a V128 packed decimal value and returns
4643    * the value in zoned format.  Note, the sign of the value is ignored.
4644    */
4645   IRTemp result_low = newTemp( Ity_I64 );
4646   IRTemp result_hi  = newTemp( Ity_I64 );
4647   IRTemp result     = newTemp( Ity_V128 );
4648
4649   /* Since we can only return 64-bits from a clean helper, we will
4650    * have to get the lower and upper 64-bits separately.
4651    */
4652
4653   assign( result_low,
4654           mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4655                          "convert_to_zoned_helper",
4656                          fnptr_to_fnentry( vbi, &convert_to_zoned_helper ),
4657                          mkIRExprVec_4( unop( Iop_V128HIto64, src ),
4658                                         unop( Iop_V128to64, src ),
4659                                         upper_byte,
4660                                         mkU64( 0 ) ) ) );
4661
4662   assign( result_hi,
4663           mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4664                          "convert_to_zoned_helper",
4665                          fnptr_to_fnentry( vbi, &convert_to_zoned_helper ),
4666                          mkIRExprVec_4( unop( Iop_V128HIto64, src ),
4667                                         unop( Iop_V128to64, src ),
4668                                         upper_byte,
4669                                         mkU64( 1 ) ) ) );
4670
4671
4672   assign( result,
4673           binop( Iop_64HLtoV128, mkexpr( result_hi ), mkexpr( result_low ) ) );
4674
4675   return mkexpr( result );
4676}
4677
4678static IRExpr * convert_to_national ( const VexAbiInfo* vbi,  IRExpr *src ) {
4679   /* The function takes 128-bit value which has a 64-bit packed decimal
4680    * value in the lower 64-bits of the source.  The packed decimal is
4681    * converted to the national format via a clean helper.  The clean
4682    * helper is used to to the large amount of IR code needed to do the
4683    * conversion.  The helper returns the upper 64-bits of the 128-bit
4684    * result if return_upper != 0.  Otherwise, the lower 64-bits of the
4685    * result is returned.
4686    */
4687   IRTemp result_low = newTemp( Ity_I64 );
4688   IRTemp result_hi  = newTemp( Ity_I64 );
4689   IRTemp result     = newTemp( Ity_V128 );
4690
4691   /* Since we can only return 64-bits from a clean helper, we will
4692    * have to get the lower and upper 64-bits separately.
4693    */
4694
4695   assign( result_low,
4696           mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4697                          "convert_to_national_helper",
4698                          fnptr_to_fnentry( vbi, &convert_to_national_helper ),
4699                          mkIRExprVec_2( unop( Iop_V128to64, src ),
4700                                         mkU64( 0 ) ) ) );
4701
4702   assign( result_hi,
4703           mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4704                          "convert_to_national_helper",
4705                          fnptr_to_fnentry( vbi, &convert_to_national_helper ),
4706                          mkIRExprVec_2( unop( Iop_V128to64, src ),
4707                                         mkU64( 1 ) ) ) );
4708
4709   assign( result,
4710           binop( Iop_64HLtoV128, mkexpr( result_hi ), mkexpr( result_low ) ) );
4711
4712   return mkexpr( result );
4713}
4714
4715static IRExpr * convert_from_zoned ( const VexAbiInfo* vbi, IRExpr *src ) {
4716   /* The function takes 128-bit zoned value and returns a signless 64-bit
4717    * packed decimal value in the lower 64-bits of the 128-bit result.
4718    */
4719   IRTemp result = newTemp( Ity_V128 );
4720
4721   assign( result,
4722           binop( Iop_ShlV128,
4723                  binop( Iop_64HLtoV128,
4724                         mkU64( 0 ),
4725                         mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4726                                        "convert_from_zoned_helper",
4727                                        fnptr_to_fnentry( vbi,
4728                                                          &convert_from_zoned_helper ),
4729                                        mkIRExprVec_2( unop( Iop_V128HIto64,
4730                                                             src ),
4731                                                       unop( Iop_V128to64,
4732                                                             src ) ) ) ),
4733                  mkU8( 4 ) ) );
4734
4735   return mkexpr( result );
4736}
4737
4738static IRExpr * convert_from_national ( const VexAbiInfo* vbi, IRExpr *src ) {
4739   /* The function takes 128-bit national value and returns a 64-bit
4740    * packed decimal value.
4741    */
4742   IRTemp result = newTemp( Ity_I64);
4743
4744   assign( result,
4745           mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4746                          "convert_from_national_helper",
4747                          fnptr_to_fnentry( vbi,
4748                                            &convert_from_national_helper ),
4749                          mkIRExprVec_2( unop( Iop_V128HIto64,
4750                                               src ),
4751                                         unop( Iop_V128to64,
4752                                               src ) ) ) );
4753
4754   return mkexpr( result );
4755}
4756
4757static IRExpr * UNSIGNED_CMP_GT_V128 ( IRExpr *vA, IRExpr *vB ) {
4758   /* This function does an unsigned compare of two V128 values. The
4759    * function is for use in 32-bit mode only as it is expensive.  The
4760    * issue is that compares (GT, LT, EQ) are not supported for operands
4761    * larger then 32-bits when running in 32-bit mode.  The function returns
4762    * a 1-bit expression, 1 for TRUE and 0 for FALSE.
4763    */
4764   IRTemp vA_word0 = newTemp( Ity_I32);
4765   IRTemp vA_word1 = newTemp( Ity_I32);
4766   IRTemp vA_word2 = newTemp( Ity_I32);
4767   IRTemp vA_word3 = newTemp( Ity_I32);
4768   IRTemp vB_word0 = newTemp( Ity_I32);
4769   IRTemp vB_word1 = newTemp( Ity_I32);
4770   IRTemp vB_word2 = newTemp( Ity_I32);
4771   IRTemp vB_word3 = newTemp( Ity_I32);
4772
4773   IRTemp eq_word1 = newTemp( Ity_I1);
4774   IRTemp eq_word2 = newTemp( Ity_I1);
4775   IRTemp eq_word3 = newTemp( Ity_I1);
4776
4777
4778   IRExpr *gt_word0, *gt_word1, *gt_word2, *gt_word3;
4779   IRExpr *eq_word3_2, *eq_word3_2_1;
4780   IRTemp result = newTemp( Ity_I1 );
4781
4782   assign( vA_word0, unop( Iop_64to32, unop( Iop_V128to64, vA ) ) );
4783   assign( vA_word1, unop( Iop_64HIto32, unop( Iop_V128to64, vA ) ) );
4784   assign( vA_word2, unop( Iop_64to32, unop( Iop_V128HIto64, vA ) ) );
4785   assign( vA_word3, unop( Iop_64HIto32, unop( Iop_V128HIto64, vA ) ) );
4786
4787   assign( vB_word0, unop( Iop_64to32, unop( Iop_V128to64, vB ) ) );
4788   assign( vB_word1, unop( Iop_64HIto32, unop( Iop_V128to64, vB ) ) );
4789   assign( vB_word2, unop( Iop_64to32, unop( Iop_V128HIto64, vB ) ) );
4790   assign( vB_word3, unop( Iop_64HIto32, unop( Iop_V128HIto64, vB ) ) );
4791
4792   assign( eq_word3, binop( Iop_CmpEQ32, mkexpr( vA_word3 ),
4793                            mkexpr( vB_word3 ) ) );
4794   assign( eq_word2, binop( Iop_CmpEQ32, mkexpr( vA_word2 ),
4795                            mkexpr( vB_word2 ) ) );
4796   assign( eq_word1, binop( Iop_CmpEQ32, mkexpr( vA_word1 ),
4797                            mkexpr( vB_word1 ) ) );
4798
4799   gt_word3 = binop( Iop_CmpLT32U, mkexpr( vB_word3 ), mkexpr( vA_word3 ) );
4800   gt_word2 = binop( Iop_CmpLT32U, mkexpr( vB_word2 ), mkexpr( vA_word2 ) );
4801   gt_word1 = binop( Iop_CmpLT32U, mkexpr( vB_word1 ), mkexpr( vA_word1 ) );
4802   gt_word0 = binop( Iop_CmpLT32U, mkexpr( vB_word0 ), mkexpr( vA_word0 ) );
4803
4804   eq_word3_2   = mkAND1( mkexpr( eq_word3 ), mkexpr( eq_word2 ) );
4805   eq_word3_2_1 = mkAND1( mkexpr( eq_word1 ), eq_word3_2 );
4806
4807   assign( result, mkOR1(
4808                         mkOR1( gt_word3,
4809                                mkAND1( mkexpr( eq_word3 ), gt_word2 ) ),
4810                         mkOR1( mkAND1( eq_word3_2, gt_word1 ),
4811                                mkAND1( eq_word3_2_1, gt_word0 ) ) ) );
4812   return mkexpr( result );
4813}
4814
4815/*------------------------------------------------------------*/
4816/* Transactional memory helpers
4817 *
4818 *------------------------------------------------------------*/
4819
4820static ULong generate_TMreason( UInt failure_code,
4821                                             UInt persistant,
4822                                             UInt nest_overflow,
4823                                             UInt tm_exact )
4824{
4825   ULong tm_err_code =
4826     ( (ULong) 0) << (63-6)   /* Failure code */
4827     | ( (ULong) persistant) << (63-7)     /* Failure persistant */
4828     | ( (ULong) 0) << (63-8)   /* Disallowed */
4829     | ( (ULong) nest_overflow) << (63-9)   /* Nesting Overflow */
4830     | ( (ULong) 0) << (63-10)  /* Footprint Overflow */
4831     | ( (ULong) 0) << (63-11)  /* Self-Induced Conflict */
4832     | ( (ULong) 0) << (63-12)  /* Non-Transactional Conflict */
4833     | ( (ULong) 0) << (63-13)  /* Transactional Conflict */
4834     | ( (ULong) 0) << (63-14)  /* Translation Invalidation Conflict */
4835     | ( (ULong) 0) << (63-15)  /* Implementation-specific */
4836     | ( (ULong) 0) << (63-16)  /* Instruction Fetch Conflict */
4837     | ( (ULong) 0) << (63-30)  /* Reserved */
4838     | ( (ULong) 0) << (63-31)  /* Abort */
4839     | ( (ULong) 0) << (63-32)  /* Suspend */
4840     | ( (ULong) 0) << (63-33)  /* Reserved */
4841     | ( (ULong) 0) << (63-35)  /* Privilege */
4842     | ( (ULong) 0) << (63-36)  /* Failure Summary */
4843     | ( (ULong) tm_exact) << (63-37)  /* TFIAR Exact */
4844     | ( (ULong) 0) << (63-38)  /* ROT */
4845     | ( (ULong) 0) << (63-51)  /* Reserved */
4846     | ( (ULong) 0) << (63-63);  /* Transaction Level */
4847
4848     return tm_err_code;
4849}
4850
4851static void storeTMfailure( Addr64 err_address, ULong tm_reason,
4852                            Addr64 handler_address )
4853{
4854   putGST( PPC_GST_TFIAR,   mkU64( err_address ) );
4855   putGST( PPC_GST_TEXASR,  mkU64( tm_reason ) );
4856   putGST( PPC_GST_TEXASRU, mkU32( 0 ) );
4857   putGST( PPC_GST_TFHAR,   mkU64( handler_address ) );
4858}
4859
4860/*------------------------------------------------------------*/
4861/*--- Integer Instruction Translation                     --- */
4862/*------------------------------------------------------------*/
4863
4864/*
4865  Integer Arithmetic Instructions
4866*/
4867static Bool dis_int_mult_add ( UInt theInstr )
4868{
4869   /* VA-Form */
4870   UChar rD_addr = ifieldRegDS( theInstr );
4871   UChar rA_addr = ifieldRegA( theInstr );
4872   UChar rB_addr = ifieldRegB( theInstr );
4873   UChar rC_addr = ifieldRegC( theInstr );
4874   UInt  opc2    = IFIELD( theInstr, 0, 6 );
4875   IRType ty     = Ity_I64;
4876   IRTemp rA     = newTemp( ty );
4877   IRTemp rB     = newTemp( ty );
4878   IRTemp rC     = newTemp( ty );
4879   IRTemp rD     = newTemp( ty );
4880   IRTemp tmpLo  = newTemp( Ity_I64 );
4881   IRTemp tmpHi  = newTemp( Ity_I64 );
4882   IRTemp tmp2Hi = newTemp( Ity_I64 );
4883   IRTemp result = newTemp( Ity_I128 );
4884   IRTemp resultLo = newTemp( Ity_I64 );
4885   IRExpr* carryout;
4886
4887   assign( rA, getIReg( rA_addr ) );
4888   assign( rB, getIReg( rB_addr ) );
4889   assign( rC, getIReg( rC_addr ) );
4890
4891   switch (opc2) {
4892   case 0x30:  // maddhd  multiply-add High doubleword signed
4893      DIP("maddhd r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr);
4894
4895      assign( result, binop( Iop_MullS64, mkexpr( rA ), mkexpr( rB ) ) );
4896      assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) );
4897      assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) );
4898
4899      /* Multiply rA and rB then add rC.  If the lower 32-bits of the result
4900       * is less then rC and the result rA * rB, a carry out of the lower 32
4901       * bits occurred and the upper 32 bits must be incremented by 1. Sign
4902       * extend rC and do the add to the upper 64 bits to handle the
4903       * negative case for rC.
4904       */
4905      assign( resultLo, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) );
4906      assign( tmp2Hi, binop( Iop_Add64,
4907                             mkexpr( tmpHi ),
4908                             unop( Iop_1Sto64,
4909                                   unop( Iop_64to1,
4910                                         binop( Iop_Shr64,
4911                                                mkexpr( rC ),
4912                                                mkU8( 63 ) ) ) ) ) );
4913
4914      /* need to do calculation for the upper 32 bit result */
4915      carryout = mkAND1( binop( Iop_CmpLT64U,
4916                                mkexpr( resultLo ), mkexpr( rC ) ),
4917                         binop( Iop_CmpLT64U,
4918                                mkexpr( resultLo ), mkexpr( tmpLo ) ) );
4919      assign( rD, binop( Iop_Add64,
4920                         mkexpr( tmp2Hi ),
4921                         unop( Iop_1Uto64, carryout ) ) );
4922      break;
4923
4924   case 0x31:  // maddhdu   multiply-add High doubleword unsigned
4925      DIP("maddhdu r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr);
4926
4927      assign( result, binop( Iop_MullU64, mkexpr( rA ), mkexpr( rB ) ) );
4928      assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) );
4929      assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) );
4930
4931      /* Add rC, if the lower 32-bits of the result is less then rC and
4932       * tmpLo, a carry out of the lower 32 bits occurred. Upper 32 bits
4933       * must be incremented by 1.
4934       */
4935      assign( resultLo, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) );
4936
4937      /* need to do calculation for the upper 32 bit result */
4938      carryout = mkAND1( binop( Iop_CmpLT64U,
4939                                mkexpr(resultLo), mkexpr( rC ) ),
4940                         binop( Iop_CmpLT64U,
4941                                mkexpr(resultLo), mkexpr( tmpLo ) ) );
4942      assign( rD, binop( Iop_Add64,
4943                         mkexpr( tmpHi ),
4944                         unop( Iop_1Uto64, carryout ) ) );
4945      break;
4946
4947   case 0x33:  // maddld   multiply-add Low doubleword
4948      DIP("maddld r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr);
4949
4950      assign( result, binop( Iop_MullS64, mkexpr( rA ), mkexpr( rB ) ) );
4951      assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) );
4952      assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) );
4953
4954      assign( rD, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) );
4955      break;
4956
4957   default:
4958      vex_printf("dis_int_mult(ppc): unrecognized instruction\n");
4959      return False;
4960   }
4961
4962   putIReg( rD_addr, mkexpr(rD) );
4963
4964   return True;
4965}
4966
4967static Bool dis_int_arith ( UInt theInstr )
4968{
4969   /* D-Form, XO-Form */
4970   UChar opc1    = ifieldOPC(theInstr);
4971   UChar rD_addr = ifieldRegDS(theInstr);
4972   UChar rA_addr = ifieldRegA(theInstr);
4973   UInt  uimm16  = ifieldUIMM16(theInstr);
4974   UChar rB_addr = ifieldRegB(theInstr);
4975   UChar flag_OE = ifieldBIT10(theInstr);
4976   UInt  opc2    = ifieldOPClo9(theInstr);
4977   UChar flag_rC = ifieldBIT0(theInstr);
4978
4979   Long   simm16 = extend_s_16to64(uimm16);
4980   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4981   IRTemp rA     = newTemp(ty);
4982   IRTemp rB     = newTemp(ty);
4983   IRTemp rD     = newTemp(ty);
4984
4985   Bool do_rc = False;
4986
4987   assign( rA, getIReg(rA_addr) );
4988   assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
4989
4990   switch (opc1) {
4991   /* D-Form */
4992   case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
4993      DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
4994      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
4995                         mkSzExtendS16(ty, uimm16) ) );
4996      set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD,
4997                       mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
4998                       mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
4999      break;
5000
5001   case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
5002      DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
5003      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
5004                         mkSzExtendS16(ty, uimm16) ) );
5005      set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD,
5006                       mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
5007                       mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
5008      do_rc = True;  // Always record to CR
5009      flag_rC = 1;
5010      break;
5011
5012   case 0x0E: // addi   (Add Immediate, PPC32 p350)
5013      // li rD,val   == addi rD,0,val
5014      // la disp(rA) == addi rD,rA,disp
5015      if ( rA_addr == 0 ) {
5016         DIP("li r%u,%d\n", rD_addr, (Int)simm16);
5017         assign( rD, mkSzExtendS16(ty, uimm16) );
5018      } else {
5019         DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
5020         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
5021                            mkSzExtendS16(ty, uimm16) ) );
5022      }
5023      break;
5024
5025   case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
5026      // lis rD,val == addis rD,0,val
5027      if ( rA_addr == 0 ) {
5028         DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
5029         assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
5030      } else {
5031         DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (UInt)simm16);
5032         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
5033                            mkSzExtendS32(ty, uimm16 << 16) ) );
5034      }
5035      break;
5036
5037   case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
5038      DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
5039      if (mode64)
5040         assign( rD, unop(Iop_128to64,
5041                          binop(Iop_MullS64, mkexpr(rA),
5042                                mkSzExtendS16(ty, uimm16))) );
5043      else
5044         assign( rD, unop(Iop_64to32,
5045                          binop(Iop_MullS32, mkexpr(rA),
5046                                mkSzExtendS16(ty, uimm16))) );
5047      break;
5048
5049   case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
5050      DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
5051      // rD = simm16 - rA
5052      assign( rD, binop( mkSzOp(ty, Iop_Sub8),
5053                         mkSzExtendS16(ty, uimm16),
5054                         mkexpr(rA)) );
5055      set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFI,
5056                       mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
5057                       mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
5058      break;
5059
5060   /* XO-Form */
5061   case 0x1F:
5062      do_rc = True;    // All below record to CR
5063
5064      switch (opc2) {
5065      case 0x10A: // add  (Add, PPC32 p347)
5066         DIP("add%s%s r%u,r%u,r%u\n",
5067             flag_OE ? "o" : "", flag_rC ? ".":"",
5068             rD_addr, rA_addr, rB_addr);
5069         assign( rD, binop( mkSzOp(ty, Iop_Add8),
5070                            mkexpr(rA), mkexpr(rB) ) );
5071         if (flag_OE) {
5072            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADD,
5073                                mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5074         }
5075         break;
5076
5077      case 0x00A: // addc      (Add Carrying, PPC32 p348)
5078         DIP("addc%s%s r%u,r%u,r%u\n",
5079             flag_OE ? "o" : "", flag_rC ? ".":"",
5080             rD_addr, rA_addr, rB_addr);
5081         assign( rD, binop( mkSzOp(ty, Iop_Add8),
5082                            mkexpr(rA), mkexpr(rB)) );
5083         set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD,
5084                          mkexpr(rD), mkexpr(rA), mkexpr(rB),
5085                          mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
5086         if (flag_OE) {
5087            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADD,
5088                                mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5089         }
5090         break;
5091
5092      case 0x08A: { // adde      (Add Extended, PPC32 p349)
5093         IRTemp old_xer_ca = newTemp(ty);
5094         DIP("adde%s%s r%u,r%u,r%u\n",
5095             flag_OE ? "o" : "", flag_rC ? ".":"",
5096             rD_addr, rA_addr, rB_addr);
5097         // rD = rA + rB + XER[CA]
5098         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5099         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
5100                            binop( mkSzOp(ty, Iop_Add8),
5101                                   mkexpr(rB), mkexpr(old_xer_ca))) );
5102         set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE,
5103                          mkexpr(rD), mkexpr(rA), mkexpr(rB),
5104                          mkexpr(old_xer_ca) );
5105         if (flag_OE) {
5106            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE,
5107                                mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5108         }
5109         break;
5110      }
5111
5112      case 0xAA: {// addex (Add Extended alternate carry bit Z23-form)
5113         DIP("addex r%u,r%u,r%u,%d\n", rD_addr, rA_addr, rB_addr, (Int)flag_OE);
5114         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
5115                            binop( mkSzOp(ty, Iop_Add8), mkexpr(rB),
5116                                   mkWidenFrom8( ty, getXER_OV(), False ) ) ) );
5117
5118         /* CY bit is same as OE bit */
5119         if (flag_OE == 0) {
5120            /* Exception, do not set SO bit */
5121            set_XER_OV_OV32( ty, PPCG_FLAG_OP_ADDE,
5122                             mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5123         } else {
5124            /* CY=1, 2 and 3 (AKA flag_OE) are reserved */
5125            vex_printf("addex instruction, CY = %d is reserved.\n", flag_OE);
5126            vpanic("addex instruction\n");
5127         }
5128         break;
5129      }
5130
5131      case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
5132         IRTemp old_xer_ca = newTemp(ty);
5133         IRExpr *min_one;
5134         if (rB_addr != 0) {
5135            vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
5136            return False;
5137         }
5138         DIP("addme%s%s r%u,r%u,r%u\n",
5139             flag_OE ? "o" : "", flag_rC ? ".":"",
5140             rD_addr, rA_addr, rB_addr);
5141         // rD = rA + (-1) + XER[CA]
5142         // => Just another form of adde
5143         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5144         min_one = mkSzImm(ty, (Long)-1);
5145         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
5146                            binop( mkSzOp(ty, Iop_Add8),
5147                                   min_one, mkexpr(old_xer_ca)) ));
5148         set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE,
5149                          mkexpr(rD), mkexpr(rA), min_one,
5150                          mkexpr(old_xer_ca) );
5151         if (flag_OE) {
5152            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE,
5153                                mkexpr(rD), mkexpr(rA), min_one );
5154         }
5155         break;
5156      }
5157
5158      case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
5159         IRTemp old_xer_ca = newTemp(ty);
5160         if (rB_addr != 0) {
5161            vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
5162            return False;
5163         }
5164         DIP("addze%s%s r%u,r%u,r%u\n",
5165             flag_OE ? "o" : "", flag_rC ? ".":"",
5166             rD_addr, rA_addr, rB_addr);
5167         // rD = rA + (0) + XER[CA]
5168         // => Just another form of adde
5169         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5170         assign( rD, binop( mkSzOp(ty, Iop_Add8),
5171                            mkexpr(rA), mkexpr(old_xer_ca)) );
5172         set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE,
5173                          mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
5174                          mkexpr(old_xer_ca) );
5175         if (flag_OE) {
5176            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE,
5177                                mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
5178         }
5179         break;
5180      }
5181
5182      case 0x1EB: // divw       (Divide Word, PPC32 p388)
5183         DIP("divw%s%s r%u,r%u,r%u\n",
5184             flag_OE ? "o" : "", flag_rC ? ".":"",
5185             rD_addr, rA_addr, rB_addr);
5186         if (mode64) {
5187            /* Note:
5188               XER settings are mode independent, and reflect the
5189               overflow of the low-order 32bit result
5190               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
5191            */
5192            /* rD[hi32] are undefined: setting them to sign of lo32
5193                - makes set_CR0 happy */
5194            IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
5195            IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
5196            assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
5197                                                         divisor) ) );
5198            if (flag_OE) {
5199               set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW,
5200                                   mkexpr(rD), dividend, divisor );
5201            }
5202         } else {
5203            assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
5204            if (flag_OE) {
5205               set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW,
5206                                   mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5207            }
5208         }
5209         /* Note:
5210            if (0x8000_0000 / -1) or (x / 0)
5211            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
5212            => But _no_ exception raised. */
5213         break;
5214
5215      case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
5216         DIP("divwu%s%s r%u,r%u,r%u\n",
5217             flag_OE ? "o" : "", flag_rC ? ".":"",
5218             rD_addr, rA_addr, rB_addr);
5219         if (mode64) {
5220            /* Note:
5221               XER settings are mode independent, and reflect the
5222               overflow of the low-order 32bit result
5223               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
5224            */
5225            IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
5226            IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
5227            assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
5228                                                         divisor) ) );
5229            if (flag_OE) {
5230               set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU,
5231                                   mkexpr(rD), dividend, divisor );
5232            }
5233         } else {
5234            assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
5235            if (flag_OE) {
5236               set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU,
5237                                   mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5238            }
5239         }
5240         /* Note: ditto comment divw, for (x / 0) */
5241         break;
5242
5243      case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
5244         if (flag_OE != 0) {
5245            vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
5246            return False;
5247         }
5248         DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5249             rD_addr, rA_addr, rB_addr);
5250         if (mode64) {
5251            /* rD[hi32] are undefined: setting them to sign of lo32
5252                - makes set_CR0 happy */
5253            assign( rD, binop(Iop_Sar64,
5254                           binop(Iop_Mul64,
5255                                 mk64lo32Sto64( mkexpr(rA) ),
5256                                 mk64lo32Sto64( mkexpr(rB) )),
5257                              mkU8(32)) );
5258         } else {
5259            assign( rD, unop(Iop_64HIto32,
5260                             binop(Iop_MullS32,
5261                                   mkexpr(rA), mkexpr(rB))) );
5262         }
5263         break;
5264
5265      case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
5266         if (flag_OE != 0) {
5267            vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
5268            return False;
5269         }
5270         DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5271             rD_addr, rA_addr, rB_addr);
5272         if (mode64) {
5273            /* rD[hi32] are undefined: setting them to sign of lo32
5274                - makes set_CR0 happy */
5275            assign( rD, binop(Iop_Sar64,
5276                           binop(Iop_Mul64,
5277                                 mk64lo32Uto64( mkexpr(rA) ),
5278                                 mk64lo32Uto64( mkexpr(rB) ) ),
5279                              mkU8(32)) );
5280         } else {
5281            assign( rD, unop(Iop_64HIto32,
5282                             binop(Iop_MullU32,
5283                                   mkexpr(rA), mkexpr(rB))) );
5284         }
5285         break;
5286
5287      case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
5288         DIP("mullw%s%s r%u,r%u,r%u\n",
5289             flag_OE ? "o" : "", flag_rC ? ".":"",
5290             rD_addr, rA_addr, rB_addr);
5291         if (mode64) {
5292            /* rD[hi32] are undefined: setting them to sign of lo32
5293                - set_XER_OV() and set_CR0() depend on this */
5294            IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
5295            IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
5296            assign( rD, binop(Iop_MullS32, a, b) );
5297            if (flag_OE) {
5298               set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_MULLW,
5299                                mkexpr(rD),
5300                                unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
5301            }
5302         } else {
5303            assign( rD, unop(Iop_64to32,
5304                             binop(Iop_MullU32,
5305                                   mkexpr(rA), mkexpr(rB))) );
5306            if (flag_OE) {
5307               set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_MULLW,
5308                                   mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5309            }
5310         }
5311         break;
5312
5313      case 0x068: // neg        (Negate, PPC32 p493)
5314         if (rB_addr != 0) {
5315            vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
5316            return False;
5317         }
5318         DIP("neg%s%s r%u,r%u\n",
5319             flag_OE ? "o" : "", flag_rC ? ".":"",
5320             rD_addr, rA_addr);
5321         // rD = (~rA) + 1
5322         assign( rD, binop( mkSzOp(ty, Iop_Add8),
5323                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
5324                            mkSzImm(ty, 1)) );
5325         if (flag_OE) {
5326            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_NEG,
5327                                mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5328         }
5329         break;
5330
5331      case 0x028: // subf       (Subtract From, PPC32 p537)
5332         DIP("subf%s%s r%u,r%u,r%u\n",
5333             flag_OE ? "o" : "", flag_rC ? ".":"",
5334             rD_addr, rA_addr, rB_addr);
5335         // rD = rB - rA
5336         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
5337                            mkexpr(rB), mkexpr(rA)) );
5338         if (flag_OE) {
5339            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBF,
5340                                mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5341         }
5342         break;
5343
5344      case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
5345         DIP("subfc%s%s r%u,r%u,r%u\n",
5346             flag_OE ? "o" : "", flag_rC ? ".":"",
5347             rD_addr, rA_addr, rB_addr);
5348         // rD = rB - rA
5349         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
5350                            mkexpr(rB), mkexpr(rA)) );
5351         set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFC,
5352                          mkexpr(rD), mkexpr(rA), mkexpr(rB),
5353                          mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
5354         if (flag_OE) {
5355            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFC,
5356                                mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5357         }
5358         break;
5359
5360      case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
5361         IRTemp old_xer_ca = newTemp(ty);
5362         DIP("subfe%s%s r%u,r%u,r%u\n",
5363             flag_OE ? "o" : "", flag_rC ? ".":"",
5364             rD_addr, rA_addr, rB_addr);
5365         // rD = (log not)rA + rB + XER[CA]
5366         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5367         assign( rD, binop( mkSzOp(ty, Iop_Add8),
5368                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
5369                            binop( mkSzOp(ty, Iop_Add8),
5370                                   mkexpr(rB), mkexpr(old_xer_ca))) );
5371         set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE,
5372                          mkexpr(rD), mkexpr(rA), mkexpr(rB),
5373                          mkexpr(old_xer_ca) );
5374         if (flag_OE) {
5375            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE,
5376                                mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5377         }
5378         break;
5379      }
5380
5381      case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
5382         IRTemp old_xer_ca = newTemp(ty);
5383         IRExpr *min_one;
5384         if (rB_addr != 0) {
5385            vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
5386            return False;
5387         }
5388         DIP("subfme%s%s r%u,r%u\n",
5389             flag_OE ? "o" : "", flag_rC ? ".":"",
5390             rD_addr, rA_addr);
5391         // rD = (log not)rA + (-1) + XER[CA]
5392         // => Just another form of subfe
5393         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5394         min_one = mkSzImm(ty, (Long)-1);
5395         assign( rD, binop( mkSzOp(ty, Iop_Add8),
5396                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
5397                            binop( mkSzOp(ty, Iop_Add8),
5398                                   min_one, mkexpr(old_xer_ca))) );
5399         set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE,
5400                          mkexpr(rD), mkexpr(rA), min_one,
5401                          mkexpr(old_xer_ca) );
5402         if (flag_OE) {
5403            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE,
5404                                mkexpr(rD), mkexpr(rA), min_one );
5405         }
5406         break;
5407      }
5408
5409      case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
5410         IRTemp old_xer_ca = newTemp(ty);
5411         if (rB_addr != 0) {
5412            vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
5413            return False;
5414         }
5415         DIP("subfze%s%s r%u,r%u\n",
5416             flag_OE ? "o" : "", flag_rC ? ".":"",
5417             rD_addr, rA_addr);
5418         // rD = (log not)rA + (0) + XER[CA]
5419         // => Just another form of subfe
5420         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5421         assign( rD, binop( mkSzOp(ty, Iop_Add8),
5422                           unop( mkSzOp(ty, Iop_Not8),
5423                                 mkexpr(rA)), mkexpr(old_xer_ca)) );
5424         set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE,
5425                          mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
5426                          mkexpr(old_xer_ca) );
5427         if (flag_OE) {
5428            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE,
5429                                mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
5430         }
5431         break;
5432      }
5433
5434
5435      /* 64bit Arithmetic */
5436      case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
5437         if (flag_OE != 0) {
5438            vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
5439            return False;
5440         }
5441         DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5442             rD_addr, rA_addr, rB_addr);
5443         assign( rD, unop(Iop_128HIto64,
5444                          binop(Iop_MullS64,
5445                                mkexpr(rA), mkexpr(rB))) );
5446
5447         break;
5448
5449      case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
5450         if (flag_OE != 0) {
5451            vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
5452            return False;
5453         }
5454         DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5455             rD_addr, rA_addr, rB_addr);
5456         assign( rD, unop(Iop_128HIto64,
5457                          binop(Iop_MullU64,
5458                                mkexpr(rA), mkexpr(rB))) );
5459         break;
5460
5461      case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
5462         DIP("mulld%s%s r%u,r%u,r%u\n",
5463             flag_OE ? "o" : "", flag_rC ? ".":"",
5464             rD_addr, rA_addr, rB_addr);
5465         assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
5466         if (flag_OE) {
5467            set_XER_OV_64( PPCG_FLAG_OP_MULLD,
5468                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5469            /* OV is set to 1 if product isn't representable.
5470             * In this case also need to set OV32 and SO to 1,
5471             * i.e. copy OV to OV32 and SO.
5472             */
5473            copy_OV_to_OV32();
5474            update_SO();
5475         }
5476         break;
5477
5478      case 0x1E9: // divd (Divide DWord, PPC64 p419)
5479         DIP("divd%s%s r%u,r%u,r%u\n",
5480             flag_OE ? "o" : "", flag_rC ? ".":"",
5481             rD_addr, rA_addr, rB_addr);
5482         assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
5483         if (flag_OE) {
5484            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW,
5485                                mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5486         }
5487         break;
5488         /* Note:
5489            if (0x8000_0000_0000_0000 / -1) or (x / 0)
5490            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
5491            => But _no_ exception raised. */
5492
5493      case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
5494         DIP("divdu%s%s r%u,r%u,r%u\n",
5495             flag_OE ? "o" : "", flag_rC ? ".":"",
5496             rD_addr, rA_addr, rB_addr);
5497         assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
5498         if (flag_OE) {
5499            set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU,
5500                                mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5501         }
5502         break;
5503         /* Note: ditto comment divd, for (x / 0) */
5504
5505      case 0x18B: // divweu (Divide Word Extended Unsigned)
5506      {
5507        /*
5508         *  If (RA) >= (RB), or if an attempt is made to perform the division
5509         *         <anything> / 0
5510         * then the contents of register RD are undefined as are (if Rc=1) the contents of
5511         * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
5512         * to 1.
5513         */
5514         IRTemp res = newTemp(Ity_I32);
5515         IRExpr * dividend, * divisor;
5516         DIP("divweu%s%s r%u,r%u,r%u\n",
5517             flag_OE ? "o" : "", flag_rC ? ".":"",
5518                                         rD_addr, rA_addr, rB_addr);
5519         if (mode64) {
5520            dividend = unop( Iop_64to32, mkexpr( rA ) );
5521            divisor = unop( Iop_64to32, mkexpr( rB ) );
5522            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
5523            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
5524         } else {
5525            dividend = mkexpr( rA );
5526            divisor =  mkexpr( rB );
5527            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
5528            assign( rD, mkexpr( res) );
5529         }
5530
5531         if (flag_OE) {
5532            set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWEU,
5533                                mkexpr(res), dividend, divisor );
5534            update_SO( );
5535         }
5536         break;
5537      }
5538
5539      case 0x1AB: // divwe (Divide Word Extended)
5540      {
5541         /*
5542          * If the quotient cannot be represented in 32 bits, or if an
5543          * attempt is made to perform the division
5544          *      <anything> / 0
5545          * then the contents of register RD are undefined as are (if
5546          * Rc=1) the contents of the LT, GT, and EQ bits of CR
5547          * Field 0. In these cases, if OE=1 then OV is set to 1.
5548          */
5549
5550         IRTemp res = newTemp(Ity_I32);
5551         IRExpr * dividend, * divisor;
5552         DIP("divwe%s%s r%u,r%u,r%u\n",
5553             flag_OE ? "o" : "", flag_rC ? ".":"",
5554                                         rD_addr, rA_addr, rB_addr);
5555         if (mode64) {
5556            dividend = unop( Iop_64to32, mkexpr( rA ) );
5557            divisor = unop( Iop_64to32, mkexpr( rB ) );
5558            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
5559            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
5560         } else {
5561            dividend = mkexpr( rA );
5562            divisor =  mkexpr( rB );
5563            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
5564            assign( rD, mkexpr( res) );
5565         }
5566
5567         if (flag_OE) {
5568            set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWE,
5569                                mkexpr(res), dividend, divisor );
5570            update_SO( );
5571         }
5572         break;
5573      }
5574
5575
5576      case 0x1A9: // divde (Divide Doubleword Extended)
5577        /*
5578         * If the quotient cannot be represented in 64 bits, or if an
5579         * attempt is made to perform the division
5580         *      <anything> / 0
5581         * then the contents of register RD are undefined as are (if
5582         * Rc=1) the contents of the LT, GT, and EQ bits of CR
5583         * Field 0. In these cases, if OE=1 then OV is set to 1.
5584         */
5585         DIP("divde%s%s r%u,r%u,r%u\n",
5586             flag_OE ? "o" : "", flag_rC ? ".":"",
5587             rD_addr, rA_addr, rB_addr);
5588         assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
5589         if (flag_OE) {
5590            set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
5591                           mkexpr( rA ), mkexpr( rB ) );
5592           copy_OV_to_OV32();
5593           update_SO();
5594         }
5595         break;
5596
5597      case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
5598        // Same CR and OV rules as given for divweu above
5599        DIP("divdeu%s%s r%u,r%u,r%u\n",
5600            flag_OE ? "o" : "", flag_rC ? ".":"",
5601            rD_addr, rA_addr, rB_addr);
5602        assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
5603        if (flag_OE) {
5604           set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
5605                          mkexpr( rA ), mkexpr( rB ) );
5606           copy_OV_to_OV32();
5607           update_SO();
5608        }
5609        break;
5610
5611      default:
5612         vex_printf("dis_int_arith(ppc)(opc2)\n");
5613         return False;
5614      }
5615      break;
5616
5617   default:
5618      vex_printf("dis_int_arith(ppc)(opc1)\n");
5619      return False;
5620   }
5621
5622   putIReg( rD_addr, mkexpr(rD) );
5623
5624   if (do_rc && flag_rC) {
5625      set_CR0( mkexpr(rD) );
5626   }
5627   return True;
5628}
5629
5630static Bool dis_modulo_int ( UInt theInstr )
5631{
5632   /* X-Form */
5633   UChar opc1    = ifieldOPC( theInstr );
5634   UInt  opc2    = ifieldOPClo10( theInstr );
5635   UChar rA_addr = ifieldRegA( theInstr );
5636   UChar rB_addr = ifieldRegB( theInstr );
5637   UChar rD_addr = ifieldRegDS( theInstr );
5638   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
5639   IRTemp rD     = newTemp( ty );
5640
5641   switch (opc1) {
5642   /* X-Form */
5643   case 0x1F:
5644      switch (opc2) {
5645      case 0x109: // modud  Modulo Unsigned Double Word
5646         {
5647            IRTemp rA = newTemp( Ity_I64 );
5648            IRTemp rB = newTemp( Ity_I64 );
5649            IRTemp quotient = newTemp( Ity_I64 );
5650            IRTemp quotientTimesDivisor = newTemp( Ity_I64 );
5651            IRTemp remainder = newTemp( Ity_I64 );
5652            IRTemp rB_0   = newTemp( Ity_I64 );    /* all 1's if rB = 0 */
5653
5654            DIP("modud r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5655
5656            assign( rA, getIReg( rA_addr ) );
5657            assign( rB, getIReg( rB_addr ) );
5658
5659            assign( quotient,
5660                    binop( Iop_DivU64, mkexpr( rA ), mkexpr( rB ) ) );
5661
5662            assign( quotientTimesDivisor,
5663                    binop( Iop_Mul64,
5664                           mkexpr( quotient ),
5665                           mkexpr( rB ) ) );
5666
5667            assign( remainder,
5668                    binop( Iop_Sub64,
5669                           mkexpr( rA ),
5670                           mkexpr( quotientTimesDivisor ) ) );
5671
5672            /* Need to match the HW for these special cases
5673             * rB = 0         result all zeros
5674             */
5675            assign( rB_0, unop( Iop_1Sto64,
5676                                binop( Iop_CmpEQ64,
5677                                       mkexpr( rB ),
5678                                       mkU64( 0x0 ) ) ) );
5679
5680            assign (rD, binop( Iop_And64,
5681                               unop( Iop_Not64, mkexpr( rB_0 ) ),
5682                               mkexpr( remainder ) ) );
5683            break;
5684         }
5685
5686      case 0x10B: // moduw  Modulo Unsigned Word
5687         {
5688            IRTemp quotient = newTemp( Ity_I32 );
5689            IRTemp quotientTimesDivisor = newTemp( Ity_I32 );
5690            IRTemp remainder = newTemp( Ity_I32 );
5691
5692            IRTemp rA     = newTemp( Ity_I32 );
5693            IRTemp rB     = newTemp( Ity_I32 );
5694            IRTemp rB_0   = newTemp( Ity_I32 );     /* all 1's if rB = 0 */
5695
5696            DIP("moduw r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5697
5698            if ( ty == Ity_I64 ) {
5699               /* rA and rB are 32 bit values in bits 32:63 of the
5700                * 64-bit register.
5701                */
5702               assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
5703               assign( rB, unop( Iop_64to32, getIReg( rB_addr ) ) );
5704
5705            } else {
5706               assign( rA, getIReg( rA_addr ) );
5707               assign( rB, getIReg( rB_addr ) );
5708            }
5709
5710            assign( quotient,
5711                    binop( Iop_DivU32, mkexpr( rA ), mkexpr( rB ) ) );
5712
5713            assign( quotientTimesDivisor,
5714                    unop( Iop_64to32,
5715                          binop( Iop_MullU32,
5716                                 mkexpr( quotient ),
5717                                 mkexpr( rB ) ) ) );
5718
5719            assign( remainder,
5720                    binop( Iop_Sub32,
5721                           mkexpr( rA ),
5722                           mkexpr( quotientTimesDivisor ) ) );
5723
5724            /* Need to match the HW for these special cases
5725             * rB = 0         result all zeros
5726             */
5727            assign( rB_0, unop( Iop_1Sto32,
5728                                binop( Iop_CmpEQ32,
5729                                       mkexpr( rB ),
5730                                       mkU32( 0x0 ) ) ) );
5731
5732            assign (rD, binop( Iop_32HLto64,
5733                               mkU32( 0 ),
5734                               binop( Iop_And32,
5735                                      unop( Iop_Not32, mkexpr( rB_0 ) ),
5736                                      mkexpr( remainder ) ) ) );
5737            break;
5738         }
5739
5740      case 0x21A: // cnttzw, cnttzw.   Count Trailing Zero Word
5741         {
5742            /* Note cnttzw RA, RS  - RA is dest, RS is source.  But the
5743             * order of the operands in theInst is opc1 RS RA opc2 which has
5744             * the operand fields backwards to what the standard order.
5745             */
5746            UChar rA_address = ifieldRegA(theInstr);
5747            UChar rS_address = ifieldRegDS(theInstr);
5748            IRTemp rA     = newTemp(Ity_I64);
5749            IRTemp rS     = newTemp(Ity_I64);
5750            UChar flag_rC = ifieldBIT0(theInstr);
5751            IRTemp result = newTemp(Ity_I32);
5752
5753            DIP("cnttzw%s r%u,r%u\n",  flag_rC ? "." : "",
5754                rA_address, rS_address);
5755
5756            assign( rS, getIReg( rS_address ) );
5757            assign( result, unop( Iop_Ctz32,
5758                                  unop( Iop_64to32, mkexpr( rS ) ) ) );
5759            assign( rA, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( result ) ) );
5760
5761            if ( flag_rC )
5762               set_CR0( mkexpr( rA ) );
5763
5764            putIReg( rA_address, mkexpr( rA ) );
5765
5766            return True;  /* Return here since this inst is not consistent
5767                           * with the other instructions
5768                           */
5769         }
5770         break;
5771
5772      case 0x23A: // cnttzd, cnttzd.   Count Trailing Zero Double word
5773         {
5774            /* Note cnttzd RA, RS  - RA is dest, RS is source.  But the
5775             * order of the operands in theInst is opc1 RS RA opc2 which has
5776             * the operand order listed backwards to what is standard.
5777             */
5778            UChar rA_address = ifieldRegA(theInstr);
5779            UChar rS_address = ifieldRegDS(theInstr);
5780            IRTemp rA     = newTemp(Ity_I64);
5781            IRTemp rS     = newTemp(Ity_I64);
5782            UChar flag_rC = ifieldBIT0(theInstr);
5783
5784            DIP("cnttzd%s r%u,r%u\n",  flag_rC ? "." : "",
5785                rA_address, rS_address);
5786
5787            assign( rS, getIReg( rS_address ) );
5788            assign( rA, unop( Iop_Ctz64, mkexpr( rS ) ) );
5789
5790            if ( flag_rC == 1 )
5791               set_CR0( mkexpr( rA ) );
5792
5793            putIReg( rA_address, mkexpr( rA ) );
5794
5795            return True;  /* Return here since this inst is not consistent
5796                           * with the other instructions
5797                           */
5798         }
5799         break;
5800
5801      case 0x309: // modsd  Modulo Signed Double Word
5802         {
5803            IRTemp rA     = newTemp( Ity_I64 );
5804            IRTemp rB     = newTemp( Ity_I64 );
5805            IRTemp rA2_63 = newTemp( Ity_I64 );    /* all 1's if rA != -2^63 */
5806            IRTemp rB_0   = newTemp( Ity_I1 );     /* 1 if rB = 0 */
5807            IRTemp rB_1   = newTemp( Ity_I1 );     /* 1 if rB = -1 */
5808            IRTemp rA_1   = newTemp( Ity_I1 );     /* 1 if rA = -1 */
5809            IRTemp resultis0   = newTemp( Ity_I64 );
5810            IRTemp resultisF   = newTemp( Ity_I64 );
5811            IRTemp quotient = newTemp( Ity_I64 );
5812            IRTemp quotientTimesDivisor = newTemp( Ity_I64 );
5813            IRTemp remainder = newTemp( Ity_I64 );
5814            IRTemp tmp  = newTemp( Ity_I64 );
5815
5816            DIP("modsd r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5817
5818            assign( rA, getIReg( rA_addr ) );
5819            assign( rB, getIReg( rB_addr ) );
5820
5821            assign( rA2_63, unop ( Iop_1Sto64,
5822                                   binop( Iop_CmpNE64,
5823                                          mkexpr( rA ),
5824                                          mkU64( 0x8000000000000000 ) ) ) );
5825            assign( rB_0, binop( Iop_CmpEQ64,
5826                                 mkexpr( rB ),
5827                                 mkU64( 0x0 ) ) );
5828
5829            assign( rB_1, binop( Iop_CmpEQ64,
5830                                 mkexpr( rB ),
5831                                 mkU64( 0xFFFFFFFFFFFFFFFF ) ) );
5832
5833            assign( rA_1, binop( Iop_CmpEQ64,
5834                                 mkexpr( rA ),
5835                                 mkU64( 0xFFFFFFFFFFFFFFFF ) ) );
5836
5837            /* Need to match the HW for these special cases
5838             * rA = -2^31 and rB = -1              result all zeros
5839             * rA =  -1 and rB = -1                result all zeros
5840             * rA =  -1 and (rB != -1 AND rB != 0) result all 1's
5841             */
5842            assign( resultis0,
5843                    binop( Iop_Or64,
5844                           mkexpr( rA2_63 ),
5845                           unop ( Iop_1Sto64, mkexpr( rB_1 ) ) ) );
5846            assign( resultisF,
5847                    binop( Iop_And64,
5848                           unop( Iop_1Sto64, mkexpr( rA_1 ) ),
5849                           binop( Iop_And64,
5850                                  unop( Iop_Not64,
5851                                        unop( Iop_1Sto64, mkexpr( rB_0 ) ) ),
5852                                  unop( Iop_Not64,
5853                                        unop( Iop_1Sto64, mkexpr( rB_1 ) ) )
5854                                  ) ) );
5855
5856            /* The following remainder computation works as long as
5857             * rA != -2^63 and rB != -1.
5858             */
5859            assign( quotient,
5860                    binop( Iop_DivS64, mkexpr( rA ), mkexpr( rB ) ) );
5861
5862            assign( quotientTimesDivisor,
5863                    binop( Iop_Mul64,
5864                           mkexpr( quotient ),
5865                           mkexpr( rB ) ) );
5866
5867            assign( remainder,
5868                    binop( Iop_Sub64,
5869                           mkexpr( rA ),
5870                           mkexpr( quotientTimesDivisor ) ) );
5871
5872            assign( tmp, binop( Iop_And64,
5873                                mkexpr( remainder ),
5874                                unop( Iop_Not64,
5875                                      mkexpr( resultis0 ) ) ) );
5876
5877            assign( rD, binop( Iop_Or64,
5878                               binop( Iop_And64,
5879                                      unop (Iop_Not64,
5880                                            mkexpr( resultisF ) ),
5881                                      mkexpr( tmp ) ),
5882                               mkexpr( resultisF ) ) );
5883            break;
5884         }
5885      case 0x30B: // modsw  Modulo Signed Word
5886         {
5887            IRTemp rA     = newTemp( Ity_I32 );
5888            IRTemp rB     = newTemp( Ity_I32 );
5889            IRTemp rA2_32 = newTemp( Ity_I32 );    /* all 1's if rA = -2^32 */
5890            IRTemp rB_0   = newTemp( Ity_I1 );     /* 1 if rB = 0 */
5891            IRTemp rB_1   = newTemp( Ity_I1 );     /* 1 if rB = -1 */
5892            IRTemp rA_1   = newTemp( Ity_I1 );     /* 1 if rA = -1 */
5893            IRTemp resultis0   = newTemp( Ity_I32 );
5894            IRTemp resultisF   = newTemp( Ity_I64 );
5895            IRTemp quotient = newTemp( Ity_I32 );
5896            IRTemp quotientTimesDivisor = newTemp( Ity_I32 );
5897            IRTemp remainder = newTemp( Ity_I32 );
5898            IRTemp tmp  = newTemp( Ity_I64 );
5899
5900            DIP("modsw r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5901
5902            if ( ty == Ity_I64 ) {
5903               /* rA and rB are 32 bit values in bits 32:63 of the
5904                * 64-bit register.
5905                */
5906               assign( rA, unop(Iop_64to32, getIReg(rA_addr) ) );
5907               assign( rB, unop(Iop_64to32, getIReg(rB_addr) ) );
5908
5909            } else {
5910               assign( rA, getIReg(rA_addr) );
5911               assign( rB, getIReg(rB_addr) );
5912            }
5913
5914            assign( rA2_32, unop( Iop_1Sto32,
5915                                  binop( Iop_CmpEQ32,
5916                                         mkexpr( rA ),
5917                                         mkU32( 0x80000000 ) ) ) );
5918            /* If the divisor is zero, then the result is undefined.
5919             * However, we will make the result be zero to match what
5920             * the hardware does.
5921             */
5922            assign( rB_0, binop( Iop_CmpEQ32,
5923                                 mkexpr( rB ),
5924                                 mkU32( 0x0 ) ) );
5925
5926            assign( rB_1, binop( Iop_CmpEQ32,
5927                                 mkexpr( rB ),
5928                                 mkU32( 0xFFFFFFFF ) ) );
5929
5930            assign( rA_1, binop( Iop_CmpEQ32,
5931                                 mkexpr( rA ),
5932                                 mkU32( 0xFFFFFFFF ) ) );
5933
5934            /* Need to match the HW for these special cases
5935             * rA = -2^31 and rB = -1              result all zeros
5936             * rA =  -1 and rB = -1                result all zeros
5937             * rA =  -1 and (rB != -1 AND rB != 0) result all 1's
5938             */
5939            assign( resultis0,
5940                    binop( Iop_Or32,
5941                           unop( Iop_Not32,
5942                                 binop( Iop_And32,
5943                                        mkexpr( rA2_32 ),
5944                                        unop( Iop_1Sto32,
5945                                              mkexpr( rB_1 ) ) ) ),
5946                           binop( Iop_And32,
5947                                  unop( Iop_1Sto32, mkexpr( rA_1 ) ),
5948                                  unop( Iop_1Sto32, mkexpr( rB_1 ) ) ) ) );
5949            assign( resultisF,
5950                    binop( Iop_And64,
5951                           unop( Iop_1Sto64, mkexpr( rA_1 ) ),
5952                           binop( Iop_And64,
5953                                  unop( Iop_Not64,
5954                                        unop( Iop_1Sto64, mkexpr( rB_0 ) ) ),
5955                                  unop( Iop_Not64,
5956                                        unop( Iop_1Sto64, mkexpr( rB_1 ) ) )
5957                                  ) ) );
5958
5959            /* The following remainder computation works as long as
5960             * rA != -2^31 and rB != -1.
5961             */
5962            assign( quotient,
5963                    binop( Iop_DivS32, mkexpr( rA ), mkexpr( rB ) ) );
5964
5965            assign( quotientTimesDivisor,
5966                    unop( Iop_64to32,
5967                          binop( Iop_MullS32,
5968                                 mkexpr( quotient ),
5969                                 mkexpr( rB ) ) ) );
5970
5971            assign( remainder,
5972                    binop( Iop_Sub32,
5973                           mkexpr( rA ),
5974                           mkexpr( quotientTimesDivisor ) ) );
5975
5976            assign( tmp, binop( Iop_32HLto64,
5977                                mkU32( 0 ),
5978                                binop( Iop_And32,
5979                                       mkexpr( remainder ),
5980                                       unop( Iop_Not32,
5981                                             mkexpr( resultis0 ) ) ) ) );
5982
5983            assign( rD, binop( Iop_Or64,
5984                               binop( Iop_And64,
5985                                      unop ( Iop_Not64,
5986                                             mkexpr( resultisF ) ),
5987                                      mkexpr( tmp ) ),
5988                               mkexpr( resultisF ) ) );
5989            break;
5990         }
5991
5992      default:
5993         vex_printf("dis_modulo_int(ppc)(opc2)\n");
5994         return False;
5995      }
5996      break;
5997
5998   default:
5999      vex_printf("dis_modulo_int(ppc)(opc1)\n");
6000      return False;
6001   }
6002
6003   putIReg( rD_addr, mkexpr( rD ) );
6004
6005   return True;
6006}
6007
6008
6009/*
6010  Byte Compare Instructions
6011*/
6012static Bool dis_byte_cmp ( UInt theInstr )
6013{
6014   /* X-Form */
6015   UChar opc1 = ifieldOPC(theInstr);
6016   UInt  opc2 = ifieldOPClo10(theInstr);
6017   UChar rA_addr = ifieldRegA(theInstr);
6018   UChar rB_addr = ifieldRegB(theInstr);
6019   IRTemp rA     = newTemp(Ity_I64);
6020   IRTemp rB     = newTemp(Ity_I64);
6021   UChar L    = toUChar( IFIELD( theInstr, 21, 1 ) );
6022   UChar BF   = toUChar( IFIELD( theInstr, 23, 3 ) );
6023
6024   assign( rA, getIReg(rA_addr) );
6025   assign( rB, getIReg(rB_addr) );
6026
6027   if (opc1 != 0x1F) {
6028      vex_printf("dis_byte_cmp(ppc)(opc1)\n");
6029      return False;
6030   }
6031
6032   switch (opc2) {
6033   case 0xc0: // cmprb (Compare Ranged Byte)
6034      {
6035         IRExpr *value;
6036         IRExpr *hi_1, *lo_1, *hi_2, *lo_2;
6037         IRExpr *inrange_1, *inrange_2;
6038
6039         DIP("cmprb %u,%u,r%u,r%u\n", BF, L, rA_addr, rB_addr);
6040
6041         hi_1 = binop( Iop_Shr64,
6042                       binop( Iop_And64,
6043                              mkexpr( rB ),
6044                              mkU64( 0xFF000000 ) ),
6045                       mkU8( 24 ) );
6046         lo_1 = binop( Iop_Shr64,
6047                       binop( Iop_And64,
6048                              mkexpr( rB ),
6049                              mkU64( 0xFF0000 ) ) ,
6050                       mkU8( 16 ) );
6051         hi_2 = binop( Iop_Shr64,
6052                       binop( Iop_And64,
6053                              mkexpr( rB ),
6054                              mkU64( 0xFF00 ) ),
6055                       mkU8( 8 ) );
6056         lo_2 = binop( Iop_And64,
6057                       mkexpr( rB ),
6058                       mkU64( 0xFF ) );
6059         value = binop( Iop_And64,
6060                        mkexpr( rA ),
6061                        mkU64( 0xFF ) );
6062
6063         inrange_1 = mkAND1( binop( Iop_CmpLE64U, value, hi_1 ),
6064                             mkNOT1( binop( Iop_CmpLT64U, value, lo_1 ) ) );
6065         inrange_2 = mkAND1( binop( Iop_CmpLE64U, value, hi_2 ),
6066                             mkNOT1( binop( Iop_CmpLT64U, value, lo_2 ) ) );
6067
6068         putGST_field( PPC_GST_CR,
6069                       binop( Iop_Shl32,
6070                              binop( Iop_Or32,
6071                                     unop( Iop_1Uto32, inrange_2 ),
6072                                     binop( Iop_And32,
6073                                            mkU32 ( L ),
6074                                            unop( Iop_1Uto32, inrange_1 ) ) ),
6075                              mkU8( 2 ) ),
6076                       BF );
6077      }
6078      break;
6079
6080   case 0xE0: // cmpeqb (Compare Equal Byte)
6081      {
6082         Int i;
6083         IRTemp tmp[9];
6084         IRExpr *value;
6085
6086         DIP("cmpeqb %u,r%u,r%u\n", BF, rA_addr, rB_addr);
6087
6088         value = binop( Iop_And64,
6089                        mkexpr( rA ),
6090                        mkU64( 0xFF ) );
6091
6092         tmp[0] = newTemp(Ity_I32);
6093         assign( tmp[0], mkU32( 0 ) );
6094
6095         for(i = 0; i < 8; i++) {
6096            tmp[i+1] = newTemp(Ity_I32);
6097            assign( tmp[i+1], binop( Iop_Or32,
6098                                     unop( Iop_1Uto32,
6099                                           binop( Iop_CmpEQ64,
6100                                                  value,
6101                                                  binop( Iop_And64,
6102                                                         binop( Iop_Shr64,
6103                                                                mkexpr( rB ),
6104                                                                mkU8( i*8 ) ),
6105                                                         mkU64( 0xFF ) ) ) ),
6106                                     mkexpr( tmp[i] ) ) );
6107         }
6108
6109         putGST_field( PPC_GST_CR,
6110                       binop( Iop_Shl32,
6111                              unop( Iop_1Uto32,
6112                                    mkNOT1( binop( Iop_CmpEQ32,
6113                                                   mkexpr( tmp[8] ),
6114                                                   mkU32( 0 ) ) ) ),
6115                              mkU8( 2 ) ),
6116                       BF );
6117      }
6118      break;
6119
6120   default:
6121      vex_printf("dis_byte_cmp(ppc)(opc2)\n");
6122      return False;
6123   }
6124   return True;
6125}
6126
6127/*
6128 * Integer Miscellaneous instructions
6129 */
6130static Bool dis_int_misc ( UInt theInstr )
6131{
6132   Int wc = IFIELD(theInstr, 21, 2);
6133   UChar opc1 = ifieldOPC(theInstr);
6134   UInt  opc2 = ifieldOPClo10(theInstr);
6135
6136   if ( opc1 != 0x1F ) {
6137      vex_printf("dis_modulo_int(ppc)(opc1)\n");
6138      return False;
6139   }
6140
6141   switch (opc2) {
6142   case 0x01E: // wait, (X-from)
6143      DIP("wait %u\n", wc);
6144
6145      /* The wait instruction causes instruction fetching and execution
6146       * to be suspended.  Instruction fetching and execution are resumed
6147       * when the events specified by the WC field occur.
6148       *
6149       *    0b00   Resume instruction fetching and execution when an
6150       *           exception or an event-based branch exception occurs,
6151       *           or a resume signal from the platform is recieved.
6152       *
6153       *    0b01   Reserved.
6154       *
6155       *  For our purposes, we will just assume the contition is always
6156       * immediately satisfied.
6157       */
6158      break;
6159   default:
6160      vex_printf("dis_int_misc(ppc)(opc2)\n");
6161      return False;
6162}
6163
6164   return True;
6165}
6166
6167/*
6168  Integer Compare Instructions
6169*/
6170static Bool dis_int_cmp ( UInt theInstr )
6171{
6172   /* D-Form, X-Form */
6173   UChar opc1    = ifieldOPC(theInstr);
6174   UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
6175   UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
6176   UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
6177   UChar rA_addr = ifieldRegA(theInstr);
6178   UInt  uimm16  = ifieldUIMM16(theInstr);
6179   UChar rB_addr = ifieldRegB(theInstr);
6180   UInt  opc2    = ifieldOPClo10(theInstr);
6181   UChar b0      = ifieldBIT0(theInstr);
6182
6183   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6184   IRExpr *a = getIReg(rA_addr);
6185   IRExpr *b;
6186
6187   if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
6188      vex_printf("dis_int_cmp(ppc)(flag_L)\n");
6189      return False;
6190   }
6191
6192   if (( b22 != 0 ) && ( opc2 != 0x080 ) ) {   // setb case exception
6193      vex_printf("dis_int_cmp(ppc)(b22)\n");
6194      return False;
6195   }
6196
6197   switch (opc1) {
6198   case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
6199      DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
6200          (Int)extend_s_16to32(uimm16));
6201      b = mkSzExtendS16( ty, uimm16 );
6202      if (flag_L == 1) {
6203         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
6204      } else {
6205         a = mkNarrowTo32( ty, a );
6206         b = mkNarrowTo32( ty, b );
6207         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
6208      }
6209      putCR0( crfD, getXER_SO() );
6210      break;
6211
6212   case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
6213      DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
6214      b = mkSzImm( ty, uimm16 );
6215      if (flag_L == 1) {
6216         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
6217      } else {
6218         a = mkNarrowTo32( ty, a );
6219         b = mkNarrowTo32( ty, b );
6220         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
6221      }
6222      putCR0( crfD, getXER_SO() );
6223      break;
6224
6225   /* X Form */
6226   case 0x1F:
6227      if (b0 != 0) {
6228         vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
6229         return False;
6230      }
6231      b = getIReg(rB_addr);
6232
6233      switch (opc2) {
6234      case 0x000: // cmp (Compare, PPC32 p367)
6235         DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
6236         /* Comparing a reg with itself produces a result which
6237            doesn't depend on the contents of the reg.  Therefore
6238            remove the false dependency, which has been known to cause
6239            memcheck to produce false errors. */
6240         if (rA_addr == rB_addr)
6241            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
6242                    ? mkU64(0)  : mkU32(0);
6243         if (flag_L == 1) {
6244            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
6245         } else {
6246            a = mkNarrowTo32( ty, a );
6247            b = mkNarrowTo32( ty, b );
6248            putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
6249         }
6250         putCR0( crfD, getXER_SO() );
6251         break;
6252
6253      case 0x020: // cmpl (Compare Logical, PPC32 p369)
6254         DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
6255         /* Comparing a reg with itself produces a result which
6256            doesn't depend on the contents of the reg.  Therefore
6257            remove the false dependency, which has been known to cause
6258            memcheck to produce false errors. */
6259         if (rA_addr == rB_addr)
6260            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
6261                    ? mkU64(0)  : mkU32(0);
6262         if (flag_L == 1) {
6263            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
6264         } else {
6265            a = mkNarrowTo32( ty, a );
6266            b = mkNarrowTo32( ty, b );
6267            putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
6268         }
6269         putCR0( crfD, getXER_SO() );
6270         break;
6271
6272      case 0x080: // setb (Set Boolean)
6273         {
6274            UChar rT_addr = ifieldRegDS(theInstr);
6275            Int bfa = IFIELD(theInstr, 18, 3);
6276            IRTemp cr = newTemp(Ity_I32);
6277            IRTemp cr0 = newTemp(Ity_I32);
6278            IRTemp cr1 = newTemp(Ity_I32);
6279            IRTemp result = newTemp(Ity_I64);
6280
6281            DIP("setb r%u,%d\n", rT_addr, bfa);
6282
6283            /* Fetch the entire condition code value */
6284            assign( cr, getGST( PPC_GST_CR ) );
6285
6286            /* Get bit zero (IBM numbering) of the CR field specified
6287             * by bfa.
6288             */
6289            assign( cr0, binop( Iop_And32,
6290                                binop( Iop_Shr32,
6291                                       mkexpr( cr ),
6292                                       mkU8( (7-bfa)*4 ) ),
6293                                mkU32( 0x8 ) ) );
6294            assign( cr1, binop( Iop_And32,
6295                                binop( Iop_Shr32,
6296                                       mkexpr( cr ),
6297                                       mkU8( (7-bfa)*4 ) ),
6298                                mkU32( 0x4 ) ) );
6299            assign( result, binop( Iop_Or64,
6300                                   unop( Iop_1Sto64,
6301                                       binop( Iop_CmpEQ32,
6302                                              mkexpr( cr0 ),
6303                                              mkU32( 0x8 ) ) ),
6304                                   binop( Iop_32HLto64,
6305                                          mkU32( 0 ),
6306                                          unop( Iop_1Uto32,
6307                                                binop( Iop_CmpEQ32,
6308                                                       mkexpr( cr1 ),
6309                                                       mkU32( 0x4 ) ) ) ) ) );
6310            if ( ty == Ity_I64 )
6311               putIReg( rT_addr, mkexpr( result ) );
6312            else
6313               putIReg( rT_addr, unop( Iop_64to32, mkexpr(result ) ) );
6314         }
6315         break;
6316      default:
6317         vex_printf("dis_int_cmp(ppc)(opc2)\n");
6318         return False;
6319      }
6320      break;
6321
6322   default:
6323      vex_printf("dis_int_cmp(ppc)(opc1)\n");
6324      return False;
6325   }
6326
6327   return True;
6328}
6329
6330
6331/*
6332  Integer Logical Instructions
6333*/
6334static Bool dis_int_logic ( UInt theInstr )
6335{
6336   /* D-Form, X-Form */
6337   UChar opc1    = ifieldOPC(theInstr);
6338   UChar rS_addr = ifieldRegDS(theInstr);
6339   UChar rA_addr = ifieldRegA(theInstr);
6340   UInt  uimm16  = ifieldUIMM16(theInstr);
6341   UChar rB_addr = ifieldRegB(theInstr);
6342   UInt  opc2    = ifieldOPClo10(theInstr);
6343   UChar flag_rC = ifieldBIT0(theInstr);
6344
6345   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6346   IRTemp rS     = newTemp(ty);
6347   IRTemp rA     = newTemp(ty);
6348   IRTemp rB     = newTemp(ty);
6349   IRExpr* irx;
6350   Bool do_rc    = False;
6351
6352   assign( rS, getIReg(rS_addr) );
6353   assign( rB, getIReg(rB_addr) );
6354
6355   switch (opc1) {
6356   case 0x1C: // andi. (AND Immediate, PPC32 p358)
6357      DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6358      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
6359                         mkSzImm(ty, uimm16)) );
6360      do_rc = True;  // Always record to CR
6361      flag_rC = 1;
6362      break;
6363
6364   case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
6365      DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6366      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
6367                         mkSzImm(ty, uimm16 << 16)) );
6368      do_rc = True;  // Always record to CR
6369      flag_rC = 1;
6370      break;
6371
6372   case 0x18: // ori (OR Immediate, PPC32 p497)
6373      DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6374      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
6375                         mkSzImm(ty, uimm16)) );
6376      break;
6377
6378   case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
6379      DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6380      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
6381                         mkSzImm(ty, uimm16 << 16)) );
6382      break;
6383
6384   case 0x1A: // xori (XOR Immediate, PPC32 p550)
6385      DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6386      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
6387                         mkSzImm(ty, uimm16)) );
6388      break;
6389
6390   case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
6391      DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6392      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
6393                         mkSzImm(ty, uimm16 << 16)) );
6394      break;
6395
6396   /* X Form */
6397   case 0x1F:
6398
6399      opc2 = IFIELD( theInstr, 2, 9 );
6400
6401      switch ( opc2 ) {
6402      case 0x1BD: // extswsli (Extend Sign Word shift left)
6403         {
6404            /* sh[5] is in bit 1, sh[0:4] is in bits [14:10] of theInstr */
6405            UChar sh = IFIELD( theInstr, 11, 5 ) | (IFIELD(theInstr, 1, 1) << 5);
6406            IRTemp temp = newTemp( ty );
6407
6408            DIP("extswsli%s r%u,r%u,%u\n", flag_rC ? ".":"",
6409                rA_addr, rS_addr, sh);
6410
6411            assign( temp, unop( Iop_32Sto64,
6412                                unop( Iop_64to32, mkexpr( rS ) ) ) );
6413            assign( rA, binop( Iop_Shl64, mkexpr( temp ), mkU8( sh ) ) );
6414            putIReg( rA_addr, mkexpr( rA ) );
6415
6416            if ( flag_rC ) {
6417               set_CR0( mkexpr( rA ) );
6418            }
6419            return True;
6420         }
6421      default:
6422         break;  // drop to next opc2 check
6423      }
6424
6425      do_rc = True; // All below record to CR, except for where we return at case end.
6426
6427      opc2 = ifieldOPClo10( theInstr );
6428
6429      switch (opc2) {
6430      case 0x01C: // and (AND, PPC32 p356)
6431         DIP("and%s r%u,r%u,r%u\n",
6432             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6433         assign(rA, binop( mkSzOp(ty, Iop_And8),
6434                           mkexpr(rS), mkexpr(rB)));
6435         break;
6436
6437      case 0x03C: // andc (AND with Complement, PPC32 p357)
6438         DIP("andc%s r%u,r%u,r%u\n",
6439             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6440         assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
6441                           unop( mkSzOp(ty, Iop_Not8),
6442                                 mkexpr(rB))));
6443         break;
6444
6445      case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
6446         IRExpr* lo32;
6447         if (rB_addr!=0) {
6448            vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
6449            return False;
6450         }
6451         DIP("cntlzw%s r%u,r%u\n",
6452             flag_rC ? ".":"", rA_addr, rS_addr);
6453
6454         // mode64: count in low word only
6455         lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
6456
6457         // Iop_Clz32 undefined for arg==0, so deal with that case:
6458         irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
6459         assign(rA, mkWidenFrom32(ty,
6460                         IRExpr_ITE( irx,
6461                                     unop(Iop_Clz32, lo32),
6462                                     mkU32(32)),
6463                         False));
6464
6465         // TODO: alternatively: assign(rA, verbose_Clz32(rS));
6466         break;
6467      }
6468
6469      case 0x11C: // eqv (Equivalent, PPC32 p396)
6470         DIP("eqv%s r%u,r%u,r%u\n",
6471             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6472         assign( rA, unop( mkSzOp(ty, Iop_Not8),
6473                           binop( mkSzOp(ty, Iop_Xor8),
6474                                  mkexpr(rS), mkexpr(rB))) );
6475         break;
6476
6477      case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
6478         if (rB_addr!=0) {
6479            vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
6480            return False;
6481         }
6482         DIP("extsb%s r%u,r%u\n",
6483             flag_rC ? ".":"", rA_addr, rS_addr);
6484         if (mode64)
6485            assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
6486         else
6487            assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
6488         break;
6489
6490      case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
6491         if (rB_addr!=0) {
6492            vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
6493            return False;
6494         }
6495         DIP("extsh%s r%u,r%u\n",
6496             flag_rC ? ".":"", rA_addr, rS_addr);
6497         if (mode64)
6498            assign( rA, unop(Iop_16Sto64,
6499                             unop(Iop_64to16, mkexpr(rS))) );
6500         else
6501            assign( rA, unop(Iop_16Sto32,
6502                             unop(Iop_32to16, mkexpr(rS))) );
6503         break;
6504
6505      case 0x1DC: // nand (NAND, PPC32 p492)
6506         DIP("nand%s r%u,r%u,r%u\n",
6507             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6508         assign( rA, unop( mkSzOp(ty, Iop_Not8),
6509                           binop( mkSzOp(ty, Iop_And8),
6510                                  mkexpr(rS), mkexpr(rB))) );
6511         break;
6512
6513      case 0x07C: // nor (NOR, PPC32 p494)
6514         DIP("nor%s r%u,r%u,r%u\n",
6515             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6516         assign( rA, unop( mkSzOp(ty, Iop_Not8),
6517                           binop( mkSzOp(ty, Iop_Or8),
6518                                  mkexpr(rS), mkexpr(rB))) );
6519         break;
6520
6521      case 0x1BC: // or (OR, PPC32 p495)
6522         if ((!flag_rC) && rS_addr == rB_addr) {
6523            DIP("mr r%u,r%u\n", rA_addr, rS_addr);
6524            assign( rA, mkexpr(rS) );
6525         } else {
6526            DIP("or%s r%u,r%u,r%u\n",
6527                flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6528            assign( rA, binop( mkSzOp(ty, Iop_Or8),
6529                               mkexpr(rS), mkexpr(rB)) );
6530         }
6531         break;
6532
6533      case 0x19C: // orc  (OR with Complement, PPC32 p496)
6534         DIP("orc%s r%u,r%u,r%u\n",
6535             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6536         assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
6537                            unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
6538         break;
6539
6540      case 0x13C: // xor (XOR, PPC32 p549)
6541         DIP("xor%s r%u,r%u,r%u\n",
6542             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6543         assign( rA, binop( mkSzOp(ty, Iop_Xor8),
6544                            mkexpr(rS), mkexpr(rB)) );
6545         break;
6546
6547
6548      /* 64bit Integer Logical Instructions */
6549      case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
6550         if (rB_addr!=0) {
6551            vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
6552            return False;
6553         }
6554         DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
6555         assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
6556         break;
6557
6558      case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
6559         if (rB_addr!=0) {
6560            vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
6561            return False;
6562         }
6563         DIP("cntlzd%s r%u,r%u\n",
6564             flag_rC ? ".":"", rA_addr, rS_addr);
6565         // Iop_Clz64 undefined for arg==0, so deal with that case:
6566         irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
6567         assign(rA, IRExpr_ITE( irx,
6568                                unop(Iop_Clz64, mkexpr(rS)),
6569                                mkU64(64) ));
6570         // TODO: alternatively: assign(rA, verbose_Clz64(rS));
6571         break;
6572
6573      case 0x1FC: // cmpb (Power6: compare bytes)
6574         DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
6575
6576         if (mode64)
6577            assign( rA, unop( Iop_V128to64,
6578                              binop( Iop_CmpEQ8x16,
6579                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
6580                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
6581                                     )) );
6582         else
6583            assign( rA, unop( Iop_V128to32,
6584                              binop( Iop_CmpEQ8x16,
6585                                     unop( Iop_32UtoV128, mkexpr(rS) ),
6586                                     unop( Iop_32UtoV128, mkexpr(rB) )
6587                                     )) );
6588         break;
6589
6590      case 0x2DF: { // mftgpr (move floating-point to general purpose register)
6591         IRTemp frB = newTemp(Ity_F64);
6592         DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
6593
6594         assign( frB, getFReg(rB_addr));  // always F64
6595         if (mode64)
6596            assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
6597         else
6598            assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
6599
6600         putIReg( rS_addr, mkexpr(rA));
6601         return True;
6602      }
6603
6604      case 0x25F: { // mffgpr (move floating-point from general purpose register)
6605         IRTemp frA = newTemp(Ity_F64);
6606         DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
6607
6608         if (mode64)
6609            assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
6610         else
6611            assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
6612
6613         putFReg( rS_addr, mkexpr(frA));
6614         return True;
6615      }
6616      case 0x1FA: // popcntd (population count doubleword
6617      {
6618    	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
6619    	  IRTemp result = gen_POPCOUNT(ty, rS, DWORD);
6620    	  putIReg( rA_addr, mkexpr(result) );
6621    	  return True;
6622      }
6623      case 0x17A: // popcntw (Population Count Words)
6624      {
6625         DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
6626         if (mode64) {
6627            IRTemp resultHi, resultLo;
6628            IRTemp argLo = newTemp(Ity_I32);
6629            IRTemp argHi = newTemp(Ity_I32);
6630            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
6631            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
6632            resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD);
6633            resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD);
6634            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
6635         } else {
6636            IRTemp result = gen_POPCOUNT(ty, rS, WORD);
6637            putIReg( rA_addr, mkexpr(result) );
6638         }
6639         return True;
6640      }
6641      case 0x7A: // popcntb (Population Count Byte)
6642      {
6643         DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
6644
6645         if (mode64) {
6646            IRTemp resultHi, resultLo;
6647            IRTemp argLo = newTemp(Ity_I32);
6648            IRTemp argHi = newTemp(Ity_I32);
6649            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
6650            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
6651            resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE);
6652            resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE);
6653            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
6654                                    mkexpr(resultLo)));
6655         } else {
6656            IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
6657            putIReg( rA_addr, mkexpr(result) );
6658         }
6659         return True;
6660      }
6661       case 0x0FC: // bpermd (Bit Permute Doubleword)
6662       {
6663          /* This is a lot of rigmarole to emulate bpermd like this, as it
6664           * could be done much faster by implementing a call to the native
6665           * instruction.  However, where possible I want to avoid using new
6666           * native instructions so that we can use valgrind to emulate those
6667           * instructions on older PPC64 hardware.
6668           */
6669 #define BPERMD_IDX_MASK 0x00000000000000FFULL
6670 #define BPERMD_BIT_MASK 0x8000000000000000ULL
6671          int i;
6672          IRExpr * rS_expr = mkexpr(rS);
6673          IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
6674          DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
6675          for (i = 0; i < 8; i++) {
6676             IRTemp idx_tmp = newTemp( Ity_I64 );
6677             IRTemp perm_bit = newTemp( Ity_I64 );
6678             IRTemp idx = newTemp( Ity_I8 );
6679             IRTemp idx_LT64 = newTemp( Ity_I1 );
6680             IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
6681
6682             assign( idx_tmp,
6683                     binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
6684             assign( idx_LT64,
6685                           binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
6686             assign( idx,
6687                           binop( Iop_And8,
6688                                  unop( Iop_1Sto8,
6689                                        mkexpr(idx_LT64) ),
6690                                  unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
6691             /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
6692              * to determine which bit of rB to use for the perm bit, and then we shift
6693              * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
6694              * to set the final perm bit.
6695              */
6696             assign( idx_LT64_ity64,
6697                           unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
6698             assign( perm_bit,
6699                           binop( Iop_And64,
6700                                  mkexpr( idx_LT64_ity64 ),
6701                                  binop( Iop_Shr64,
6702                                         binop( Iop_And64,
6703                                                mkU64( BPERMD_BIT_MASK ),
6704                                                binop( Iop_Shl64,
6705                                                       mkexpr( rB ),
6706                                                       mkexpr( idx ) ) ),
6707                                         mkU8( 63 ) ) ) );
6708             res = binop( Iop_Or64,
6709                                res,
6710                                binop( Iop_Shl64,
6711                                       mkexpr( perm_bit ),
6712                                       mkU8( i ) ) );
6713             rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
6714          }
6715          putIReg(rA_addr, res);
6716          return True;
6717       }
6718
6719      default:
6720         vex_printf("dis_int_logic(ppc)(opc2)\n");
6721         return False;
6722      }
6723      break;
6724
6725   default:
6726      vex_printf("dis_int_logic(ppc)(opc1)\n");
6727      return False;
6728   }
6729
6730   putIReg( rA_addr, mkexpr(rA) );
6731
6732   if (do_rc && flag_rC) {
6733      set_CR0( mkexpr(rA) );
6734   }
6735   return True;
6736}
6737
6738/*
6739  Integer Parity Instructions
6740*/
6741static Bool dis_int_parity ( UInt theInstr )
6742{
6743   /* X-Form */
6744   UChar opc1    = ifieldOPC(theInstr);
6745   UChar rS_addr = ifieldRegDS(theInstr);
6746   UChar rA_addr = ifieldRegA(theInstr);
6747   UChar rB_addr = ifieldRegB(theInstr);
6748   UInt  opc2    = ifieldOPClo10(theInstr);
6749   UChar b0      = ifieldBIT0(theInstr);
6750   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6751
6752   IRTemp rS     = newTemp(ty);
6753   IRTemp rA     = newTemp(ty);
6754   IRTemp iTot1  = newTemp(Ity_I32);
6755   IRTemp iTot2  = newTemp(Ity_I32);
6756   IRTemp iTot3  = newTemp(Ity_I32);
6757   IRTemp iTot4  = newTemp(Ity_I32);
6758   IRTemp iTot5  = newTemp(Ity_I32);
6759   IRTemp iTot6  = newTemp(Ity_I32);
6760   IRTemp iTot7  = newTemp(Ity_I32);
6761   IRTemp iTot8  = newTemp(Ity_I32);
6762   IRTemp rS1    = newTemp(ty);
6763   IRTemp rS2    = newTemp(ty);
6764   IRTemp rS3    = newTemp(ty);
6765   IRTemp rS4    = newTemp(ty);
6766   IRTemp rS5    = newTemp(ty);
6767   IRTemp rS6    = newTemp(ty);
6768   IRTemp rS7    = newTemp(ty);
6769   IRTemp iHi    = newTemp(Ity_I32);
6770   IRTemp iLo    = newTemp(Ity_I32);
6771   IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
6772   IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
6773
6774   if (opc1 != 0x1f || rB_addr || b0) {
6775      vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
6776      return False;
6777   }
6778
6779   assign( rS, getIReg(rS_addr) );
6780
6781   switch (opc2) {
6782   case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
6783      DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
6784      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
6785      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
6786      assign( iTot2, binop(Iop_Add32,
6787                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
6788                           mkexpr(iTot1)) );
6789      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
6790      assign( iTot3, binop(Iop_Add32,
6791                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
6792                           mkexpr(iTot2)) );
6793      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
6794      assign( iTot4, binop(Iop_Add32,
6795                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
6796                           mkexpr(iTot3)) );
6797      if (mode64) {
6798         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
6799         assign( iTot5, binop(Iop_Add32,
6800                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
6801                              mkexpr(iTot4)) );
6802         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
6803         assign( iTot6, binop(Iop_Add32,
6804                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
6805                              mkexpr(iTot5)) );
6806         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
6807         assign( iTot7, binop(Iop_Add32,
6808                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
6809                              mkexpr(iTot6)) );
6810         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
6811         assign( iTot8, binop(Iop_Add32,
6812                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
6813                              mkexpr(iTot7)) );
6814         assign( rA, unop(Iop_32Uto64,
6815                          binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
6816      } else
6817         assign( rA, mkexpr(iTot4) );
6818
6819      break;
6820   case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
6821      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
6822      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
6823      assign( iTot2, binop(Iop_Add32,
6824                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
6825                           mkexpr(iTot1)) );
6826      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
6827      assign( iTot3, binop(Iop_Add32,
6828                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
6829                           mkexpr(iTot2)) );
6830      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
6831      assign( iTot4, binop(Iop_Add32,
6832                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
6833                           mkexpr(iTot3)) );
6834      assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
6835
6836      if (mode64) {
6837         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
6838         assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
6839         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
6840         assign( iTot6, binop(Iop_Add32,
6841                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
6842                              mkexpr(iTot5)) );
6843         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
6844         assign( iTot7, binop(Iop_Add32,
6845                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
6846                              mkexpr(iTot6)) );
6847         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
6848         assign( iTot8, binop(Iop_Add32,
6849                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
6850                              mkexpr(iTot7)) );
6851         assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
6852            assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
6853      } else
6854         assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
6855      break;
6856   default:
6857      vex_printf("dis_int_parity(ppc)(opc2)\n");
6858      return False;
6859   }
6860
6861   putIReg( rA_addr, mkexpr(rA) );
6862
6863   return True;
6864}
6865
6866
6867/*
6868  Integer Rotate Instructions
6869*/
6870static Bool dis_int_rot ( UInt theInstr )
6871{
6872   /* M-Form, MDS-Form */
6873   UChar opc1    = ifieldOPC(theInstr);
6874   UChar rS_addr = ifieldRegDS(theInstr);
6875   UChar rA_addr = ifieldRegA(theInstr);
6876   UChar rB_addr = ifieldRegB(theInstr);
6877   UChar sh_imm  = rB_addr;
6878   UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
6879   UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
6880   UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
6881   UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
6882   UChar b1      = ifieldBIT1(theInstr);
6883   UChar flag_rC = ifieldBIT0(theInstr);
6884
6885   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6886   IRTemp rS     = newTemp(ty);
6887   IRTemp rA     = newTemp(ty);
6888   IRTemp rB     = newTemp(ty);
6889   IRTemp rot    = newTemp(ty);
6890   IRExpr *r;
6891   UInt   mask32;
6892   ULong  mask64;
6893
6894   assign( rS, getIReg(rS_addr) );
6895   assign( rB, getIReg(rB_addr) );
6896
6897   switch (opc1) {
6898   case 0x14: {
6899      // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
6900      DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
6901          rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
6902      if (mode64) {
6903         // tmp32 = (ROTL(rS_Lo32, Imm)
6904         // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
6905         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
6906         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
6907         r = unop(Iop_32Uto64, r);
6908         assign( rot, binop(Iop_Or64, r,
6909                            binop(Iop_Shl64, r, mkU8(32))) );
6910         assign( rA,
6911            binop(Iop_Or64,
6912                  binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
6913                  binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
6914      }
6915      else {
6916         // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
6917         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
6918         r = ROTL(mkexpr(rS), mkU8(sh_imm));
6919         assign( rA,
6920            binop(Iop_Or32,
6921                  binop(Iop_And32, mkU32(mask32), r),
6922                  binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
6923      }
6924      break;
6925   }
6926
6927   case 0x15: {
6928      // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
6929      vassert(MaskBeg < 32);
6930      vassert(MaskEnd < 32);
6931      vassert(sh_imm  < 32);
6932
6933      if (mode64) {
6934         IRTemp rTmp = newTemp(Ity_I64);
6935         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
6936         DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
6937             rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
6938         // tmp32 = (ROTL(rS_Lo32, Imm)
6939         // rA = ((tmp32 || tmp32) & mask64)
6940         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
6941         r = unop(Iop_32Uto64, r);
6942         assign( rTmp, r );
6943         r = NULL;
6944         assign( rot, binop(Iop_Or64, mkexpr(rTmp),
6945                            binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
6946         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
6947      }
6948      else {
6949         if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
6950            /* Special-case the ,n,0,31-n form as that is just n-bit
6951               shift left, PPC32 p501 */
6952            DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
6953                rA_addr, rS_addr, sh_imm);
6954            assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
6955         }
6956         else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
6957            /* Special-case the ,32-n,n,31 form as that is just n-bit
6958               unsigned shift right, PPC32 p501 */
6959            DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
6960                rA_addr, rS_addr, MaskBeg);
6961            assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
6962         }
6963         else {
6964            /* General case. */
6965            mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
6966            DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
6967                rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
6968            // rA = ROTL(rS, Imm) & mask
6969            assign( rA, binop(Iop_And32,
6970                              ROTL(mkexpr(rS), mkU8(sh_imm)),
6971                              mkU32(mask32)) );
6972         }
6973      }
6974      break;
6975   }
6976
6977   case 0x17: {
6978      // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
6979      DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
6980          rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
6981      if (mode64) {
6982         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
6983         /* weird insn alert!
6984            tmp32 = (ROTL(rS_Lo32, rB[0-4])
6985            rA = ((tmp32 || tmp32) & mask64)
6986         */
6987         // note, ROTL does the masking, so we don't do it here
6988         r = ROTL( unop(Iop_64to32, mkexpr(rS)),
6989                   unop(Iop_64to8, mkexpr(rB)) );
6990         r = unop(Iop_32Uto64, r);
6991         assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
6992         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
6993      } else {
6994         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
6995         // rA = ROTL(rS, rB[0-4]) & mask
6996         // note, ROTL does the masking, so we don't do it here
6997         assign( rA, binop(Iop_And32,
6998                           ROTL(mkexpr(rS),
6999                                unop(Iop_32to8, mkexpr(rB))),
7000                           mkU32(mask32)) );
7001      }
7002      break;
7003   }
7004
7005   /* 64bit Integer Rotates */
7006   case 0x1E: {
7007      msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
7008      sh_imm |= b1 << 5;
7009
7010      vassert( msk_imm < 64 );
7011      vassert( sh_imm < 64 );
7012
7013      switch (opc2) {
7014      case 0x4: {
7015         /* r = ROTL64( rS, rB_lo6) */
7016         r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
7017
7018         if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
7019            DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
7020                rA_addr, rS_addr, rB_addr, msk_imm);
7021            // note, ROTL does the masking, so we don't do it here
7022            mask64 = MASK64(0, 63-msk_imm);
7023            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
7024            break;
7025         } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
7026            DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
7027                rA_addr, rS_addr, rB_addr, msk_imm);
7028            mask64 = MASK64(63-msk_imm, 63);
7029            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
7030            break;
7031         }
7032         break;
7033      }
7034      case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
7035         DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
7036             rA_addr, rS_addr, sh_imm, msk_imm);
7037         r = ROTL(mkexpr(rS), mkU8(sh_imm));
7038         mask64 = MASK64(sh_imm, 63-msk_imm);
7039         assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
7040         break;
7041         // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
7042         /*
7043           Hmm... looks like this'll do the job more simply:
7044           r = SHL(rS, sh_imm)
7045           m = ~(1 << (63-msk_imm))
7046           assign(rA, r & m);
7047         */
7048
7049      case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
7050         if (mode64
7051             && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
7052            /* special-case the ,64-n,n form as that is just
7053               unsigned shift-right by n */
7054            DIP("srdi%s r%u,r%u,%u\n",
7055                flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
7056            assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
7057         } else {
7058            DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
7059                rA_addr, rS_addr, sh_imm, msk_imm);
7060            r = ROTL(mkexpr(rS), mkU8(sh_imm));
7061            mask64 = MASK64(0, 63-msk_imm);
7062            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
7063         }
7064         break;
7065
7066      case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
7067         if (mode64
7068             && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
7069            /* special-case the ,n,63-n form as that is just
7070               shift-left by n */
7071            DIP("sldi%s r%u,r%u,%u\n",
7072                flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
7073            assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
7074         } else {
7075            DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
7076                rA_addr, rS_addr, sh_imm, msk_imm);
7077            r = ROTL(mkexpr(rS), mkU8(sh_imm));
7078            mask64 = MASK64(63-msk_imm, 63);
7079            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
7080         }
7081         break;
7082
7083      case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
7084         IRTemp rA_orig = newTemp(ty);
7085         DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
7086             rA_addr, rS_addr, sh_imm, msk_imm);
7087         r = ROTL(mkexpr(rS), mkU8(sh_imm));
7088         mask64 = MASK64(sh_imm, 63-msk_imm);
7089         assign( rA_orig, getIReg(rA_addr) );
7090         assign( rA, binop(Iop_Or64,
7091                           binop(Iop_And64, mkU64(mask64),  r),
7092                           binop(Iop_And64, mkU64(~mask64),
7093                                            mkexpr(rA_orig))) );
7094         break;
7095      }
7096      default:
7097         vex_printf("dis_int_rot(ppc)(opc2)\n");
7098         return False;
7099      }
7100      break;
7101   }
7102
7103   default:
7104      vex_printf("dis_int_rot(ppc)(opc1)\n");
7105      return False;
7106   }
7107
7108   putIReg( rA_addr, mkexpr(rA) );
7109
7110   if (flag_rC) {
7111      set_CR0( mkexpr(rA) );
7112   }
7113   return True;
7114}
7115
7116
7117/*
7118  Integer Load Instructions
7119*/
7120static Bool dis_int_load ( UInt theInstr )
7121{
7122   /* D-Form, X-Form, DS-Form */
7123   UChar opc1     = ifieldOPC(theInstr);
7124   UChar rD_addr  = ifieldRegDS(theInstr);
7125   UChar rA_addr  = ifieldRegA(theInstr);
7126   UInt  uimm16   = ifieldUIMM16(theInstr);
7127   UChar rB_addr  = ifieldRegB(theInstr);
7128   UInt  opc2     = ifieldOPClo10(theInstr);
7129   UChar b1       = ifieldBIT1(theInstr);
7130   UChar b0       = ifieldBIT0(theInstr);
7131
7132   Int     simm16 = extend_s_16to32(uimm16);
7133   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
7134   IRTemp  EA     = newTemp(ty);
7135   IRExpr* val;
7136
7137   switch (opc1) {
7138   case 0x1F: // register offset
7139      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7140      break;
7141   case 0x38: // immediate offset: 64bit: lq: maskoff
7142              // lowest 4 bits of immediate before forming EA
7143      simm16 = simm16 & 0xFFFFFFF0;
7144      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
7145      break;
7146   case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
7147              // lowest 2 bits of immediate before forming EA
7148      simm16 = simm16 & 0xFFFFFFFC;
7149      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
7150      break;
7151   default:   // immediate offset
7152      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
7153      break;
7154   }
7155
7156   switch (opc1) {
7157   case 0x22: // lbz (Load B & Zero, PPC32 p433)
7158      DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7159      val = load(Ity_I8, mkexpr(EA));
7160      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
7161      break;
7162
7163   case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
7164      if (rA_addr == 0 || rA_addr == rD_addr) {
7165         vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
7166         return False;
7167      }
7168      DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7169      val = load(Ity_I8, mkexpr(EA));
7170      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
7171      putIReg( rA_addr, mkexpr(EA) );
7172      break;
7173
7174   case 0x2A: // lha (Load HW Alg, PPC32 p445)
7175      DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7176      val = load(Ity_I16, mkexpr(EA));
7177      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
7178      break;
7179
7180   case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
7181      if (rA_addr == 0 || rA_addr == rD_addr) {
7182         vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
7183         return False;
7184      }
7185      DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7186      val = load(Ity_I16, mkexpr(EA));
7187      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
7188      putIReg( rA_addr, mkexpr(EA) );
7189      break;
7190
7191   case 0x28: // lhz (Load HW & Zero, PPC32 p450)
7192      DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7193      val = load(Ity_I16, mkexpr(EA));
7194      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
7195      break;
7196
7197   case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
7198      if (rA_addr == 0 || rA_addr == rD_addr) {
7199         vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
7200         return False;
7201      }
7202      DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7203      val = load(Ity_I16, mkexpr(EA));
7204      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
7205      putIReg( rA_addr, mkexpr(EA) );
7206      break;
7207
7208   case 0x20: // lwz (Load W & Zero, PPC32 p460)
7209      DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7210      val = load(Ity_I32, mkexpr(EA));
7211      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
7212      break;
7213
7214   case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
7215      if (rA_addr == 0 || rA_addr == rD_addr) {
7216         vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
7217         return False;
7218      }
7219      DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7220      val = load(Ity_I32, mkexpr(EA));
7221      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
7222      putIReg( rA_addr, mkexpr(EA) );
7223      break;
7224
7225   /* X Form */
7226   case 0x1F:
7227      if (b0 != 0) {
7228         vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
7229         return False;
7230      }
7231
7232      switch (opc2) {
7233      case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
7234         DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7235         if (rA_addr == 0 || rA_addr == rD_addr) {
7236            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
7237            return False;
7238         }
7239         val = load(Ity_I8, mkexpr(EA));
7240         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
7241         putIReg( rA_addr, mkexpr(EA) );
7242         break;
7243
7244      case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
7245         DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7246         val = load(Ity_I8, mkexpr(EA));
7247         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
7248         break;
7249
7250      case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
7251         if (rA_addr == 0 || rA_addr == rD_addr) {
7252            vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
7253            return False;
7254         }
7255         DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7256         val = load(Ity_I16, mkexpr(EA));
7257         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
7258         putIReg( rA_addr, mkexpr(EA) );
7259         break;
7260
7261      case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
7262         DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7263         val = load(Ity_I16, mkexpr(EA));
7264         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
7265         break;
7266
7267      case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
7268         if (rA_addr == 0 || rA_addr == rD_addr) {
7269            vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
7270            return False;
7271         }
7272         DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7273         val = load(Ity_I16, mkexpr(EA));
7274         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
7275         putIReg( rA_addr, mkexpr(EA) );
7276         break;
7277
7278      case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
7279         DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7280         val = load(Ity_I16, mkexpr(EA));
7281         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
7282         break;
7283
7284      case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
7285         if (rA_addr == 0 || rA_addr == rD_addr) {
7286            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
7287            return False;
7288         }
7289         DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7290         val = load(Ity_I32, mkexpr(EA));
7291         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
7292         putIReg( rA_addr, mkexpr(EA) );
7293         break;
7294
7295      case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
7296         DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7297         val = load(Ity_I32, mkexpr(EA));
7298         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
7299         break;
7300
7301
7302      /* 64bit Loads */
7303      case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
7304         if (rA_addr == 0 || rA_addr == rD_addr) {
7305            vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
7306            return False;
7307         }
7308         DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7309         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
7310         putIReg( rA_addr, mkexpr(EA) );
7311         break;
7312
7313      case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
7314         DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7315         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
7316         break;
7317
7318      case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
7319         if (rA_addr == 0 || rA_addr == rD_addr) {
7320            vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
7321            return False;
7322         }
7323         DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7324         putIReg( rD_addr,
7325                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
7326         putIReg( rA_addr, mkexpr(EA) );
7327         break;
7328
7329      case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
7330         DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7331         putIReg( rD_addr,
7332                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
7333         break;
7334
7335      default:
7336         vex_printf("dis_int_load(ppc)(opc2)\n");
7337         return False;
7338      }
7339      break;
7340
7341   /* DS Form - 64bit Loads.  In each case EA will have been formed
7342      with the lowest 2 bits masked off the immediate offset. */
7343   case 0x3A:
7344      switch ((b1<<1) | b0) {
7345      case 0x0: // ld (Load DWord, PPC64 p472)
7346         DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
7347         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
7348         break;
7349
7350      case 0x1: // ldu (Load DWord, Update, PPC64 p474)
7351         if (rA_addr == 0 || rA_addr == rD_addr) {
7352            vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
7353            return False;
7354         }
7355         DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
7356         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
7357         putIReg( rA_addr, mkexpr(EA) );
7358         break;
7359
7360      case 0x2: // lwa (Load Word Alg, PPC64 p499)
7361         DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
7362         putIReg( rD_addr,
7363                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
7364         break;
7365
7366      default:
7367         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
7368         return False;
7369      }
7370      break;
7371
7372   case 0x38: {
7373      IRTemp  high = newTemp(ty);
7374      IRTemp  low  = newTemp(ty);
7375      /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
7376      DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
7377      /* NOTE: there are some changes to XER[41:42] that have not been
7378       * implemented.
7379       */
7380      // trap if EA misaligned on 16 byte address
7381      if (mode64) {
7382         if (host_endness == VexEndnessBE) {
7383            assign(high, load(ty, mkexpr( EA ) ) );
7384            assign(low, load(ty, binop( Iop_Add64,
7385                                        mkexpr( EA ),
7386                                        mkU64( 8 ) ) ) );
7387	 } else {
7388            assign(low, load(ty, mkexpr( EA ) ) );
7389            assign(high, load(ty, binop( Iop_Add64,
7390                                         mkexpr( EA ),
7391                                         mkU64( 8 ) ) ) );
7392	 }
7393      } else {
7394         assign(high, load(ty, binop( Iop_Add32,
7395                                      mkexpr( EA ),
7396                                      mkU32( 4 ) ) ) );
7397         assign(low, load(ty, binop( Iop_Add32,
7398                                      mkexpr( EA ),
7399                                      mkU32( 12 ) ) ) );
7400      }
7401      gen_SIGBUS_if_misaligned( EA, 16 );
7402      putIReg( rD_addr,  mkexpr( high) );
7403      putIReg( rD_addr+1,  mkexpr( low) );
7404      break;
7405   }
7406   default:
7407      vex_printf("dis_int_load(ppc)(opc1)\n");
7408      return False;
7409   }
7410   return True;
7411}
7412
7413
7414
7415/*
7416  Integer Store Instructions
7417*/
7418static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi )
7419{
7420   /* D-Form, X-Form, DS-Form */
7421   UChar opc1    = ifieldOPC(theInstr);
7422   UInt  rS_addr = ifieldRegDS(theInstr);
7423   UInt  rA_addr = ifieldRegA(theInstr);
7424   UInt  uimm16  = ifieldUIMM16(theInstr);
7425   UInt  rB_addr = ifieldRegB(theInstr);
7426   UInt  opc2    = ifieldOPClo10(theInstr);
7427   UChar b1      = ifieldBIT1(theInstr);
7428   UChar b0      = ifieldBIT0(theInstr);
7429
7430   Int    simm16 = extend_s_16to32(uimm16);
7431   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
7432   IRTemp rS     = newTemp(ty);
7433   IRTemp rB     = newTemp(ty);
7434   IRTemp EA     = newTemp(ty);
7435
7436   assign( rB, getIReg(rB_addr) );
7437   assign( rS, getIReg(rS_addr) );
7438
7439   switch (opc1) {
7440   case 0x1F: // register offset
7441      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7442      break;
7443   case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
7444              // lowest 2 bits of immediate before forming EA
7445      simm16 = simm16 & 0xFFFFFFFC;
7446   default:   // immediate offset
7447      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
7448      break;
7449   }
7450
7451   switch (opc1) {
7452   case 0x26: // stb (Store B, PPC32 p509)
7453      DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7454      store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
7455      break;
7456
7457   case 0x27: // stbu (Store B, Update, PPC32 p510)
7458      if (rA_addr == 0 ) {
7459         vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
7460         return False;
7461      }
7462      DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7463      putIReg( rA_addr, mkexpr(EA) );
7464      store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
7465      break;
7466
7467   case 0x2C: // sth (Store HW, PPC32 p522)
7468      DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7469      store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
7470      break;
7471
7472   case 0x2D: // sthu (Store HW, Update, PPC32 p524)
7473      if (rA_addr == 0) {
7474         vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
7475         return False;
7476      }
7477      DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7478      putIReg( rA_addr, mkexpr(EA) );
7479      store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
7480      break;
7481
7482   case 0x24: // stw (Store W, PPC32 p530)
7483      DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7484      store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
7485      break;
7486
7487   case 0x25: // stwu (Store W, Update, PPC32 p534)
7488      if (rA_addr == 0) {
7489         vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
7490         return False;
7491      }
7492      DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7493      putIReg( rA_addr, mkexpr(EA) );
7494      store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
7495      break;
7496
7497   /* X Form : all these use EA_indexed */
7498   case 0x1F:
7499      if (b0 != 0) {
7500         vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
7501         return False;
7502      }
7503
7504      switch (opc2) {
7505      case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
7506         if (rA_addr == 0) {
7507            vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
7508            return False;
7509         }
7510         DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7511         putIReg( rA_addr, mkexpr(EA) );
7512         store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
7513         break;
7514
7515      case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
7516         DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7517         store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
7518         break;
7519
7520      case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
7521         if (rA_addr == 0) {
7522            vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
7523            return False;
7524         }
7525         DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7526         putIReg( rA_addr, mkexpr(EA) );
7527         store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
7528         break;
7529
7530      case 0x197: // sthx (Store HW Indexed, PPC32 p526)
7531         DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7532         store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
7533         break;
7534
7535      case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
7536         if (rA_addr == 0) {
7537            vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
7538            return False;
7539         }
7540         DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7541         putIReg( rA_addr, mkexpr(EA) );
7542         store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
7543         break;
7544
7545      case 0x097: // stwx (Store W Indexed, PPC32 p536)
7546         DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7547         store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
7548         break;
7549
7550
7551      /* 64bit Stores */
7552      case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
7553         if (rA_addr == 0) {
7554            vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
7555            return False;
7556         }
7557         DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7558         putIReg( rA_addr, mkexpr(EA) );
7559         store( mkexpr(EA), mkexpr(rS) );
7560         break;
7561
7562      case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
7563         DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7564         store( mkexpr(EA), mkexpr(rS) );
7565         break;
7566
7567      default:
7568         vex_printf("dis_int_store(ppc)(opc2)\n");
7569         return False;
7570      }
7571      break;
7572
7573   /* DS Form - 64bit Stores.  In each case EA will have been formed
7574      with the lowest 2 bits masked off the immediate offset. */
7575   case 0x3E:
7576      switch ((b1<<1) | b0) {
7577      case 0x0: // std (Store DWord, PPC64 p580)
7578         if (!mode64)
7579            return False;
7580
7581         DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7582         store( mkexpr(EA), mkexpr(rS) );
7583         break;
7584
7585      case 0x1: // stdu (Store DWord, Update, PPC64 p583)
7586         if (!mode64)
7587            return False;
7588
7589         DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7590         putIReg( rA_addr, mkexpr(EA) );
7591         store( mkexpr(EA), mkexpr(rS) );
7592         break;
7593
7594      case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
7595         IRTemp EA_hi = newTemp(ty);
7596         IRTemp EA_lo = newTemp(ty);
7597         DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7598
7599         if (mode64) {
7600            if (host_endness == VexEndnessBE) {
7601
7602               /* upper 64-bits */
7603               assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
7604
7605               /* lower 64-bits */
7606               assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) );
7607	    } else {
7608               /* upper 64-bits */
7609               assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) );
7610
7611               /* lower 64-bits */
7612               assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) );
7613	    }
7614         } else {
7615            /* upper half of upper 64-bits */
7616            assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) );
7617
7618            /* lower half of upper 64-bits */
7619            assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
7620         }
7621         store( mkexpr(EA_hi), mkexpr(rS) );
7622         store( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
7623         break;
7624      }
7625      default:
7626         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
7627         return False;
7628      }
7629      break;
7630
7631   default:
7632      vex_printf("dis_int_store(ppc)(opc1)\n");
7633      return False;
7634   }
7635   return True;
7636}
7637
7638
7639
7640/*
7641  Integer Load/Store Multiple Instructions
7642*/
7643static Bool dis_int_ldst_mult ( UInt theInstr )
7644{
7645   /* D-Form */
7646   UChar opc1     = ifieldOPC(theInstr);
7647   UChar rD_addr  = ifieldRegDS(theInstr);
7648   UChar rS_addr  = rD_addr;
7649   UChar rA_addr  = ifieldRegA(theInstr);
7650   UInt  uimm16   = ifieldUIMM16(theInstr);
7651
7652   Int     simm16 = extend_s_16to32(uimm16);
7653   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
7654   IROp    mkAdd  = mode64 ? Iop_Add64 : Iop_Add32;
7655   IRTemp  EA     = newTemp(ty);
7656   UInt    r      = 0;
7657   UInt    ea_off = 0;
7658   IRExpr* irx_addr;
7659
7660   assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
7661
7662   switch (opc1) {
7663   case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
7664      if (rA_addr >= rD_addr) {
7665         vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
7666         return False;
7667      }
7668      DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
7669      for (r = rD_addr; r <= 31; r++) {
7670         irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
7671         putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ),
7672                                       False) );
7673         ea_off += 4;
7674      }
7675      break;
7676
7677   case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
7678      DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7679      for (r = rS_addr; r <= 31; r++) {
7680         irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
7681         store( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
7682         ea_off += 4;
7683      }
7684      break;
7685
7686   default:
7687      vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
7688      return False;
7689   }
7690   return True;
7691}
7692
7693
7694
7695/*
7696  Integer Load/Store String Instructions
7697*/
7698static
7699void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
7700                             IRTemp EA,        // EA
7701                             Int    rD,        // first dst register
7702                             Int    maxBytes ) // 32 or 128
7703{
7704   Int     i, shift = 24;
7705   IRExpr* e_nbytes = mkexpr(tNBytes);
7706   IRExpr* e_EA     = mkexpr(EA);
7707   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
7708
7709   vassert(rD >= 0 && rD < 32);
7710   rD--; if (rD < 0) rD = 31;
7711
7712   for (i = 0; i < maxBytes; i++) {
7713      /* if (nBytes < (i+1)) goto NIA; */
7714      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
7715                         Ijk_Boring,
7716                         mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
7717      /* when crossing into a new dest register, set it to zero. */
7718      if ((i % 4) == 0) {
7719         rD++; if (rD == 32) rD = 0;
7720         putIReg(rD, mkSzImm(ty, 0));
7721         shift = 24;
7722      }
7723      /* rD |=  (8Uto32(*(EA+i))) << shift */
7724      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
7725      putIReg(
7726         rD,
7727         mkWidenFrom32(
7728            ty,
7729            binop(
7730               Iop_Or32,
7731               mkNarrowTo32(ty, getIReg(rD)),
7732               binop(
7733                  Iop_Shl32,
7734                  unop(
7735                     Iop_8Uto32,
7736                     load( Ity_I8,
7737                           binop( mkSzOp(ty,Iop_Add8),
7738                                  e_EA, mkSzImm(ty,i)))
7739                  ),
7740                  mkU8(toUChar(shift))
7741               )
7742            ),
7743            /*Signed*/False
7744	 )
7745      );
7746      shift -= 8;
7747   }
7748}
7749
7750static
7751void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
7752                              IRTemp EA,        // EA
7753                              Int    rS,        // first src register
7754                              Int    maxBytes ) // 32 or 128
7755{
7756   Int     i, shift = 24;
7757   IRExpr* e_nbytes = mkexpr(tNBytes);
7758   IRExpr* e_EA     = mkexpr(EA);
7759   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
7760
7761   vassert(rS >= 0 && rS < 32);
7762   rS--; if (rS < 0) rS = 31;
7763
7764   for (i = 0; i < maxBytes; i++) {
7765      /* if (nBytes < (i+1)) goto NIA; */
7766      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
7767                         Ijk_Boring,
7768                         mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
7769      /* check for crossing into a new src register. */
7770      if ((i % 4) == 0) {
7771         rS++; if (rS == 32) rS = 0;
7772         shift = 24;
7773      }
7774      /* *(EA+i) = 32to8(rS >> shift) */
7775      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
7776      store(
7777            binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
7778            unop( Iop_32to8,
7779                  binop( Iop_Shr32,
7780                         mkNarrowTo32( ty, getIReg(rS) ),
7781                         mkU8( toUChar(shift) )))
7782      );
7783      shift -= 8;
7784   }
7785}
7786
7787static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
7788{
7789   /* X-Form */
7790   UChar opc1     = ifieldOPC(theInstr);
7791   UChar rD_addr  = ifieldRegDS(theInstr);
7792   UChar rS_addr  = rD_addr;
7793   UChar rA_addr  = ifieldRegA(theInstr);
7794   UChar rB_addr  = ifieldRegB(theInstr);
7795   UChar NumBytes = rB_addr;
7796   UInt  opc2     = ifieldOPClo10(theInstr);
7797   UChar b0       = ifieldBIT0(theInstr);
7798
7799   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
7800   IRTemp t_EA    = newTemp(ty);
7801   IRTemp t_nbytes = IRTemp_INVALID;
7802
7803   *stopHere = False;
7804
7805   if (opc1 != 0x1F || b0 != 0) {
7806      vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
7807      return False;
7808   }
7809
7810   switch (opc2) {
7811   case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
7812      /* NB: does not reject the case where RA is in the range of
7813         registers to be loaded.  It should. */
7814      DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
7815      assign( t_EA, ea_rAor0(rA_addr) );
7816      if (NumBytes == 8 && !mode64) {
7817         /* Special case hack */
7818         /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
7819         putIReg( rD_addr,
7820                  load(Ity_I32, mkexpr(t_EA)) );
7821         putIReg( (rD_addr+1) % 32,
7822                  load(Ity_I32,
7823                       binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
7824      } else {
7825         t_nbytes = newTemp(Ity_I32);
7826         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
7827         generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
7828         *stopHere = True;
7829      }
7830      return True;
7831
7832   case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
7833      /* NB: does not reject the case where RA is in the range of
7834         registers to be loaded.  It should.  Although considering
7835         that that can only be detected at run time, it's not easy to
7836         do so. */
7837      if (rD_addr == rA_addr || rD_addr == rB_addr)
7838         return False;
7839      if (rD_addr == 0 && rA_addr == 0)
7840         return False;
7841      DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7842      t_nbytes = newTemp(Ity_I32);
7843      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
7844      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
7845      generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
7846      *stopHere = True;
7847      return True;
7848
7849   case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
7850      DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
7851      assign( t_EA, ea_rAor0(rA_addr) );
7852      if (NumBytes == 8 && !mode64) {
7853         /* Special case hack */
7854         /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
7855         store( mkexpr(t_EA),
7856                getIReg(rD_addr) );
7857         store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
7858                getIReg((rD_addr+1) % 32) );
7859      } else {
7860         t_nbytes = newTemp(Ity_I32);
7861         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
7862         generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
7863         *stopHere = True;
7864      }
7865      return True;
7866
7867   case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
7868      DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7869      t_nbytes = newTemp(Ity_I32);
7870      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
7871      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
7872      generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
7873      *stopHere = True;
7874      return True;
7875
7876   default:
7877      vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
7878      return False;
7879   }
7880   return True;
7881}
7882
7883
7884/* ------------------------------------------------------------------
7885   Integer Branch Instructions
7886   ------------------------------------------------------------------ */
7887
7888/*
7889  Branch helper function
7890  ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
7891  Returns an I32 which is 0x00000000 if the ctr condition failed
7892  and 0xFFFFFFFF otherwise.
7893*/
7894static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
7895{
7896   IRType ty = mode64 ? Ity_I64 : Ity_I32;
7897   IRTemp ok = newTemp(Ity_I32);
7898
7899   if ((BO >> 2) & 1) {     // independent of ctr
7900      assign( ok, mkU32(0xFFFFFFFF) );
7901   } else {
7902      if ((BO >> 1) & 1) {  // ctr == 0 ?
7903         assign( ok, unop( Iop_1Sto32,
7904                           binop( mkSzOp(ty, Iop_CmpEQ8),
7905                                  getGST( PPC_GST_CTR ),
7906                                  mkSzImm(ty,0))) );
7907      } else {              // ctr != 0 ?
7908         assign( ok, unop( Iop_1Sto32,
7909                           binop( mkSzOp(ty, Iop_CmpNE8),
7910                                  getGST( PPC_GST_CTR ),
7911                                  mkSzImm(ty,0))) );
7912      }
7913   }
7914   return mkexpr(ok);
7915}
7916
7917
7918/*
7919  Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
7920  Returns an I32 which is either 0 if the condition failed or
7921  some arbitrary nonzero value otherwise. */
7922
7923static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
7924{
7925   Int where;
7926   IRTemp res   = newTemp(Ity_I32);
7927   IRTemp cr_bi = newTemp(Ity_I32);
7928
7929   if ((BO >> 4) & 1) {
7930      assign( res, mkU32(1) );
7931   } else {
7932      // ok = (CR[BI] == BO[3]) Note, the following relies on
7933      // getCRbit_anywhere returning a value which
7934      // is either zero or has exactly 1 bit set.
7935      assign( cr_bi, getCRbit_anywhere( BI, &where ) );
7936
7937      if ((BO >> 3) & 1) {
7938         /* We can use cr_bi as-is. */
7939         assign( res, mkexpr(cr_bi) );
7940      } else {
7941         /* We have to invert the sense of the information held in
7942            cr_bi.  For that we need to know which bit
7943            getCRbit_anywhere regards as significant. */
7944         assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
7945                                       mkU32(1<<where)) );
7946      }
7947   }
7948   return mkexpr(res);
7949}
7950
7951
7952/*
7953  Integer Branch Instructions
7954*/
7955static Bool dis_branch ( UInt theInstr,
7956                         const VexAbiInfo* vbi,
7957                         /*OUT*/DisResult* dres,
7958                         Bool (*resteerOkFn)(void*,Addr),
7959                         void* callback_opaque )
7960{
7961   UChar opc1    = ifieldOPC(theInstr);
7962   UChar BO      = ifieldRegDS(theInstr);
7963   UChar BI      = ifieldRegA(theInstr);
7964   UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
7965   UChar b11to15 = ifieldRegB(theInstr);
7966   UInt  opc2    = ifieldOPClo10(theInstr);
7967   UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
7968   UChar flag_AA = ifieldBIT1(theInstr);
7969   UChar flag_LK = ifieldBIT0(theInstr);
7970
7971   IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
7972   Addr64   tgt       = 0;
7973   UInt     BD        = extend_s_16to32(BD_u16);
7974   IRTemp   do_branch = newTemp(Ity_I32);
7975   IRTemp   ctr_ok    = newTemp(Ity_I32);
7976   IRTemp   cond_ok   = newTemp(Ity_I32);
7977   IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
7978   IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
7979   IRTemp   lr_old    = newTemp(ty);
7980
7981   /* Hack to pass through code that just wants to read the PC */
7982   if (theInstr == 0x429F0005) {
7983      DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
7984      putGST( PPC_GST_LR, e_nia );
7985      return True;
7986   }
7987
7988   /* The default what-next.  Individual cases can override it. */
7989   dres->whatNext = Dis_StopHere;
7990   vassert(dres->jk_StopHere == Ijk_INVALID);
7991
7992   switch (opc1) {
7993   case 0x12: // b     (Branch, PPC32 p360)
7994      if (flag_AA) {
7995         tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
7996      } else {
7997         tgt = mkSzAddr( ty, guest_CIA_curr_instr +
7998                             (Long)extend_s_26to64(LI_u26) );
7999      }
8000      if (mode64) {
8001         DIP("b%s%s 0x%llx\n",
8002             flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
8003      } else {
8004         DIP("b%s%s 0x%x\n",
8005             flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
8006      }
8007
8008      if (flag_LK) {
8009         putGST( PPC_GST_LR, e_nia );
8010         if (vbi->guest_ppc_zap_RZ_at_bl
8011             && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
8012            IRTemp t_tgt = newTemp(ty);
8013            assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
8014            make_redzone_AbiHint( vbi, t_tgt,
8015                                  "branch-and-link (unconditional call)" );
8016         }
8017      }
8018
8019      if (resteerOkFn( callback_opaque, tgt )) {
8020         dres->whatNext   = Dis_ResteerU;
8021         dres->continueAt = tgt;
8022      } else {
8023         dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
8024         putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
8025      }
8026      break;
8027
8028   case 0x10: // bc    (Branch Conditional, PPC32 p361)
8029      DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
8030          flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
8031
8032      if (!(BO & 0x4)) {
8033         putGST( PPC_GST_CTR,
8034                 binop(mkSzOp(ty, Iop_Sub8),
8035                       getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
8036      }
8037
8038      /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
8039         cond_ok is either zero or nonzero, since that's the cheapest
8040         way to compute it.  Anding them together gives a value which
8041         is either zero or non zero and so that's what we must test
8042         for in the IRStmt_Exit. */
8043      assign( ctr_ok,  branch_ctr_ok( BO ) );
8044      assign( cond_ok, branch_cond_ok( BO, BI ) );
8045      assign( do_branch,
8046              binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
8047
8048      if (flag_AA) {
8049         tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
8050      } else {
8051         tgt = mkSzAddr(ty, guest_CIA_curr_instr +
8052                            (Long)extend_s_16to64(BD_u16));
8053      }
8054      if (flag_LK)
8055         putGST( PPC_GST_LR, e_nia );
8056
8057      stmt( IRStmt_Exit(
8058               binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
8059               flag_LK ? Ijk_Call : Ijk_Boring,
8060               mkSzConst(ty, tgt), OFFB_CIA ) );
8061
8062      dres->jk_StopHere = Ijk_Boring;
8063      putGST( PPC_GST_CIA, e_nia );
8064      break;
8065
8066   case 0x13:
8067      /* For bclr and bcctr, it appears that the lowest two bits of
8068         b11to15 are a branch hint, and so we only need to ensure it's
8069         of the form 000XX. */
8070      if ((b11to15 & ~3) != 0) {
8071         vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15);
8072         return False;
8073      }
8074
8075      switch (opc2) {
8076      case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
8077         if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
8078            vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
8079            return False;
8080         }
8081         DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
8082
8083         assign( cond_ok, branch_cond_ok( BO, BI ) );
8084
8085         /* FIXME: this is confusing.  lr_old holds the old value
8086            of ctr, not lr :-) */
8087         assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
8088
8089         if (flag_LK)
8090            putGST( PPC_GST_LR, e_nia );
8091
8092         stmt( IRStmt_Exit(
8093                  binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
8094                  Ijk_Boring,
8095                  c_nia, OFFB_CIA ));
8096
8097         if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
8098            make_redzone_AbiHint( vbi, lr_old,
8099                                  "b-ctr-l (indirect call)" );
8100	 }
8101
8102         dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
8103         putGST( PPC_GST_CIA, mkexpr(lr_old) );
8104         break;
8105
8106      case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
8107         Bool vanilla_return = False;
8108         if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
8109            DIP("blr\n");
8110            vanilla_return = True;
8111         } else {
8112            DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
8113         }
8114
8115         if (!(BO & 0x4)) {
8116            putGST( PPC_GST_CTR,
8117                    binop(mkSzOp(ty, Iop_Sub8),
8118                          getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
8119         }
8120
8121         /* See comments above for 'bc' about this */
8122         assign( ctr_ok,  branch_ctr_ok( BO ) );
8123         assign( cond_ok, branch_cond_ok( BO, BI ) );
8124         assign( do_branch,
8125                 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
8126
8127         assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
8128
8129         if (flag_LK)
8130            putGST( PPC_GST_LR,  e_nia );
8131
8132         stmt( IRStmt_Exit(
8133                  binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
8134                  Ijk_Boring,
8135                  c_nia, OFFB_CIA ));
8136
8137         if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
8138            make_redzone_AbiHint( vbi, lr_old,
8139                                  "branch-to-lr (unconditional return)" );
8140         }
8141
8142         /* blrl is pretty strange; it's like a return that sets the
8143            return address of its caller to the insn following this
8144            one.  Mark it as a return. */
8145         dres->jk_StopHere = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
8146         putGST( PPC_GST_CIA, mkexpr(lr_old) );
8147         break;
8148      }
8149      default:
8150         vex_printf("dis_int_branch(ppc)(opc2)\n");
8151         return False;
8152      }
8153      break;
8154
8155   default:
8156      vex_printf("dis_int_branch(ppc)(opc1)\n");
8157      return False;
8158   }
8159
8160   return True;
8161}
8162
8163/*
8164 *  PC relative instruction
8165 */
8166static Bool dis_pc_relative ( UInt theInstr )
8167{
8168   /* DX-Form */
8169   UChar opc1 = ifieldOPC(theInstr);
8170   unsigned long long D;
8171   UInt d0 = IFIELD(theInstr,  6, 10);
8172   UInt d1 = IFIELD(theInstr, 16,  5);
8173   UInt d2 = IFIELD(theInstr,  0,  1);
8174   UChar rT_addr = ifieldRegDS(theInstr);
8175   UInt  opc2    = ifieldOPClo5(theInstr);
8176   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
8177
8178   if ( opc1 != 0x13) {
8179      vex_printf("dis_pc_relative(ppc)(opc1)\n");
8180      return False;
8181   }
8182
8183   switch (opc2) {
8184   case 0x002:   // addpcis  (Add PC immediate Shifted DX-form)
8185      {
8186         IRExpr* nia     = mkSzImm(ty, nextInsnAddr());
8187         IRExpr* result;
8188
8189         D = (d0 << 6) | (d1 << 1) | d2;
8190         DIP("addpcis %u,%llu\n", rT_addr, D);
8191
8192         if ( (D & 0x8000) == 0x8000 )
8193            D = 0xFFFFFFFFFFFF0000UL | D;  // sign extend
8194
8195         if ( ty == Ity_I32 ) {
8196            result = binop( Iop_Add32, nia, mkU32( D << 16 ) );
8197         } else {
8198            vassert( ty == Ity_I64 );
8199            result = binop( Iop_Add64, nia, mkU64( D << 16 ) );
8200         }
8201
8202         putIReg( rT_addr, result);
8203      }
8204      break;
8205
8206   default:
8207      vex_printf("dis_pc_relative(ppc)(opc2)\n");
8208      return False;
8209   }
8210
8211   return True;
8212}
8213
8214/*
8215  Condition Register Logical Instructions
8216 */
8217static Bool dis_cond_logic ( UInt theInstr )
8218{
8219   /* XL-Form */
8220   UChar opc1      = ifieldOPC(theInstr);
8221   UChar crbD_addr = ifieldRegDS(theInstr);
8222   UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
8223   UChar crbA_addr = ifieldRegA(theInstr);
8224   UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
8225   UChar crbB_addr = ifieldRegB(theInstr);
8226   UInt  opc2      = ifieldOPClo10(theInstr);
8227   UChar b0        = ifieldBIT0(theInstr);
8228
8229   IRTemp crbD     = newTemp(Ity_I32);
8230   IRTemp crbA     = newTemp(Ity_I32);
8231   IRTemp crbB     = newTemp(Ity_I32);
8232
8233   if (opc1 != 19 || b0 != 0) {
8234      vex_printf("dis_cond_logic(ppc)(opc1)\n");
8235      return False;
8236   }
8237
8238   if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
8239      if (((crbD_addr & 0x3) != 0) ||
8240          ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
8241         vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
8242         return False;
8243      }
8244      DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
8245      putCR0(   crfD_addr, getCR0(  crfS_addr) );
8246      putCR321( crfD_addr, getCR321(crfS_addr) );
8247   } else {
8248      assign( crbA, getCRbit(crbA_addr) );
8249      if (crbA_addr == crbB_addr)
8250         crbB = crbA;
8251      else
8252         assign( crbB, getCRbit(crbB_addr) );
8253
8254      switch (opc2) {
8255      case 0x101: // crand   (Cond Reg AND, PPC32 p372)
8256         DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8257         assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
8258         break;
8259      case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
8260         DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8261         assign( crbD, binop(Iop_And32,
8262                             mkexpr(crbA),
8263                             unop(Iop_Not32, mkexpr(crbB))) );
8264         break;
8265      case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
8266         DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8267         assign( crbD, unop(Iop_Not32,
8268                            binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
8269         break;
8270      case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
8271         DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8272         assign( crbD, unop(Iop_Not32,
8273                            binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
8274         break;
8275      case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
8276         DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8277         assign( crbD, unop(Iop_Not32,
8278                            binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
8279         break;
8280      case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
8281         DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8282         assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
8283         break;
8284      case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
8285         DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8286         assign( crbD, binop(Iop_Or32,
8287                             mkexpr(crbA),
8288                             unop(Iop_Not32, mkexpr(crbB))) );
8289         break;
8290      case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
8291         DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8292         assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
8293         break;
8294      default:
8295         vex_printf("dis_cond_logic(ppc)(opc2)\n");
8296         return False;
8297      }
8298
8299      putCRbit( crbD_addr, mkexpr(crbD) );
8300   }
8301   return True;
8302}
8303
8304
8305/*
8306  Trap instructions
8307*/
8308
8309/* Do the code generation for a trap.  Returned Bool is true iff
8310   this is an unconditional trap.  If the two arg IRExpr*s are
8311   Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
8312   then they are 64-bit, and we must be disassembling 64-bit
8313   instructions. */
8314static Bool do_trap ( UChar TO,
8315                      IRExpr* argL0, IRExpr* argR0, Addr64 cia )
8316{
8317   IRTemp argL, argR;
8318   IRExpr *argLe, *argRe, *cond, *tmp;
8319
8320   Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
8321
8322   IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
8323   IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
8324   IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
8325   IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
8326   IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
8327   IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
8328   IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
8329   IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
8330   IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
8331   IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
8332
8333   const UChar b11100 = 0x1C;
8334   const UChar b00111 = 0x07;
8335
8336   if (is32bit) {
8337      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
8338      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
8339   } else {
8340      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
8341      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
8342      vassert( mode64 );
8343   }
8344
8345   if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
8346      /* Unconditional trap.  Just do the exit without
8347         testing the arguments. */
8348      stmt( IRStmt_Exit(
8349               binop(opCMPEQ, const0, const0),
8350               Ijk_SigTRAP,
8351               mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
8352               OFFB_CIA
8353      ));
8354      return True; /* unconditional trap */
8355   }
8356
8357   if (is32bit) {
8358      argL = newTemp(Ity_I32);
8359      argR = newTemp(Ity_I32);
8360   } else {
8361      argL = newTemp(Ity_I64);
8362      argR = newTemp(Ity_I64);
8363   }
8364
8365   assign( argL, argL0 );
8366   assign( argR, argR0 );
8367
8368   argLe = mkexpr(argL);
8369   argRe = mkexpr(argR);
8370
8371   cond = const0;
8372   if (TO & 16) { // L <s R
8373      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
8374      cond = binop(opOR, tmp, cond);
8375   }
8376   if (TO & 8) { // L >s R
8377      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
8378      cond = binop(opOR, tmp, cond);
8379   }
8380   if (TO & 4) { // L == R
8381      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
8382      cond = binop(opOR, tmp, cond);
8383   }
8384   if (TO & 2) { // L <u R
8385      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
8386      cond = binop(opOR, tmp, cond);
8387   }
8388   if (TO & 1) { // L >u R
8389      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
8390      cond = binop(opOR, tmp, cond);
8391   }
8392   stmt( IRStmt_Exit(
8393            binop(opCMPNE, cond, const0),
8394            Ijk_SigTRAP,
8395            mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
8396            OFFB_CIA
8397   ));
8398   return False; /* not an unconditional trap */
8399}
8400
8401static Bool dis_trapi ( UInt theInstr,
8402                        /*OUT*/DisResult* dres )
8403{
8404   /* D-Form */
8405   UChar  opc1    = ifieldOPC(theInstr);
8406   UChar  TO      = ifieldRegDS(theInstr);
8407   UChar  rA_addr = ifieldRegA(theInstr);
8408   UInt   uimm16  = ifieldUIMM16(theInstr);
8409   ULong  simm16  = extend_s_16to64(uimm16);
8410   Addr64 cia     = guest_CIA_curr_instr;
8411   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
8412   Bool   uncond  = False;
8413
8414   switch (opc1) {
8415   case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
8416      uncond = do_trap( TO,
8417                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
8418                               : getIReg(rA_addr),
8419                        mkU32( (UInt)simm16 ),
8420                        cia );
8421      if (TO == 4) {
8422         DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16);
8423      } else {
8424         DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16);
8425      }
8426      break;
8427   case 0x02: // tdi
8428      if (!mode64)
8429         return False;
8430      uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
8431      if (TO == 4) {
8432         DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16);
8433      } else {
8434         DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16);
8435      }
8436      break;
8437   default:
8438      return False;
8439   }
8440
8441   if (uncond) {
8442      /* If the trap shows signs of being unconditional, don't
8443         continue decoding past it. */
8444      putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
8445      dres->jk_StopHere = Ijk_Boring;
8446      dres->whatNext    = Dis_StopHere;
8447   }
8448
8449   return True;
8450}
8451
8452static Bool dis_trap ( UInt theInstr,
8453                        /*OUT*/DisResult* dres )
8454{
8455   /* X-Form */
8456   UInt   opc2    = ifieldOPClo10(theInstr);
8457   UChar  TO      = ifieldRegDS(theInstr);
8458   UChar  rA_addr = ifieldRegA(theInstr);
8459   UChar  rB_addr = ifieldRegB(theInstr);
8460   Addr64 cia     = guest_CIA_curr_instr;
8461   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
8462   Bool   uncond  = False;
8463
8464   if (ifieldBIT0(theInstr) != 0)
8465      return False;
8466
8467   switch (opc2) {
8468   case 0x004: // tw  (Trap Word, PPC64 p540)
8469      uncond = do_trap( TO,
8470                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
8471                               : getIReg(rA_addr),
8472                        mode64 ? unop(Iop_64to32, getIReg(rB_addr))
8473                               : getIReg(rB_addr),
8474                        cia );
8475      if (TO == 4) {
8476         DIP("tweq r%u,r%u\n", rA_addr, rB_addr);
8477      } else {
8478         DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr);
8479      }
8480      break;
8481   case 0x044: // td (Trap Doubleword, PPC64 p534)
8482      if (!mode64)
8483         return False;
8484      uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
8485      if (TO == 4) {
8486         DIP("tdeq r%u,r%u\n", rA_addr, rB_addr);
8487      } else {
8488         DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr);
8489      }
8490      break;
8491   default:
8492      return False;
8493   }
8494
8495   if (uncond) {
8496      /* If the trap shows signs of being unconditional, don't
8497         continue decoding past it. */
8498      putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
8499      dres->jk_StopHere = Ijk_Boring;
8500      dres->whatNext    = Dis_StopHere;
8501   }
8502
8503   return True;
8504}
8505
8506
8507/*
8508  System Linkage Instructions
8509*/
8510static Bool dis_syslink ( UInt theInstr,
8511                          const VexAbiInfo* abiinfo, DisResult* dres )
8512{
8513   IRType ty = mode64 ? Ity_I64 : Ity_I32;
8514
8515   if (theInstr != 0x44000002) {
8516      vex_printf("dis_syslink(ppc)(theInstr)\n");
8517      return False;
8518   }
8519
8520   // sc  (System Call, PPC32 p504)
8521   DIP("sc\n");
8522
8523   /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
8524      Valgrind can back the guest up to this instruction if it needs
8525      to restart the syscall. */
8526   putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
8527
8528   /* It's important that all ArchRegs carry their up-to-date value
8529      at this point.  So we declare an end-of-block here, which
8530      forces any TempRegs caching ArchRegs to be flushed. */
8531   putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
8532
8533   dres->whatNext    = Dis_StopHere;
8534   dres->jk_StopHere = Ijk_Sys_syscall;
8535   return True;
8536}
8537
8538
8539/*
8540  Memory Synchronization Instructions
8541
8542  Note on Reservations:
8543  We rely on the assumption that V will in fact only allow one thread at
8544  once to run.  In effect, a thread can make a reservation, but we don't
8545  check any stores it does.  Instead, the reservation is cancelled when
8546  the scheduler switches to another thread (run_thread_for_a_while()).
8547*/
8548static Bool dis_memsync ( UInt theInstr )
8549{
8550   /* X-Form, XL-Form */
8551   UChar opc1    = ifieldOPC(theInstr);
8552   UInt  b11to25 = IFIELD(theInstr, 11, 15);
8553   UChar flag_L  = ifieldRegDS(theInstr);
8554   UInt  b11to20 = IFIELD(theInstr, 11, 10);
8555   UInt  M0      = IFIELD(theInstr, 11, 5);
8556   UChar rD_addr = ifieldRegDS(theInstr);
8557   UChar rS_addr = rD_addr;
8558   UChar rA_addr = ifieldRegA(theInstr);
8559   UChar rB_addr = ifieldRegB(theInstr);
8560   UInt  opc2    = ifieldOPClo10(theInstr);
8561   UChar b0      = ifieldBIT0(theInstr);
8562
8563   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
8564   IRTemp EA     = newTemp(ty);
8565
8566   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
8567
8568   switch (opc1) {
8569   /* XL-Form */
8570   case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
8571      if (opc2 != 0x096) {
8572         vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
8573         return False;
8574      }
8575      if (b11to25 != 0 || b0 != 0) {
8576         vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
8577         return False;
8578      }
8579      DIP("isync\n");
8580      stmt( IRStmt_MBE(Imbe_Fence) );
8581      break;
8582
8583   /* X-Form */
8584   case 0x1F:
8585      switch (opc2) {
8586      case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394)
8587         if (M0 == 0) {
8588            if (b11to20 != 0 || b0 != 0) {
8589               vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n");
8590               return False;
8591            }
8592            DIP("eieio\n");
8593         } else {
8594            if (b11to20 != 0 || b0 != 0) {
8595               vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n");
8596               return False;
8597            }
8598            DIP("mbar %d\n", M0);
8599         }
8600         /* Insert a memory fence, just to be on the safe side. */
8601         stmt( IRStmt_MBE(Imbe_Fence) );
8602         break;
8603
8604      case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
8605         IRTemp res;
8606         /* According to the PowerPC ISA version 2.05, b0 (called EH
8607            in the documentation) is merely a hint bit to the
8608            hardware, I think as to whether or not contention is
8609            likely.  So we can just ignore it. */
8610         DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
8611
8612         // trap if misaligned
8613         gen_SIGBUS_if_misaligned( EA, 4 );
8614
8615         // and actually do the load
8616         res = newTemp(Ity_I32);
8617         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
8618
8619         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
8620         break;
8621      }
8622
8623      case 0x034: { // lbarx (Load Word and Reserve Indexed)
8624         IRTemp res;
8625         /* According to the PowerPC ISA version 2.05, b0 (called EH
8626            in the documentation) is merely a hint bit to the
8627            hardware, I think as to whether or not contention is
8628            likely.  So we can just ignore it. */
8629         DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
8630
8631         // and actually do the load
8632         res = newTemp(Ity_I8);
8633         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
8634
8635         putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) );
8636         break;
8637     }
8638
8639      case 0x074: { // lharx (Load Word and Reserve Indexed)
8640         IRTemp res;
8641         /* According to the PowerPC ISA version 2.05, b0 (called EH
8642            in the documentation) is merely a hint bit to the
8643            hardware, I think as to whether or not contention is
8644            likely.  So we can just ignore it. */
8645         DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
8646
8647         // trap if misaligned
8648         gen_SIGBUS_if_misaligned( EA, 2 );
8649
8650         // and actually do the load
8651         res = newTemp(Ity_I16);
8652         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
8653
8654         putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) );
8655         break;
8656      }
8657
8658      case 0x096: {
8659         // stwcx. (Store Word Conditional Indexed, PPC32 p532)
8660         // Note this has to handle stwcx. in both 32- and 64-bit modes,
8661         // so isn't quite as straightforward as it might otherwise be.
8662         IRTemp rS = newTemp(Ity_I32);
8663         IRTemp resSC;
8664         if (b0 != 1) {
8665            vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
8666            return False;
8667         }
8668         DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
8669
8670         // trap if misaligned
8671         gen_SIGBUS_if_misaligned( EA, 4 );
8672
8673         // Get the data to be stored, and narrow to 32 bits if necessary
8674         assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
8675
8676         // Do the store, and get success/failure bit into resSC
8677         resSC = newTemp(Ity_I1);
8678         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
8679
8680         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
8681         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
8682         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
8683         putCR0(0, getXER_SO());
8684
8685         /* Note:
8686            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
8687            whether rS is stored is dependent on that value. */
8688         /* So I guess we can just ignore this case? */
8689         break;
8690      }
8691
8692      case 0x2B6: {
8693         // stbcx. (Store Byte Conditional Indexed)
8694         // Note this has to handle stbcx. in both 32- and 64-bit modes,
8695         // so isn't quite as straightforward as it might otherwise be.
8696         IRTemp rS = newTemp(Ity_I8);
8697         IRTemp resSC;
8698         if (b0 != 1) {
8699            vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
8700            return False;
8701         }
8702         DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
8703
8704         // Get the data to be stored, and narrow to 32 bits if necessary
8705         assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) );
8706
8707         // Do the store, and get success/failure bit into resSC
8708         resSC = newTemp(Ity_I1);
8709         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
8710
8711         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
8712         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
8713         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
8714         putCR0(0, getXER_SO());
8715
8716         /* Note:
8717            If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and
8718            whether rS is stored is dependent on that value. */
8719         /* So I guess we can just ignore this case? */
8720         break;
8721      }
8722
8723      case 0x2D6: {
8724         // sthcx. (Store Word Conditional Indexed, PPC32 p532)
8725         // Note this has to handle sthcx. in both 32- and 64-bit modes,
8726         // so isn't quite as straightforward as it might otherwise be.
8727         IRTemp rS = newTemp(Ity_I16);
8728         IRTemp resSC;
8729         if (b0 != 1) {
8730            vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
8731            return False;
8732         }
8733         DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
8734
8735         // trap if misaligned
8736         gen_SIGBUS_if_misaligned( EA, 2 );
8737
8738         // Get the data to be stored, and narrow to 16 bits if necessary
8739         assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) );
8740
8741         // Do the store, and get success/failure bit into resSC
8742         resSC = newTemp(Ity_I1);
8743         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
8744
8745         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
8746         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
8747         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
8748         putCR0(0, getXER_SO());
8749
8750         /* Note:
8751            If resaddr != lharx_resaddr, CR0[EQ] is undefined, and
8752            whether rS is stored is dependent on that value. */
8753         /* So I guess we can just ignore this case? */
8754         break;
8755      }
8756
8757      case 0x256: // sync (Synchronize, PPC32 p543),
8758                  // also lwsync (L==1), ptesync (L==2)
8759         /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
8760
8761            The PowerPC architecture used in IBM chips has expanded
8762            the sync instruction into two variants: lightweight sync
8763            and heavyweight sync.  The original sync instruction is
8764            the new heavyweight sync and lightweight sync is a strict
8765            subset of the heavyweight sync functionality. This allows
8766            the programmer to specify a less expensive operation on
8767            high-end systems when the full sync functionality is not
8768            necessary.
8769
8770            The basic "sync" mnemonic now utilizes an operand. "sync"
8771            without an operand now becomes a extended mnemonic for
8772            heavyweight sync.  Processors without the lwsync
8773            instruction will not decode the L field and will perform a
8774            heavyweight sync.  Everything is backward compatible.
8775
8776            sync    =       sync 0
8777            lwsync  =       sync 1
8778            ptesync =       sync 2    *** TODO - not implemented ***
8779         */
8780         if (b11to20 != 0 || b0 != 0) {
8781            vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
8782            return False;
8783         }
8784         if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
8785            vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
8786            return False;
8787         }
8788         DIP("%ssync\n", flag_L == 1 ? "lw" : "");
8789         /* Insert a memory fence.  It's sometimes important that these
8790            are carried through to the generated code. */
8791         stmt( IRStmt_MBE(Imbe_Fence) );
8792         break;
8793
8794      /* 64bit Memsync */
8795      case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
8796         IRTemp res;
8797         /* According to the PowerPC ISA version 2.05, b0 (called EH
8798            in the documentation) is merely a hint bit to the
8799            hardware, I think as to whether or not contention is
8800            likely.  So we can just ignore it. */
8801         if (!mode64)
8802            return False;
8803         DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
8804
8805         // trap if misaligned
8806         gen_SIGBUS_if_misaligned( EA, 8 );
8807
8808         // and actually do the load
8809         res = newTemp(Ity_I64);
8810         stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) );
8811
8812         putIReg( rD_addr, mkexpr(res) );
8813         break;
8814      }
8815
8816      case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
8817         // A marginally simplified version of the stwcx. case
8818         IRTemp rS = newTemp(Ity_I64);
8819         IRTemp resSC;
8820         if (b0 != 1) {
8821            vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
8822            return False;
8823         }
8824         if (!mode64)
8825            return False;
8826         DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
8827
8828         // trap if misaligned
8829         gen_SIGBUS_if_misaligned( EA, 8 );
8830
8831         // Get the data to be stored
8832         assign( rS, getIReg(rS_addr) );
8833
8834         // Do the store, and get success/failure bit into resSC
8835         resSC = newTemp(Ity_I1);
8836         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
8837
8838         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
8839         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
8840         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
8841         putCR0(0, getXER_SO());
8842
8843         /* Note:
8844            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
8845            whether rS is stored is dependent on that value. */
8846         /* So I guess we can just ignore this case? */
8847         break;
8848      }
8849
8850      /* 128bit Memsync */
8851      case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
8852         IRTemp res_hi = newTemp(ty);
8853         IRTemp res_lo = newTemp(ty);
8854
8855         /* According to the PowerPC ISA version 2.07, b0 (called EH
8856            in the documentation) is merely a hint bit to the
8857            hardware, I think as to whether or not contention is
8858            likely.  So we can just ignore it. */
8859         DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
8860
8861         // trap if misaligned
8862         gen_SIGBUS_if_misaligned( EA, 16 );
8863
8864         // and actually do the load
8865         if (mode64) {
8866            if (host_endness == VexEndnessBE) {
8867               stmt( stmt_load( res_hi,
8868                                mkexpr(EA), NULL/*this is a load*/) );
8869               stmt( stmt_load( res_lo,
8870                                binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
8871                                NULL/*this is a load*/) );
8872	    } else {
8873               stmt( stmt_load( res_lo,
8874                                mkexpr(EA), NULL/*this is a load*/) );
8875               stmt( stmt_load( res_hi,
8876                                binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
8877                                NULL/*this is a load*/) );
8878            }
8879         } else {
8880            stmt( stmt_load( res_hi,
8881                             binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
8882                             NULL/*this is a load*/) );
8883            stmt( stmt_load( res_lo,
8884                             binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
8885                             NULL/*this is a load*/) );
8886         }
8887         putIReg( rD_addr,   mkexpr(res_hi) );
8888         putIReg( rD_addr+1, mkexpr(res_lo) );
8889         break;
8890      }
8891
8892      case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
8893         // A marginally simplified version of the stwcx. case
8894         IRTemp rS_hi = newTemp(ty);
8895         IRTemp rS_lo = newTemp(ty);
8896         IRTemp resSC;
8897         if (b0 != 1) {
8898            vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
8899            return False;
8900         }
8901
8902         DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
8903
8904         // trap if misaligned
8905         gen_SIGBUS_if_misaligned( EA, 16 );
8906         // Get the data to be stored
8907         assign( rS_hi, getIReg(rS_addr) );
8908         assign( rS_lo, getIReg(rS_addr+1) );
8909
8910         // Do the store, and get success/failure bit into resSC
8911         resSC = newTemp(Ity_I1);
8912
8913         if (mode64) {
8914            if (host_endness == VexEndnessBE) {
8915               stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) );
8916               store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
8917                      mkexpr(rS_lo) );
8918	    } else {
8919               stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) );
8920               store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
8921                      mkexpr(rS_hi) );
8922	    }
8923         } else {
8924            stmt( stmt_load( resSC, binop( Iop_Add32,
8925                                           mkexpr(EA),
8926                                           mkU32(4) ),
8927                                           mkexpr(rS_hi) ) );
8928            store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
8929         }
8930
8931         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
8932         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
8933         putCR321(0, binop( Iop_Shl8,
8934                            unop(Iop_1Uto8, mkexpr(resSC) ),
8935                            mkU8(1)));
8936         putCR0(0, getXER_SO());
8937         break;
8938      }
8939
8940      default:
8941         vex_printf("dis_memsync(ppc)(opc2)\n");
8942         return False;
8943      }
8944      break;
8945
8946   default:
8947      vex_printf("dis_memsync(ppc)(opc1)\n");
8948      return False;
8949   }
8950   return True;
8951}
8952
8953
8954
8955/*
8956  Integer Shift Instructions
8957*/
8958static Bool dis_int_shift ( UInt theInstr )
8959{
8960   /* X-Form, XS-Form */
8961   UChar opc1    = ifieldOPC(theInstr);
8962   UChar rS_addr = ifieldRegDS(theInstr);
8963   UChar rA_addr = ifieldRegA(theInstr);
8964   UChar rB_addr = ifieldRegB(theInstr);
8965   UChar sh_imm  = rB_addr;
8966   UInt  opc2    = ifieldOPClo10(theInstr);
8967   UChar b1      = ifieldBIT1(theInstr);
8968   UChar flag_rC = ifieldBIT0(theInstr);
8969
8970   IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
8971   IRTemp  rA         = newTemp(ty);
8972   IRTemp  rS         = newTemp(ty);
8973   IRTemp  rB         = newTemp(ty);
8974   IRTemp  outofrange = newTemp(Ity_I1);
8975   IRTemp  rS_lo32    = newTemp(Ity_I32);
8976   IRTemp  rB_lo32    = newTemp(Ity_I32);
8977   IRExpr* e_tmp;
8978
8979   assign( rS, getIReg(rS_addr) );
8980   assign( rB, getIReg(rB_addr) );
8981   assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
8982   assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
8983
8984   if (opc1 == 0x1F) {
8985      switch (opc2) {
8986      case 0x018: { // slw (Shift Left Word, PPC32 p505)
8987         DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
8988             rA_addr, rS_addr, rB_addr);
8989         /* rA = rS << rB */
8990         /* ppc32 semantics are:
8991            slw(x,y) = (x << (y & 31))         -- primary result
8992                       & ~((y << 26) >>s 31)   -- make result 0
8993                                                  for y in 32 .. 63
8994         */
8995         e_tmp =
8996            binop( Iop_And32,
8997               binop( Iop_Shl32,
8998                      mkexpr(rS_lo32),
8999                      unop( Iop_32to8,
9000                            binop(Iop_And32,
9001                                  mkexpr(rB_lo32), mkU32(31)))),
9002               unop( Iop_Not32,
9003                     binop( Iop_Sar32,
9004                            binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
9005                            mkU8(31))) );
9006         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
9007         break;
9008      }
9009
9010      case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
9011         IRTemp sh_amt = newTemp(Ity_I32);
9012         DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
9013             rA_addr, rS_addr, rB_addr);
9014         /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
9015            amt = rB & 63
9016            rA = Sar32( rS, amt > 31 ? 31 : amt )
9017            XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
9018         */
9019         assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
9020                                          mkexpr(rB_lo32)) );
9021         assign( outofrange,
9022                 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) );
9023         e_tmp = binop( Iop_Sar32,
9024                        mkexpr(rS_lo32),
9025                        unop( Iop_32to8,
9026                              IRExpr_ITE( mkexpr(outofrange),
9027                                          mkU32(31),
9028                                          mkexpr(sh_amt)) ) );
9029         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
9030
9031         set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAW,
9032                          mkexpr(rA),
9033                          mkWidenFrom32(ty, mkexpr(rS_lo32), True),
9034                          mkWidenFrom32(ty, mkexpr(sh_amt), True ),
9035                          mkWidenFrom32(ty, getXER_CA_32(), True) );
9036         break;
9037      }
9038
9039      case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
9040         DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
9041             rA_addr, rS_addr, sh_imm);
9042         vassert(sh_imm < 32);
9043         if (mode64) {
9044            assign( rA, binop(Iop_Sar64,
9045                              binop(Iop_Shl64, getIReg(rS_addr),
9046                                               mkU8(32)),
9047                              mkU8(32 + sh_imm)) );
9048         } else {
9049            assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
9050                                         mkU8(sh_imm)) );
9051         }
9052
9053         set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAWI,
9054                          mkexpr(rA),
9055                          mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
9056                          mkSzImm(ty, sh_imm),
9057                          mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) );
9058         break;
9059
9060      case 0x218: // srw (Shift Right Word, PPC32 p508)
9061         DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
9062             rA_addr, rS_addr, rB_addr);
9063         /* rA = rS >>u rB */
9064         /* ppc32 semantics are:
9065            srw(x,y) = (x >>u (y & 31))        -- primary result
9066                       & ~((y << 26) >>s 31)   -- make result 0
9067                                                  for y in 32 .. 63
9068         */
9069         e_tmp =
9070            binop(
9071               Iop_And32,
9072               binop( Iop_Shr32,
9073                      mkexpr(rS_lo32),
9074                      unop( Iop_32to8,
9075                            binop(Iop_And32, mkexpr(rB_lo32),
9076                                             mkU32(31)))),
9077               unop( Iop_Not32,
9078                     binop( Iop_Sar32,
9079                            binop(Iop_Shl32, mkexpr(rB_lo32),
9080                                             mkU8(26)),
9081                            mkU8(31))));
9082         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
9083         break;
9084
9085
9086      /* 64bit Shifts */
9087      case 0x01B: // sld (Shift Left DWord, PPC64 p568)
9088         DIP("sld%s r%u,r%u,r%u\n",
9089             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
9090         /* rA = rS << rB */
9091         /* ppc64 semantics are:
9092            slw(x,y) = (x << (y & 63))         -- primary result
9093                       & ~((y << 57) >>s 63)   -- make result 0
9094                                                  for y in 64 ..
9095         */
9096         assign( rA,
9097            binop(
9098               Iop_And64,
9099               binop( Iop_Shl64,
9100                      mkexpr(rS),
9101                      unop( Iop_64to8,
9102                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
9103               unop( Iop_Not64,
9104                     binop( Iop_Sar64,
9105                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
9106                            mkU8(63)))) );
9107         break;
9108
9109      case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
9110         IRTemp sh_amt = newTemp(Ity_I64);
9111         DIP("srad%s r%u,r%u,r%u\n",
9112             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
9113         /* amt = rB & 127
9114            rA = Sar64( rS, amt > 63 ? 63 : amt )
9115            XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
9116         */
9117         assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
9118         assign( outofrange,
9119                 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) );
9120         assign( rA,
9121                 binop( Iop_Sar64,
9122                        mkexpr(rS),
9123                        unop( Iop_64to8,
9124                              IRExpr_ITE( mkexpr(outofrange),
9125                                          mkU64(63),
9126                                          mkexpr(sh_amt)) ))
9127               );
9128         set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAD,
9129                          mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
9130                          mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) );
9131         break;
9132      }
9133
9134      case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
9135         sh_imm |= b1<<5;
9136         vassert(sh_imm < 64);
9137         DIP("sradi%s r%u,r%u,%u\n",
9138             flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
9139         assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
9140
9141         set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRADI,
9142                          mkexpr(rA),
9143                          getIReg(rS_addr),
9144                          mkU64(sh_imm),
9145                          mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) );
9146         break;
9147
9148      case 0x21B: // srd (Shift Right DWord, PPC64 p574)
9149         DIP("srd%s r%u,r%u,r%u\n",
9150             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
9151         /* rA = rS >>u rB */
9152         /* ppc semantics are:
9153            srw(x,y) = (x >>u (y & 63))        -- primary result
9154                       & ~((y << 57) >>s 63)   -- make result 0
9155                                                  for y in 64 .. 127
9156         */
9157         assign( rA,
9158            binop(
9159               Iop_And64,
9160               binop( Iop_Shr64,
9161                      mkexpr(rS),
9162                      unop( Iop_64to8,
9163                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
9164               unop( Iop_Not64,
9165                     binop( Iop_Sar64,
9166                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
9167                            mkU8(63)))) );
9168         break;
9169
9170      default:
9171         vex_printf("dis_int_shift(ppc)(opc2)\n");
9172         return False;
9173      }
9174   } else {
9175      vex_printf("dis_int_shift(ppc)(opc1)\n");
9176      return False;
9177   }
9178
9179   putIReg( rA_addr, mkexpr(rA) );
9180
9181   if (flag_rC) {
9182      set_CR0( mkexpr(rA) );
9183   }
9184   return True;
9185}
9186
9187
9188
9189/*
9190  Integer Load/Store Reverse Instructions
9191*/
9192/* Generates code to swap the byte order in an Ity_I32. */
9193static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
9194{
9195   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
9196   return
9197      binop(Iop_Or32,
9198         binop(Iop_Shl32, mkexpr(t), mkU8(24)),
9199      binop(Iop_Or32,
9200         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
9201                          mkU32(0x00FF0000)),
9202      binop(Iop_Or32,
9203         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
9204                          mkU32(0x0000FF00)),
9205         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
9206                          mkU32(0x000000FF) )
9207      )));
9208}
9209
9210/* Generates code to swap the byte order in the lower half of an Ity_I32,
9211   and zeroes the upper half. */
9212static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
9213{
9214   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
9215   return
9216      binop(Iop_Or32,
9217         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
9218                          mkU32(0x0000FF00)),
9219         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
9220                          mkU32(0x000000FF))
9221      );
9222}
9223
9224static Bool dis_int_ldst_rev ( UInt theInstr )
9225{
9226   /* X-Form */
9227   UChar opc1    = ifieldOPC(theInstr);
9228   UChar rD_addr = ifieldRegDS(theInstr);
9229   UChar rS_addr = rD_addr;
9230   UChar rA_addr = ifieldRegA(theInstr);
9231   UChar rB_addr = ifieldRegB(theInstr);
9232   UInt  opc2    = ifieldOPClo10(theInstr);
9233   UChar b0      = ifieldBIT0(theInstr);
9234
9235   IRType ty = mode64 ? Ity_I64 : Ity_I32;
9236   IRTemp EA = newTemp(ty);
9237   IRTemp w1 = newTemp(Ity_I32);
9238   IRTemp w2 = newTemp(Ity_I32);
9239
9240   if (opc1 != 0x1F || b0 != 0) {
9241      vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
9242      return False;
9243   }
9244
9245   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
9246
9247   switch (opc2) {
9248
9249      case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
9250         DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
9251         assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) );
9252         assign( w2, gen_byterev16(w1) );
9253         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
9254                                         /* Signed */False) );
9255         break;
9256
9257      case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
9258         DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
9259         assign( w1, load(Ity_I32, mkexpr(EA)) );
9260         assign( w2, gen_byterev32(w1) );
9261         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
9262                                         /* Signed */False) );
9263         break;
9264
9265      case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
9266      {
9267         IRExpr * nextAddr;
9268         IRTemp w3 = newTemp( Ity_I32 );
9269         IRTemp w4 = newTemp( Ity_I32 );
9270         DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
9271         assign( w1, load( Ity_I32, mkexpr( EA ) ) );
9272         assign( w2, gen_byterev32( w1 ) );
9273         nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
9274                           ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
9275         assign( w3, load( Ity_I32, nextAddr ) );
9276         assign( w4, gen_byterev32( w3 ) );
9277         if (host_endness == VexEndnessLE)
9278            putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) );
9279         else
9280            putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
9281         break;
9282      }
9283
9284      case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
9285         DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
9286         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
9287         store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
9288         break;
9289
9290      case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
9291         DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
9292         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
9293         store( mkexpr(EA), gen_byterev32(w1) );
9294         break;
9295
9296      case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
9297      {
9298         IRTemp lo = newTemp(Ity_I32);
9299         IRTemp hi = newTemp(Ity_I32);
9300         IRTemp rS = newTemp(Ity_I64);
9301         assign( rS, getIReg( rS_addr ) );
9302         DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
9303         assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
9304         assign(hi, unop(Iop_64to32, mkexpr(rS)));
9305         store( mkexpr( EA ),
9306                binop( Iop_32HLto64, gen_byterev32( hi ),
9307                       gen_byterev32( lo ) ) );
9308         break;
9309      }
9310
9311      default:
9312         vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
9313         return False;
9314   }
9315   return True;
9316}
9317
9318
9319
9320/*
9321  Processor Control Instructions
9322*/
9323static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr )
9324{
9325   UChar opc1     = ifieldOPC(theInstr);
9326
9327   /* X-Form */
9328   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
9329   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
9330   UChar rD_addr  = ifieldRegDS(theInstr);
9331   UInt  b11to20  = IFIELD( theInstr, 11, 10 );
9332
9333   /* XFX-Form */
9334   UChar rS_addr  = rD_addr;
9335   UInt  SPR      = b11to20;
9336   UInt  TBR      = b11to20;
9337   UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
9338   UInt  CRM      = IFIELD( theInstr, 12, 8 );
9339   UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
9340
9341   UInt  opc2     = ifieldOPClo10(theInstr);
9342   UChar b0       = ifieldBIT0(theInstr);
9343
9344   IRType ty = mode64 ? Ity_I64 : Ity_I32;
9345   IRTemp rS = newTemp(ty);
9346   assign( rS, getIReg(rS_addr) );
9347
9348   /* Reorder SPR field as per PPC32 p470 */
9349   SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
9350   /* Reorder TBR field as per PPC32 p475 */
9351   TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
9352
9353   /* b0 = 0, inst is treated as floating point inst for reservation purposes
9354    * b0 = 1, inst is treated as vector inst for reservation purposes
9355    */
9356   if (opc1 != 0x1F) {
9357      vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0);
9358      return False;
9359   }
9360
9361   switch (opc2) {
9362   /* X-Form */
9363   case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
9364      if (b21to22 != 0 || b11to20 != 0) {
9365         vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
9366         return False;
9367      }
9368      DIP("mcrxr crf%d\n", crfD);
9369      /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
9370      putGST_field( PPC_GST_CR,
9371                    getGST_field( PPC_GST_XER, 7 ),
9372                    crfD );
9373
9374      // Clear XER[0-3]
9375      putXER_SO( mkU8(0) );
9376      putXER_OV( mkU8(0) );
9377      putXER_CA( mkU8(0) );
9378      break;
9379   }
9380
9381   case 0x013:
9382      // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
9383      // b20==1 & b11==0: mfocrf (Move from One CR Field)
9384      // However it seems that the 'mfcr' behaviour is an acceptable
9385      // implementation of mfocr (from the 2.02 arch spec)
9386      if (b11to20 == 0) {
9387         DIP("mfcr r%u\n", rD_addr);
9388         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
9389                                         /* Signed */False) );
9390         break;
9391      }
9392      if (b20 == 1 && b11 == 0) {
9393         DIP("mfocrf r%u,%u\n", rD_addr, CRM);
9394         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
9395                                         /* Signed */False) );
9396         break;
9397      }
9398      /* not decodable */
9399      return False;
9400
9401   /* XFX-Form */
9402   case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
9403
9404      switch (SPR) {  // Choose a register...
9405      case 0x1:
9406         DIP("mfxer r%u\n", rD_addr);
9407         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
9408                                         /* Signed */False) );
9409         break;
9410      case 0x8:
9411         DIP("mflr r%u\n", rD_addr);
9412         putIReg( rD_addr, getGST( PPC_GST_LR ) );
9413         break;
9414      case 0x9:
9415         DIP("mfctr r%u\n", rD_addr);
9416         putIReg( rD_addr, getGST( PPC_GST_CTR ) );
9417         break;
9418      case 0x80:  // 128
9419         DIP("mfspr r%u (TFHAR)\n", rD_addr);
9420         putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
9421         break;
9422      case 0x81:  // 129
9423         DIP("mfspr r%u (TFIAR)\n", rD_addr);
9424         putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
9425         break;
9426      case 0x82:  // 130
9427         DIP("mfspr r%u (TEXASR)\n", rD_addr);
9428         putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
9429         break;
9430      case 0x83:  // 131
9431         DIP("mfspr r%u (TEXASRU)\n", rD_addr);
9432         putIReg( rD_addr, getGST( PPC_GST_TEXASRU) );
9433         break;
9434      case 0x9F:  // 159
9435         DIP("mfspr r%u (PSPB)\n", rD_addr);
9436         putIReg( rD_addr, getGST( PPC_GST_PSPB) );
9437         break;
9438      case 0x380:  // 896
9439         DIP("mfspr r%u (PPR)\n", rD_addr);
9440         putIReg( rD_addr, getGST( PPC_GST_PPR) );
9441         break;
9442      case 0x382:  // 898
9443         DIP("mfspr r%u (PPR)32\n", rD_addr);
9444         putIReg( rD_addr, getGST( PPC_GST_PPR32) );
9445         break;
9446      case 0x100:
9447         DIP("mfvrsave r%u\n", rD_addr);
9448         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
9449                                         /* Signed */False) );
9450         break;
9451
9452      case 0x103:
9453         DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
9454         putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
9455         break;
9456
9457      /* Even a lowly PPC7400 can run the associated helper, so no
9458         obvious need for feature testing at this point. */
9459      case 268 /* 0x10C */:
9460      case 269 /* 0x10D */: {
9461         UInt     arg  = SPR==268 ? 0 : 1;
9462         IRTemp   val  = newTemp(Ity_I32);
9463         IRExpr** args = mkIRExprVec_1( mkU32(arg) );
9464         IRDirty* d    = unsafeIRDirty_1_N(
9465                            val,
9466                            0/*regparms*/,
9467                            "ppc32g_dirtyhelper_MFSPR_268_269",
9468                            fnptr_to_fnentry
9469                               (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
9470                            args
9471                         );
9472         /* execute the dirty call, dumping the result in val. */
9473         stmt( IRStmt_Dirty(d) );
9474         putIReg( rD_addr,
9475                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
9476         DIP("mfspr r%u,%u", rD_addr, SPR);
9477         break;
9478      }
9479
9480      /* Again, runs natively on PPC7400 (7447, really).  Not
9481         bothering with a feature test. */
9482      case 287: /* 0x11F */ {
9483         IRTemp   val  = newTemp(Ity_I32);
9484         IRExpr** args = mkIRExprVec_0();
9485         IRDirty* d    = unsafeIRDirty_1_N(
9486                            val,
9487                            0/*regparms*/,
9488                            "ppc32g_dirtyhelper_MFSPR_287",
9489                            fnptr_to_fnentry
9490                               (vbi, &ppc32g_dirtyhelper_MFSPR_287),
9491                            args
9492                         );
9493         /* execute the dirty call, dumping the result in val. */
9494         stmt( IRStmt_Dirty(d) );
9495         putIReg( rD_addr,
9496                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
9497         DIP("mfspr r%u,%u", rD_addr, SPR);
9498         break;
9499      }
9500
9501      default:
9502         vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
9503         return False;
9504      }
9505      break;
9506
9507   case 0x173: { // mftb (Move from Time Base, PPC32 p475)
9508      IRTemp   val  = newTemp(Ity_I64);
9509      IRExpr** args = mkIRExprVec_0();
9510      IRDirty* d    = unsafeIRDirty_1_N(
9511                              val,
9512                              0/*regparms*/,
9513                              "ppcg_dirtyhelper_MFTB",
9514                              fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
9515                              args );
9516      /* execute the dirty call, dumping the result in val. */
9517      stmt( IRStmt_Dirty(d) );
9518
9519      switch (TBR) {
9520      case 269:
9521         DIP("mftbu r%u", rD_addr);
9522         putIReg( rD_addr,
9523                  mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
9524                                /* Signed */False) );
9525         break;
9526      case 268:
9527         DIP("mftb r%u", rD_addr);
9528         putIReg( rD_addr, (mode64) ? mkexpr(val) :
9529                                      unop(Iop_64to32, mkexpr(val)) );
9530         break;
9531      default:
9532         return False; /* illegal instruction */
9533      }
9534      break;
9535   }
9536
9537   case 0x090: {
9538      // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
9539      // b20==1: mtocrf (Move to One Cond Reg Field)
9540      Int   cr;
9541      UChar shft;
9542      if (b11 != 0)
9543         return False;
9544      if (b20 == 1) {
9545         /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
9546            1 field is written.  It seems more robust to decline to
9547            decode the insn if so. */
9548         switch (CRM) {
9549            case 0x01: case 0x02: case 0x04: case 0x08:
9550            case 0x10: case 0x20: case 0x40: case 0x80:
9551               break;
9552            default:
9553               return False;
9554         }
9555      }
9556      DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
9557                           CRM, rS_addr);
9558      /* Write to each field specified by CRM */
9559      for (cr = 0; cr < 8; cr++) {
9560         if ((CRM & (1 << (7-cr))) == 0)
9561            continue;
9562         shft = 4*(7-cr);
9563         putGST_field( PPC_GST_CR,
9564                       binop(Iop_Shr32,
9565                             mkNarrowTo32(ty, mkexpr(rS)),
9566                             mkU8(shft)), cr );
9567      }
9568      break;
9569   }
9570
9571   case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
9572
9573      switch (SPR) {  // Choose a register...
9574      case 0x1:
9575         DIP("mtxer r%u\n", rS_addr);
9576         putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
9577         break;
9578      case 0x8:
9579         DIP("mtlr r%u\n", rS_addr);
9580         putGST( PPC_GST_LR, mkexpr(rS) );
9581         break;
9582      case 0x9:
9583         DIP("mtctr r%u\n", rS_addr);
9584         putGST( PPC_GST_CTR, mkexpr(rS) );
9585         break;
9586      case 0x100:
9587         DIP("mtvrsave r%u\n", rS_addr);
9588         putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
9589         break;
9590      case 0x80:  // 128
9591         DIP("mtspr r%u (TFHAR)\n", rS_addr);
9592         putGST( PPC_GST_TFHAR, mkexpr(rS) );
9593         break;
9594      case 0x81:  // 129
9595         DIP("mtspr r%u (TFIAR)\n", rS_addr);
9596         putGST( PPC_GST_TFIAR, mkexpr(rS) );
9597         break;
9598      case 0x82:  // 130
9599         DIP("mtspr r%u (TEXASR)\n", rS_addr);
9600         putGST( PPC_GST_TEXASR, mkexpr(rS) );
9601         break;
9602      case 0x9F:  // 159
9603         DIP("mtspr r%u (PSPB)\n", rS_addr);
9604         putGST( PPC_GST_PSPB, mkexpr(rS) );
9605         break;
9606      case 0x380:  // 896
9607         DIP("mtspr r%u (PPR)\n", rS_addr);
9608         putGST( PPC_GST_PPR, mkexpr(rS) );
9609         break;
9610      case 0x382:  // 898
9611         DIP("mtspr r%u (PPR32)\n", rS_addr);
9612         putGST( PPC_GST_PPR32, mkexpr(rS) );
9613         break;
9614      default:
9615         vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
9616         return False;
9617      }
9618      break;
9619
9620   case 0x33:                // mfvsrd
9621   {
9622      UChar XS = ifieldRegXS( theInstr );
9623      UChar rA_addr = ifieldRegA(theInstr);
9624      IRExpr * high64;
9625      IRTemp vS = newTemp( Ity_V128 );
9626      DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS);
9627
9628      /*  XS = SX || S
9629       *  For SX=0, mfvsrd is treated as a Floating-Point
9630       *            instruction in terms of resource availability.
9631       *  For SX=1, mfvsrd is treated as a Vector instruction in
9632       *            terms of resource availability.
9633       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9634       */
9635      assign( vS, getVSReg( XS ) );
9636      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
9637      putIReg( rA_addr, (mode64) ? high64 :
9638      unop( Iop_64to32, high64 ) );
9639      break;
9640   }
9641
9642   case 0x73:                // mfvsrwz
9643   {
9644      UChar XS = ifieldRegXS( theInstr );
9645      UChar rA_addr = ifieldRegA(theInstr);
9646      IRExpr * high64;
9647      IRTemp vS = newTemp( Ity_V128 );
9648      DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS);
9649      /*  XS = SX || S
9650       *  For SX=0, mfvsrwz is treated as a Floating-Point
9651       *            instruction in terms of resource availability.
9652       *  For SX=1, mfvsrwz is treated as a Vector instruction in
9653       *            terms of resource availability.
9654       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9655       */
9656
9657      assign( vS, getVSReg( XS ) );
9658      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
9659      /* move value to the destination setting the upper 32-bits to zero */
9660      putIReg( rA_addr, (mode64) ?
9661                                  binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) :
9662                                  unop(  Iop_64to32,
9663                                         binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
9664      break;
9665   }
9666
9667   case 0xB3:                // mtvsrd
9668   {
9669      UChar XT = ifieldRegXT( theInstr );
9670      UChar rA_addr = ifieldRegA(theInstr);
9671      IRTemp rA = newTemp(ty);
9672      DIP("mtvsrd vsr%d,r%u\n", XT, rA_addr);
9673      /*  XS = SX || S
9674       *  For SX=0, mfvsrd is treated as a Floating-Point
9675       *            instruction in terms of resource availability.
9676       *  For SX=1, mfvsrd is treated as a Vector instruction in
9677       *            terms of resource availability.
9678       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9679       */
9680      assign( rA, getIReg(rA_addr) );
9681
9682      if (mode64)
9683         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
9684      else
9685         putVSReg( XT, binop( Iop_64HLtoV128,
9686                              binop( Iop_32HLto64,
9687                                     mkU32( 0 ),
9688                                     mkexpr( rA ) ),
9689                                     mkU64( 0 ) ) );
9690      break;
9691   }
9692
9693   case 0xD3:                // mtvsrwa
9694   {
9695      UChar XT = ifieldRegXT( theInstr );
9696      UChar rA_addr = ifieldRegA(theInstr);
9697      IRTemp rA = newTemp( Ity_I32 );
9698      DIP("mtvsrwa vsr%d,r%u\n", XT, rA_addr);
9699      /*  XS = SX || S
9700       *  For SX=0, mtvsrwa is treated as a Floating-Point
9701       *            instruction in terms of resource availability.
9702       *  For SX=1, mtvsrwa is treated as a Vector instruction in
9703       *            terms of resource availability.
9704       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9705       */
9706      if (mode64)
9707         assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
9708      else
9709         assign( rA, getIReg(rA_addr) );
9710
9711      putVSReg( XT, binop( Iop_64HLtoV128,
9712                           unop( Iop_32Sto64, mkexpr( rA ) ),
9713                           mkU64( 0 ) ) );
9714      break;
9715   }
9716
9717   case 0xF3:                // mtvsrwz
9718      {
9719         UChar XT = ifieldRegXT( theInstr );
9720         UChar rA_addr = ifieldRegA(theInstr);
9721         IRTemp rA = newTemp( Ity_I32 );
9722         DIP("mtvsrwz vsr%d,r%u\n", rA_addr, XT);
9723         /*  XS = SX || S
9724          *  For SX=0, mtvsrwz is treated as a Floating-Point
9725          *            instruction in terms of resource availability.
9726          *  For SX=1, mtvsrwz is treated as a Vector instruction in
9727          *            terms of resource availability.
9728          * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9729          */
9730         if (mode64)
9731             assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
9732         else
9733             assign( rA, getIReg(rA_addr) );
9734
9735         putVSReg( XT, binop( Iop_64HLtoV128,
9736                              binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
9737                              mkU64( 0 ) ) );
9738         break;
9739      }
9740
9741   default:
9742      vex_printf("dis_proc_ctl(ppc)(opc2)\n");
9743      return False;
9744   }
9745   return True;
9746}
9747
9748
9749/*
9750  Cache Management Instructions
9751*/
9752static Bool dis_cache_manage ( UInt         theInstr,
9753                               DisResult*   dres,
9754                               const VexArchInfo* guest_archinfo )
9755{
9756   /* X-Form */
9757   UChar opc1    = ifieldOPC(theInstr);
9758   UChar b21to25 = ifieldRegDS(theInstr);
9759   UChar rA_addr = ifieldRegA(theInstr);
9760   UChar rB_addr = ifieldRegB(theInstr);
9761   UInt  opc2    = ifieldOPClo10(theInstr);
9762   UChar b0      = ifieldBIT0(theInstr);
9763   UInt  lineszB = guest_archinfo->ppc_icache_line_szB;
9764   Bool  is_dcbzl = False;
9765
9766   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
9767
9768   // Check for valid hint values for dcbt and dcbtst as currently described in
9769   // ISA 2.07.  If valid, then we simply set b21to25 to zero since we have no
9770   // means of modeling the hint anyway.
9771   if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) {
9772      if (b21to25 == 0x10 || b21to25 < 0x10)
9773         b21to25 = 0;
9774   }
9775   if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
9776      b21to25 = 0;
9777
9778   if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
9779      if (b21to25 == 1) {
9780         is_dcbzl = True;
9781         b21to25 = 0;
9782         if (!(guest_archinfo->ppc_dcbzl_szB)) {
9783            vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
9784            return False;
9785         }
9786      }
9787   }
9788
9789   if (opc1 != 0x1F || b0 != 0) {
9790      if (0) vex_printf("dis_cache_manage %d %d\n",
9791                        opc1, b0);
9792      vex_printf("dis_cache_manage(ppc)(opc1|b0)\n");
9793      return False;
9794   }
9795
9796   /* stay sane .. */
9797   vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
9798
9799   switch (opc2) {
9800//zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
9801//zz       vassert(0); /* AWAITING TEST CASE */
9802//zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
9803//zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
9804//zz       break;
9805
9806   case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
9807      DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
9808      /* nop as far as vex is concerned */
9809      break;
9810
9811   case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
9812      DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
9813      /* nop as far as vex is concerned */
9814      break;
9815
9816   case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
9817      DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
9818      /* nop as far as vex is concerned */
9819      break;
9820
9821   case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
9822      DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
9823      /* nop as far as vex is concerned */
9824      break;
9825
9826   case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
9827                 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
9828      /* Clear all bytes in cache block at (rA|0) + rB. */
9829      IRTemp  EA   = newTemp(ty);
9830      IRTemp  addr = newTemp(ty);
9831      IRExpr* irx_addr;
9832      UInt    i;
9833      UInt clearszB;
9834      if (is_dcbzl) {
9835          clearszB = guest_archinfo->ppc_dcbzl_szB;
9836          DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
9837      }
9838      else {
9839          clearszB = guest_archinfo->ppc_dcbz_szB;
9840          DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
9841      }
9842
9843      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
9844
9845      if (mode64) {
9846         /* Round EA down to the start of the containing block. */
9847         assign( addr, binop( Iop_And64,
9848                              mkexpr(EA),
9849                              mkU64( ~((ULong)clearszB-1) )) );
9850
9851         for (i = 0; i < clearszB / 8; i++) {
9852            irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
9853            store( irx_addr, mkU64(0) );
9854         }
9855      } else {
9856         /* Round EA down to the start of the containing block. */
9857         assign( addr, binop( Iop_And32,
9858                              mkexpr(EA),
9859                              mkU32( ~(clearszB-1) )) );
9860
9861         for (i = 0; i < clearszB / 4; i++) {
9862            irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
9863            store( irx_addr, mkU32(0) );
9864         }
9865      }
9866      break;
9867   }
9868
9869   case 0x3D6: {
9870      // icbi (Instruction Cache Block Invalidate, PPC32 p431)
9871      /* Invalidate all translations containing code from the cache
9872         block at (rA|0) + rB. */
9873      IRTemp EA   = newTemp(ty);
9874      IRTemp addr = newTemp(ty);
9875      DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
9876      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
9877
9878      /* Round EA down to the start of the containing block. */
9879      assign( addr, binop( mkSzOp(ty, Iop_And8),
9880                           mkexpr(EA),
9881                           mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
9882      putGST( PPC_GST_CMSTART, mkexpr(addr) );
9883      putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) );
9884
9885      /* be paranoid ... */
9886      stmt( IRStmt_MBE(Imbe_Fence) );
9887
9888      putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
9889      dres->jk_StopHere = Ijk_InvalICache;
9890      dres->whatNext    = Dis_StopHere;
9891      break;
9892   }
9893
9894   default:
9895      vex_printf("dis_cache_manage(ppc)(opc2)\n");
9896      return False;
9897   }
9898   return True;
9899}
9900
9901
9902/*------------------------------------------------------------*/
9903/*--- Floating Point Helpers                               ---*/
9904/*------------------------------------------------------------*/
9905
9906/* --------- Synthesise a 2-bit FPU rounding mode. --------- */
9907/* Produces a value in 0 .. 3, which is encoded as per the type
9908   IRRoundingMode.  PPCRoundingMode encoding is different to
9909   IRRoundingMode, so need to map it.
9910*/
9911
9912static IRExpr* /* :: Ity_I32 */ set_round_to_Oddmode ( void )
9913{
9914/* PPC/ valgrind have two-bits to designate the rounding mode.
9915   ISA 3.0 adds instructions than can use a round to odd mode
9916   but did not change the number of bits for the rm.  Basically,
9917   they added two instructions that only differ by the rounding
9918   mode the operation uses.  In essesce, they encoded the rm
9919   in the name.  In order to avoid having to create Iops, that
9920   encode the rm in th name, we will "expand" the definition of
9921   the rounding mode bits.  We will just pass the rm and then
9922   map the to odd mode to the appropriate PPCFpOp name that
9923   will tell us which instruction to map to.
9924
9925   rounding mode | PPC | IR
9926   ------------------------
9927   to nearest    | 000  | 00
9928   to zero       | 001  | 11
9929   to +infinity  | 010  | 10
9930   to -infinity  | 011  | 01
9931   to odd        | 1xx  | xx
9932*/
9933   return mkU32(8);
9934}
9935
9936static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
9937{
9938/*
9939   rounding mode | PPC | IR
9940   ------------------------
9941   to nearest    | 00  | 00
9942   to zero       | 01  | 11
9943   to +infinity  | 10  | 10
9944   to -infinity  | 11  | 01
9945*/
9946   IRTemp rm_PPC32 = newTemp(Ity_I32);
9947   assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
9948
9949   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
9950   return binop( Iop_Xor32,
9951                 mkexpr(rm_PPC32),
9952                 binop( Iop_And32,
9953                        binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
9954                        mkU32(2) ));
9955}
9956
9957/* The DFP IR rounding modes were chosen such that the existing PPC to IR
9958 * mapping would still work with the extended three bit DFP rounding
9959 * mode designator.
9960
9961 *  rounding mode                     | PPC  |  IR
9962 *  -----------------------------------------------
9963 *  to nearest, ties to even          | 000  | 000
9964 *  to zero                           | 001  | 011
9965 *  to +infinity                      | 010  | 010
9966 *  to -infinity                      | 011  | 001
9967 *  to nearest, ties away from 0      | 100  | 100
9968 *  to nearest, ties toward 0         | 101  | 111
9969 *  to away from 0                    | 110  | 110
9970 *  to prepare for shorter precision  | 111  | 101
9971 */
9972static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
9973{
9974   IRTemp rm_PPC32 = newTemp( Ity_I32 );
9975   assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
9976
9977   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
9978   return binop( Iop_Xor32,
9979                 mkexpr( rm_PPC32 ),
9980                 binop( Iop_And32,
9981                        binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
9982                        mkU32( 2 ) ) );
9983}
9984
9985#define NANmaskSingle   0x7F800000
9986#define NANmaskDouble   0x7FF00000
9987
9988static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
9989{
9990   IRTemp exp_zero  = newTemp(Ity_I8);
9991   IRTemp frac_mask = newTemp(Ity_I32);
9992   IRTemp frac_not_zero = newTemp(Ity_I8);
9993
9994   /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
9995    * The input value is always 64-bits, for single precision values, the
9996    * lower 32 bits must be zero.
9997    *
9998    * Single Pricision
9999    *  [62:54] exponent field is equal to 0xFF for NAN and Infinity.
10000    *  [53:32] fraction field is zero for Infinity and non-zero for NAN
10001    *  [31:0]  unused for single precision representation
10002    *
10003    * Double Pricision
10004    *  [62:51] exponent field is equal to 0xFF for NAN and Infinity.
10005    *  [50:0]  fraction field is zero for Infinity and non-zero for NAN
10006    *
10007    * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
10008    */
10009   assign( frac_mask, unop( Iop_Not32,
10010                            binop( Iop_Or32,
10011                                   mkU32( 0x80000000ULL ), Hi32Mask) ) );
10012
10013   assign( exp_zero,
10014           unop( Iop_1Sto8,
10015                 binop( Iop_CmpEQ32,
10016                        binop( Iop_And32,
10017                               unop( Iop_64HIto32,
10018                                     unop( Iop_ReinterpF64asI64,
10019                                           value ) ),
10020                               Hi32Mask ),
10021                        Hi32Mask ) ) );
10022   assign( frac_not_zero,
10023           binop( Iop_Or8,
10024                  unop( Iop_1Sto8,
10025                        binop( Iop_CmpNE32,
10026                               binop( Iop_And32,
10027                                      unop( Iop_64HIto32,
10028                                            unop( Iop_ReinterpF64asI64,
10029                                                  value ) ),
10030                                      mkexpr( frac_mask ) ),
10031                               mkU32( 0x0 ) ) ),
10032                  unop( Iop_1Sto8,
10033                        binop( Iop_CmpNE32,
10034                               binop( Iop_And32,
10035                                      unop( Iop_64to32,
10036                                            unop( Iop_ReinterpF64asI64,
10037                                                  value ) ),
10038                                      mkU32( 0xFFFFFFFF ) ),
10039                               mkU32( 0x0 ) ) ) ) );
10040   return unop( Iop_8Sto32,
10041                binop( Iop_And8,
10042                       mkexpr( exp_zero ),
10043                       mkexpr( frac_not_zero ) ) );
10044}
10045
10046static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
10047{
10048   /* This function will only complement the 64-bit floating point value if it
10049    * is not Nan.  NaN is not a signed value.  Need to do computations using
10050    * 32-bit operands to ensure it will run in 32-bit mode.
10051    */
10052   return  binop( Iop_32HLto64,
10053                  binop( Iop_Or32,
10054                         binop( Iop_And32,
10055                                nan_mask,
10056                                unop( Iop_64HIto32,
10057                                      unop( Iop_ReinterpF64asI64,
10058                                            value ) ) ),
10059                         binop( Iop_And32,
10060                                unop( Iop_Not32,
10061                                      nan_mask ),
10062                                unop( Iop_64HIto32,
10063                                      unop( Iop_ReinterpF64asI64,
10064                                            unop( Iop_NegF64,
10065                                                  value ) ) ) ) ),
10066                  unop( Iop_64to32,
10067                        unop( Iop_ReinterpF64asI64, value ) ) );
10068}
10069
10070/*------------------------------------------------------------*/
10071/*--- Floating Point Instruction Translation               ---*/
10072/*------------------------------------------------------------*/
10073
10074/*
10075  Floating Point Load Instructions
10076*/
10077static Bool dis_fp_load ( UInt theInstr )
10078{
10079   /* X-Form, D-Form */
10080   UChar opc1      = ifieldOPC(theInstr);
10081   UChar frD_addr  = ifieldRegDS(theInstr);
10082   UChar rA_addr   = ifieldRegA(theInstr);
10083   UChar rB_addr   = ifieldRegB(theInstr);
10084   UInt  opc2      = ifieldOPClo10(theInstr);
10085   UChar b0        = ifieldBIT0(theInstr);
10086   UInt  uimm16    = ifieldUIMM16(theInstr);
10087
10088   Int    simm16 = extend_s_16to32(uimm16);
10089   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
10090   IRTemp EA     = newTemp(ty);
10091   IRTemp rA     = newTemp(ty);
10092   IRTemp rB     = newTemp(ty);
10093   IRTemp iHi    = newTemp(Ity_I32);
10094   IRTemp iLo    = newTemp(Ity_I32);
10095
10096   assign( rA, getIReg(rA_addr) );
10097   assign( rB, getIReg(rB_addr) );
10098
10099   /* These are completely straightforward from a rounding and status
10100      bits perspective: no rounding involved and no funny status or CR
10101      bits affected. */
10102
10103   switch (opc1) {
10104   case 0x30: // lfs (Load Float Single, PPC32 p441)
10105      DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
10106      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
10107      putFReg( frD_addr,
10108               unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
10109      break;
10110
10111   case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
10112      if (rA_addr == 0)
10113         return False;
10114      DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
10115      assign( EA, ea_rA_simm(rA_addr, simm16) );
10116      putFReg( frD_addr,
10117               unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
10118      putIReg( rA_addr, mkexpr(EA) );
10119      break;
10120
10121   case 0x32: // lfd (Load Float Double, PPC32 p437)
10122      DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
10123      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
10124      putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
10125      break;
10126
10127   case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
10128      if (rA_addr == 0)
10129         return False;
10130      DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
10131      assign( EA, ea_rA_simm(rA_addr, simm16) );
10132      putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
10133      putIReg( rA_addr, mkexpr(EA) );
10134      break;
10135
10136   case 0x1F:
10137      if (b0 != 0) {
10138         vex_printf("dis_fp_load(ppc)(instr,b0)\n");
10139         return False;
10140      }
10141
10142      switch(opc2) {
10143      case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
10144         DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10145         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
10146         putFReg( frD_addr, unop( Iop_F32toF64,
10147                                  load(Ity_F32, mkexpr(EA))) );
10148         break;
10149
10150      case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
10151         if (rA_addr == 0)
10152            return False;
10153         DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10154         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
10155         putFReg( frD_addr,
10156                  unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
10157         putIReg( rA_addr, mkexpr(EA) );
10158         break;
10159
10160      case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
10161         DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10162         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
10163         putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
10164         break;
10165
10166      case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
10167         if (rA_addr == 0)
10168            return False;
10169         DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10170         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
10171         putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
10172         putIReg( rA_addr, mkexpr(EA) );
10173         break;
10174
10175      case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
10176         DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10177         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
10178         assign( iLo, load(Ity_I32, mkexpr(EA)) );
10179         assign( iHi, binop(Iop_Sub32,
10180                            mkU32(0),
10181                            binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
10182         putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
10183                                 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
10184         break;
10185
10186      case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
10187      {
10188         IRTemp dw = newTemp( Ity_I64 );
10189         DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10190         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
10191         assign( iLo, load(Ity_I32, mkexpr(EA)) );
10192         assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
10193         putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
10194         break;
10195      }
10196
10197      default:
10198         vex_printf("dis_fp_load(ppc)(opc2)\n");
10199         return False;
10200      }
10201      break;
10202
10203   default:
10204      vex_printf("dis_fp_load(ppc)(opc1)\n");
10205      return False;
10206   }
10207   return True;
10208}
10209
10210
10211
10212/*
10213  Floating Point Store Instructions
10214*/
10215static Bool dis_fp_store ( UInt theInstr )
10216{
10217   /* X-Form, D-Form */
10218   UChar opc1      = ifieldOPC(theInstr);
10219   UChar frS_addr  = ifieldRegDS(theInstr);
10220   UChar rA_addr   = ifieldRegA(theInstr);
10221   UChar rB_addr   = ifieldRegB(theInstr);
10222   UInt  opc2      = ifieldOPClo10(theInstr);
10223   UChar b0        = ifieldBIT0(theInstr);
10224   Int   uimm16    = ifieldUIMM16(theInstr);
10225
10226   Int    simm16 = extend_s_16to32(uimm16);
10227   IRTemp frS    = newTemp(Ity_F64);
10228   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
10229   IRTemp EA     = newTemp(ty);
10230   IRTemp rA     = newTemp(ty);
10231   IRTemp rB     = newTemp(ty);
10232
10233   assign( frS, getFReg(frS_addr) );
10234   assign( rA,  getIReg(rA_addr) );
10235   assign( rB,  getIReg(rB_addr) );
10236
10237   /* These are straightforward from a status bits perspective: no
10238      funny status or CR bits affected.  For single precision stores,
10239      the values are truncated and denormalised (not rounded) to turn
10240      them into single precision values. */
10241
10242   switch (opc1) {
10243
10244   case 0x34: // stfs (Store Float Single, PPC32 p518)
10245      DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
10246      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
10247      /* Use Iop_TruncF64asF32 to truncate and possible denormalise
10248         the value to be stored in the correct way, without any
10249         rounding. */
10250      store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
10251      break;
10252
10253   case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
10254      if (rA_addr == 0)
10255         return False;
10256      DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
10257      assign( EA, ea_rA_simm(rA_addr, simm16) );
10258      /* See comment for stfs */
10259      store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
10260      putIReg( rA_addr, mkexpr(EA) );
10261      break;
10262
10263   case 0x36: // stfd (Store Float Double, PPC32 p513)
10264      DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
10265      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
10266      store( mkexpr(EA), mkexpr(frS) );
10267      break;
10268
10269   case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
10270      if (rA_addr == 0)
10271         return False;
10272      DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
10273      assign( EA, ea_rA_simm(rA_addr, simm16) );
10274      store( mkexpr(EA), mkexpr(frS) );
10275      putIReg( rA_addr, mkexpr(EA) );
10276      break;
10277
10278   case 0x1F:
10279      if (b0 != 0) {
10280         vex_printf("dis_fp_store(ppc)(instr,b0)\n");
10281         return False;
10282      }
10283      switch(opc2) {
10284      case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
10285         DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
10286         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
10287         /* See note for stfs */
10288         store( mkexpr(EA),
10289                unop(Iop_TruncF64asF32, mkexpr(frS)) );
10290         break;
10291
10292      case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
10293         if (rA_addr == 0)
10294            return False;
10295         DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
10296         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
10297         /* See note for stfs */
10298         store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
10299         putIReg( rA_addr, mkexpr(EA) );
10300         break;
10301
10302      case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
10303         DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
10304         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
10305         store( mkexpr(EA), mkexpr(frS) );
10306         break;
10307
10308      case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
10309         if (rA_addr == 0)
10310            return False;
10311         DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
10312         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
10313         store( mkexpr(EA), mkexpr(frS) );
10314         putIReg( rA_addr, mkexpr(EA) );
10315         break;
10316
10317      case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
10318         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10319         DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
10320         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
10321         store( mkexpr(EA),
10322                unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
10323         break;
10324
10325      default:
10326         vex_printf("dis_fp_store(ppc)(opc2)\n");
10327         return False;
10328      }
10329      break;
10330
10331   default:
10332      vex_printf("dis_fp_store(ppc)(opc1)\n");
10333      return False;
10334   }
10335   return True;
10336}
10337
10338
10339
10340/*
10341  Floating Point Arith Instructions
10342*/
10343static Bool dis_fp_arith ( UInt theInstr )
10344{
10345   /* A-Form */
10346   UChar opc1     = ifieldOPC(theInstr);
10347   UChar frD_addr = ifieldRegDS(theInstr);
10348   UChar frA_addr = ifieldRegA(theInstr);
10349   UChar frB_addr = ifieldRegB(theInstr);
10350   UChar frC_addr = ifieldRegC(theInstr);
10351   UChar opc2     = ifieldOPClo5(theInstr);
10352   UChar flag_rC  = ifieldBIT0(theInstr);
10353
10354   IRTemp  frD = newTemp(Ity_F64);
10355   IRTemp  frA = newTemp(Ity_F64);
10356   IRTemp  frB = newTemp(Ity_F64);
10357   IRTemp  frC = newTemp(Ity_F64);
10358   IRExpr* rm  = get_IR_roundingmode();
10359
10360   /* By default, we will examine the results of the operation and set
10361      fpscr[FPRF] accordingly. */
10362   Bool set_FPRF = True;
10363
10364   /* By default, if flag_RC is set, we will clear cr1 after the
10365      operation.  In reality we should set cr1 to indicate the
10366      exception status of the operation, but since we're not
10367      simulating exceptions, the exception status will appear to be
10368      zero.  Hence cr1 should be cleared if this is a . form insn. */
10369   Bool clear_CR1 = True;
10370
10371   assign( frA, getFReg(frA_addr));
10372   assign( frB, getFReg(frB_addr));
10373   assign( frC, getFReg(frC_addr));
10374
10375   switch (opc1) {
10376   case 0x3B:
10377      switch (opc2) {
10378      case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
10379         if (frC_addr != 0)
10380            return False;
10381         DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10382             frD_addr, frA_addr, frB_addr);
10383         assign( frD, triop( Iop_DivF64r32,
10384                             rm, mkexpr(frA), mkexpr(frB) ));
10385         break;
10386
10387      case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
10388         if (frC_addr != 0)
10389            return False;
10390         DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10391             frD_addr, frA_addr, frB_addr);
10392         assign( frD, triop( Iop_SubF64r32,
10393                             rm, mkexpr(frA), mkexpr(frB) ));
10394         break;
10395
10396      case 0x15: // fadds (Floating Add Single, PPC32 p401)
10397         if (frC_addr != 0)
10398            return False;
10399         DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10400             frD_addr, frA_addr, frB_addr);
10401         assign( frD, triop( Iop_AddF64r32,
10402                             rm, mkexpr(frA), mkexpr(frB) ));
10403         break;
10404
10405      case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
10406         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
10407         if (frA_addr != 0 || frC_addr != 0)
10408            return False;
10409         DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
10410             frD_addr, frB_addr);
10411         // however illogically, on ppc970 this insn behaves identically
10412         // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
10413         assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
10414         break;
10415
10416      case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
10417         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10418         if (frA_addr != 0 || frC_addr != 0)
10419            return False;
10420         DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
10421             frD_addr, frB_addr);
10422         { IRExpr* ieee_one
10423              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
10424           assign( frD, triop( Iop_DivF64r32,
10425                               rm,
10426                               ieee_one, mkexpr(frB) ));
10427         }
10428         break;
10429
10430      case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
10431         if (frB_addr != 0)
10432            return False;
10433         DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10434             frD_addr, frA_addr, frC_addr);
10435         assign( frD, triop( Iop_MulF64r32,
10436                             rm, mkexpr(frA), mkexpr(frC) ));
10437         break;
10438
10439      case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
10440         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10441         // Undocumented instruction?
10442         if (frA_addr != 0 || frC_addr != 0)
10443            return False;
10444         DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
10445             frD_addr, frB_addr);
10446         assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
10447         break;
10448
10449      default:
10450         vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
10451         return False;
10452      }
10453      break;
10454
10455   case 0x3F:
10456      switch (opc2) {
10457      case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
10458         if (frC_addr != 0)
10459            return False;
10460         DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10461             frD_addr, frA_addr, frB_addr);
10462         assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
10463         break;
10464
10465      case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
10466         if (frC_addr != 0)
10467            return False;
10468         DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10469             frD_addr, frA_addr, frB_addr);
10470         assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
10471         break;
10472
10473      case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
10474         if (frC_addr != 0)
10475            return False;
10476         DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10477             frD_addr, frA_addr, frB_addr);
10478         assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
10479         break;
10480
10481      case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
10482         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
10483         if (frA_addr != 0 || frC_addr != 0)
10484            return False;
10485         DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
10486             frD_addr, frB_addr);
10487         assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
10488         break;
10489
10490      case 0x17: { // fsel (Floating Select, PPC32 p426)
10491         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10492         IRTemp cc    = newTemp(Ity_I32);
10493         IRTemp cc_b0 = newTemp(Ity_I32);
10494
10495         DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10496             frD_addr, frA_addr, frC_addr, frB_addr);
10497
10498         // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
10499         // => GT|EQ == (cc & 0x1 == 0)
10500         assign( cc, binop(Iop_CmpF64, mkexpr(frA),
10501                                       IRExpr_Const(IRConst_F64(0))) );
10502         assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
10503
10504         // frD = (frA >= 0.0) ? frC : frB
10505         //     = (cc_b0 == 0) ? frC : frB
10506         assign( frD,
10507                 IRExpr_ITE(
10508                    binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
10509                    mkexpr(frC),
10510                    mkexpr(frB) ));
10511
10512         /* One of the rare ones which don't mess with FPRF */
10513         set_FPRF = False;
10514         break;
10515      }
10516
10517      case 0x18: // fre (Floating Reciprocal Estimate)
10518         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10519         // Note: unclear whether this insn really exists or not
10520         // ppc970 doesn't have it, but POWER5 does
10521         if (frA_addr != 0 || frC_addr != 0)
10522            return False;
10523         DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
10524             frD_addr, frB_addr);
10525         { IRExpr* ieee_one
10526              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
10527           assign( frD, triop( Iop_DivF64,
10528                               rm,
10529                               ieee_one, mkexpr(frB) ));
10530         }
10531         break;
10532
10533      case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
10534         if (frB_addr != 0)
10535            vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
10536         DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10537             frD_addr, frA_addr, frC_addr);
10538         assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
10539         break;
10540
10541      case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
10542         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10543         if (frA_addr != 0 || frC_addr != 0)
10544            return False;
10545         DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
10546             frD_addr, frB_addr);
10547         assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
10548         break;
10549
10550      default:
10551         vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
10552         return False;
10553      }
10554      break;
10555
10556   default:
10557      vex_printf("dis_fp_arith(ppc)(opc1)\n");
10558      return False;
10559   }
10560
10561   putFReg( frD_addr, mkexpr(frD) );
10562
10563   if (set_FPRF) {
10564      // XXX XXX XXX FIXME
10565      // set FPRF from frD
10566   }
10567
10568   if (flag_rC && clear_CR1) {
10569      putCR321( 1, mkU8(0) );
10570      putCR0( 1, mkU8(0) );
10571   }
10572
10573   return True;
10574}
10575
10576
10577
10578/*
10579  Floating Point Mult-Add Instructions
10580*/
10581static Bool dis_fp_multadd ( UInt theInstr )
10582{
10583   /* A-Form */
10584   UChar opc1     = ifieldOPC(theInstr);
10585   UChar frD_addr = ifieldRegDS(theInstr);
10586   UChar frA_addr = ifieldRegA(theInstr);
10587   UChar frB_addr = ifieldRegB(theInstr);
10588   UChar frC_addr = ifieldRegC(theInstr);
10589   UChar opc2     = ifieldOPClo5(theInstr);
10590   UChar flag_rC  = ifieldBIT0(theInstr);
10591
10592   IRTemp  frD = newTemp(Ity_F64);
10593   IRTemp  frA = newTemp(Ity_F64);
10594   IRTemp  frB = newTemp(Ity_F64);
10595   IRTemp  frC = newTemp(Ity_F64);
10596   IRTemp  rmt = newTemp(Ity_I32);
10597   IRTemp  tmp = newTemp(Ity_F64);
10598   IRTemp  sign_tmp = newTemp(Ity_I64);
10599   IRTemp  nan_mask = newTemp(Ity_I32);
10600   IRExpr* rm;
10601
10602   /* By default, we will examine the results of the operation and set
10603      fpscr[FPRF] accordingly. */
10604   Bool set_FPRF = True;
10605
10606   /* By default, if flag_RC is set, we will clear cr1 after the
10607      operation.  In reality we should set cr1 to indicate the
10608      exception status of the operation, but since we're not
10609      simulating exceptions, the exception status will appear to be
10610      zero.  Hence cr1 should be cleared if this is a . form insn. */
10611   Bool clear_CR1 = True;
10612
10613   /* Bind the rounding mode expression to a temp; there's no
10614      point in creating gratuitous CSEs, as we know we'll need
10615      to use it twice. */
10616   assign( rmt, get_IR_roundingmode() );
10617   rm = mkexpr(rmt);
10618
10619   assign( frA, getFReg(frA_addr));
10620   assign( frB, getFReg(frB_addr));
10621   assign( frC, getFReg(frC_addr));
10622
10623   /* The rounding in this is all a bit dodgy.  The idea is to only do
10624      one rounding.  That clearly isn't achieveable without dedicated
10625      four-input IR primops, although in the single precision case we
10626      can sort-of simulate it by doing the inner multiply in double
10627      precision.
10628
10629      In the negated cases, the negation happens after rounding. */
10630
10631   switch (opc1) {
10632   case 0x3B:
10633      switch (opc2) {
10634      case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
10635         DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10636             frD_addr, frA_addr, frC_addr, frB_addr);
10637         assign( frD, qop( Iop_MSubF64r32, rm,
10638                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
10639         break;
10640
10641      case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
10642         DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10643             frD_addr, frA_addr, frC_addr, frB_addr);
10644         assign( frD, qop( Iop_MAddF64r32, rm,
10645                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
10646         break;
10647
10648      case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
10649      case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
10650
10651         if (opc2 == 0x1E) {
10652            DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10653                     frD_addr, frA_addr, frC_addr, frB_addr);
10654            assign( tmp, qop( Iop_MSubF64r32, rm,
10655                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
10656         } else {
10657            DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10658                     frD_addr, frA_addr, frC_addr, frB_addr);
10659            assign( tmp, qop( Iop_MAddF64r32, rm,
10660                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
10661         }
10662
10663         assign( nan_mask, Check_NaN( mkexpr( tmp ),
10664                                      mkU32( NANmaskSingle ) ) );
10665         assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
10666                                               mkexpr( nan_mask ) ) );
10667         assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
10668         break;
10669
10670      default:
10671         vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
10672         return False;
10673      }
10674      break;
10675
10676   case 0x3F:
10677      switch (opc2) {
10678      case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
10679         DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10680             frD_addr, frA_addr, frC_addr, frB_addr);
10681         assign( frD, qop( Iop_MSubF64, rm,
10682                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
10683         break;
10684
10685      case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
10686         DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10687             frD_addr, frA_addr, frC_addr, frB_addr);
10688         assign( frD, qop( Iop_MAddF64, rm,
10689                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
10690         break;
10691
10692      case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
10693      case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
10694
10695         if (opc2 == 0x1E) {
10696            DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10697                     frD_addr, frA_addr, frC_addr, frB_addr);
10698            assign( tmp, qop( Iop_MSubF64, rm,
10699                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
10700         } else {
10701            DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10702                     frD_addr, frA_addr, frC_addr, frB_addr);
10703            assign( tmp, qop( Iop_MAddF64, rm,
10704                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
10705         }
10706
10707         assign( nan_mask, Check_NaN( mkexpr( tmp ),
10708                                      mkU32( NANmaskDouble ) ) );
10709         assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
10710                                               mkexpr( nan_mask ) ) );
10711         assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
10712         break;
10713
10714      default:
10715         vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
10716         return False;
10717      }
10718      break;
10719
10720   default:
10721      vex_printf("dis_fp_multadd(ppc)(opc1)\n");
10722      return False;
10723   }
10724
10725   putFReg( frD_addr, mkexpr(frD) );
10726
10727   if (set_FPRF) {
10728      // XXX XXX XXX FIXME
10729      // set FPRF from frD
10730   }
10731
10732   if (flag_rC && clear_CR1) {
10733      putCR321( 1, mkU8(0) );
10734      putCR0( 1, mkU8(0) );
10735   }
10736
10737   return True;
10738}
10739
10740/*
10741 * fe_flag is set to 1 if any of the following conditions occurs:
10742 *  - The floating-point operand in register FRB is a Zero, a
10743 *    NaN, an Infinity, or a negative value.
10744 *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
10745 *  Otherwise fe_flag is set to 0.
10746 *
10747 * fg_flag is set to 1 if either of the following conditions occurs.
10748 *   - The floating-point operand in register FRB is a Zero, an
10749 *     Infinity, or a denormalized value.
10750 *  Otherwise fg_flag is set to 0.
10751 *
10752 */
10753
10754static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
10755{
10756   // The following temps are for holding intermediate results
10757   IRTemp e_b = newTemp(Ity_I32);
10758   IRExpr * fe_flag,  * fg_flag;
10759   IRTemp frB_exp_shR = newTemp(Ity_I32);
10760   UInt bias = sp? 127 : 1023;
10761   IRExpr * frbNaN, * frbDenorm, * frBNeg;
10762   IRExpr * eb_LTE;
10763   IRTemp  frbZero_tmp = newTemp(Ity_I1);
10764   IRTemp  frbInf_tmp = newTemp(Ity_I1);
10765   *fe_flag_tmp = newTemp(Ity_I32);
10766   *fg_flag_tmp = newTemp(Ity_I32);
10767
10768   if ( sp )
10769      assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_Int ) );
10770   else
10771      assign( frB_exp_shR, fp_exp_part( Ity_I64, frB_Int ) );
10772
10773   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
10774
10775   //////////////////  fe_flag tests BEGIN //////////////////////
10776   /* We first do all tests that may result in setting fe_flag to '1'.
10777    * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
10778    * for details.)
10779    */
10780   if ( sp ) {
10781      frbNaN = is_NaN( Ity_I32, frB_Int );
10782      assign( frbInf_tmp, is_Inf( Ity_I32, frB_Int ) );
10783      assign( frbZero_tmp, is_Zero( Ity_I32, frB_Int ) );
10784
10785   } else {
10786      frbNaN = is_NaN( Ity_I64, frB_Int );
10787      assign( frbInf_tmp, is_Inf( Ity_I64, frB_Int ) );
10788      assign( frbZero_tmp, is_Zero( Ity_I64, frB_Int ) );
10789   }
10790
10791   {
10792      // Test_value = -970 for double precision
10793      UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
10794      eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
10795   }
10796   frBNeg = binop( Iop_CmpEQ32,
10797                   binop( Iop_Shr32,
10798                          sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
10799                          mkU8( 31 ) ),
10800                   mkU32( 1 ) );
10801   //////////////////  fe_flag tests END //////////////////////
10802
10803   //////////////////  fg_flag tests BEGIN //////////////////////
10804   /*
10805    * The following tests were already performed above in the fe_flag
10806    * tests.  So these conditions will result in both fe_ and fg_ flags
10807    * being set.
10808    *   - Test if FRB is Zero
10809    *   - Test if FRB is an Infinity
10810    */
10811
10812   /*
10813    * Test if FRB holds a denormalized value.  A denormalized value is one where
10814    * the exp is 0 and the fraction is non-zero.
10815    */
10816   if (sp) {
10817      IRTemp frac_part = newTemp(Ity_I32);
10818      assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
10819      frbDenorm
10820               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
10821                         binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
10822   } else {
10823      IRExpr * hi32, * low32, * fraction_is_nonzero;
10824      IRTemp frac_part = newTemp(Ity_I64);
10825
10826      assign( frac_part, FP_FRAC_PART(frB_Int) );
10827      hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
10828      low32 = unop( Iop_64to32, mkexpr( frac_part ) );
10829      fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
10830                                                mkU32( 0 ) );
10831      frbDenorm
10832               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
10833                         fraction_is_nonzero );
10834   }
10835   //////////////////  fg_flag tests END //////////////////////
10836
10837   /////////////////////////
10838   fe_flag = mkOR1( mkexpr( frbZero_tmp ),
10839                    mkOR1( frbNaN,
10840                           mkOR1( mkexpr( frbInf_tmp ),
10841                                  mkOR1( frBNeg, eb_LTE ) ) ) );
10842
10843   fe_flag = unop(Iop_1Uto32, fe_flag);
10844
10845   fg_flag = mkOR1( mkexpr( frbZero_tmp ),
10846                    mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
10847   fg_flag = unop(Iop_1Uto32, fg_flag);
10848   assign (*fg_flag_tmp, fg_flag);
10849   assign (*fe_flag_tmp, fe_flag);
10850}
10851/*
10852 * fe_flag is set to 1 if any of the following conditions occurs:
10853 *  - The double-precision floating-point operand in register FRA is a NaN or an
10854 *    Infinity.
10855 *  - The double-precision floating-point operand in register FRB is a Zero, a
10856 *    NaN, or an Infinity.
10857 *  - e_b is less than or equal to -1022.
10858 *  - e_b is greater than or equal to 1021.
10859 *  - The double-precision floating-point operand in register FRA is not a zero
10860 *    and the difference, e_a - e_b, is greater than or equal to 1023.
10861 *  - The double-precision floating-point operand in register FRA is not a zero
10862 *    and the difference, e_a - e_b, is less than or equal to -1021.
10863 *  - The double-precision floating-point operand in register FRA is not a zero
10864 *    and e_a is less than or equal to -970
10865 *  Otherwise fe_flag is set to 0.
10866 *
10867 * fg_flag is set to 1 if either of the following conditions occurs.
10868 *   - The double-precision floating-point operand in register FRA is an Infinity.
10869 *   - The double-precision floating-point operand in register FRB is a Zero, an
10870 *     Infinity, or a denormalized value.
10871 *  Otherwise fg_flag is set to 0.
10872 *
10873 */
10874static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
10875{
10876   // The following temps are for holding intermediate results
10877   IRTemp e_a = newTemp(Ity_I32);
10878   IRTemp e_b = newTemp(Ity_I32);
10879   IRTemp frA_exp_shR = newTemp(Ity_I32);
10880   IRTemp frB_exp_shR = newTemp(Ity_I32);
10881
10882   UInt bias = sp? 127 : 1023;
10883   *fe_flag_tmp = newTemp(Ity_I32);
10884   *fg_flag_tmp = newTemp(Ity_I32);
10885
10886   /* The following variables hold boolean results from tests
10887    * that are OR'ed together for setting the fe_ and fg_ flags.
10888    * For some cases, the booleans are used more than once, so
10889    * I make those IRTemp's instead of IRExpr's.
10890    */
10891   IRExpr * fraNaN, * frbNaN, * frbDenorm;
10892   IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
10893   IRTemp  fraInf_tmp = newTemp(Ity_I1);
10894   IRTemp  frbZero_tmp = newTemp(Ity_I1);
10895   IRTemp  frbInf_tmp = newTemp(Ity_I1);
10896   IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
10897
10898/* The following are the flags that are set by OR'ing the results of
10899 * all the tests done for tdiv.  These flags are the input to the specified CR.
10900 */
10901   IRExpr * fe_flag, * fg_flag;
10902
10903   // Create temps that will be used throughout the following tests.
10904   if ( sp ) {
10905      assign( frA_exp_shR, fp_exp_part( Ity_I32, frA_int ) );
10906      assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_int ) );
10907   } else{
10908      assign( frA_exp_shR, fp_exp_part( Ity_I64, frA_int ) );
10909      assign( frB_exp_shR, fp_exp_part( Ity_I64, frB_int ) );
10910   }
10911
10912   /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
10913   assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
10914   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
10915
10916
10917   //////////////////  fe_flag tests BEGIN //////////////////////
10918   /* We first do all tests that may result in setting fe_flag to '1'. */
10919
10920   /*
10921    * Test if the double-precision floating-point operand in register FRA is
10922    * a NaN:
10923    */
10924   fraNaN = sp ? is_NaN( Ity_I32, frA_int ) : is_NaN( Ity_I64, frA_int );
10925   /*
10926    * Test if the double-precision floating-point operands in register FRA
10927    * and FRB is an Infinity.  Test if FRB is zero.
10928    */
10929   if ( sp ) {
10930      assign(fraInf_tmp, is_Inf( Ity_I32, frA_int ) );
10931      assign( frbInf_tmp, is_Inf( Ity_I32, frB_int ) );
10932      assign( frbZero_tmp, is_Zero( Ity_I32, frB_int ) );
10933
10934   } else {
10935      assign(fraInf_tmp, is_Inf( Ity_I64, frA_int ) );
10936      assign( frbInf_tmp, is_Inf( Ity_I64, frB_int ) );
10937      assign( frbZero_tmp, is_Zero( Ity_I64, frB_int ) );
10938   }
10939   /*
10940    * Test if the double-precision floating-point operand in register FRB is
10941    * a NaN:
10942    */
10943   frbNaN = sp ? is_NaN( Ity_I32, frB_int ) : is_NaN( Ity_I64, frB_int );
10944
10945   /*
10946    * Test if e_b <= -1022 for double precision;
10947    * or e_b <= -126 for single precision
10948    */
10949   {
10950      UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
10951      eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
10952   }
10953
10954   /*
10955    * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
10956    * or e_b >= -125 (125 < e_b) for single precision
10957    */
10958   {
10959      Int test_value = sp ? 125 : 1021;
10960      eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
10961   }
10962
10963   /*
10964    * Test if FRA != Zero and (e_a - e_b) >= bias
10965    */
10966   if ( sp )
10967      assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( Ity_I32, frA_int ) ) );
10968   else
10969      assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( Ity_I64, frA_int ) ) );
10970
10971   ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
10972                       binop( Iop_CmpLT32S, mkU32( bias ),
10973                              binop( Iop_Sub32, mkexpr( e_a ),
10974                                     mkexpr( e_b ) ) ) );
10975
10976   /*
10977    * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
10978    */
10979   {
10980      UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
10981
10982      ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
10983                          binop( Iop_CmpLE32S,
10984                                 binop( Iop_Sub32,
10985                                        mkexpr( e_a ),
10986                                        mkexpr( e_b ) ),
10987                                        mkU32( test_value ) ) );
10988   }
10989
10990   /*
10991    * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
10992    */
10993   {
10994      UInt test_value = 0xfffffc36;  //Int test_value = -970;
10995
10996      ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
10997                                                        mkexpr( e_a ),
10998                                                        mkU32( test_value ) ) );
10999   }
11000   //////////////////  fe_flag tests END //////////////////////
11001
11002   //////////////////  fg_flag tests BEGIN //////////////////////
11003   /*
11004    * The following tests were already performed above in the fe_flag
11005    * tests.  So these conditions will result in both fe_ and fg_ flags
11006    * being set.
11007    *   - Test if FRA is an Infinity
11008    *   - Test if FRB ix Zero
11009    *   - Test if FRB is an Infinity
11010    */
11011
11012   /*
11013    * Test if FRB holds a denormalized value.  A denormalized value is one where
11014    * the exp is 0 and the fraction is non-zero.
11015    */
11016   {
11017      IRExpr * fraction_is_nonzero;
11018
11019      if (sp) {
11020         fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
11021                                      mkU32( 0 ) );
11022      } else {
11023         IRExpr * hi32, * low32;
11024         IRTemp frac_part = newTemp(Ity_I64);
11025         assign( frac_part, FP_FRAC_PART(frB_int) );
11026
11027         hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
11028         low32 = unop( Iop_64to32, mkexpr( frac_part ) );
11029         fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
11030                                      mkU32( 0 ) );
11031      }
11032      frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
11033                                 mkU32( 0x0 ) ), fraction_is_nonzero );
11034
11035   }
11036   //////////////////  fg_flag tests END //////////////////////
11037
11038   fe_flag
11039   = mkOR1(
11040            fraNaN,
11041            mkOR1(
11042                   mkexpr( fraInf_tmp ),
11043                   mkOR1(
11044                          mkexpr( frbZero_tmp ),
11045                          mkOR1(
11046                                 frbNaN,
11047                                 mkOR1(
11048                                        mkexpr( frbInf_tmp ),
11049                                        mkOR1( eb_LTE,
11050                                               mkOR1( eb_GTE,
11051                                                      mkOR1( ea_eb_GTE,
11052                                                             mkOR1( ea_eb_LTE,
11053                                                                    ea_LTE ) ) ) ) ) ) ) ) );
11054
11055   fe_flag = unop(Iop_1Uto32, fe_flag);
11056
11057   fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
11058                                                 mkOR1( mkexpr( frbInf_tmp ),
11059                                                        frbDenorm ) ) );
11060   fg_flag = unop(Iop_1Uto32, fg_flag);
11061   assign(*fe_flag_tmp, fe_flag);
11062   assign(*fg_flag_tmp, fg_flag);
11063}
11064
11065/* See description for _do_fp_tdiv() above. */
11066static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
11067{
11068   IRTemp  fe_flag, fg_flag;
11069   /////////////////////////
11070   /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
11071    * where fl_flag == 1 on ppc64.
11072    */
11073   IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
11074   fe_flag = fg_flag = IRTemp_INVALID;
11075   _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
11076   return binop( Iop_Or32,
11077                 binop( Iop_Or32,
11078                        binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
11079                        binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
11080                 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
11081}
11082
11083static Bool dis_fp_tests ( UInt theInstr )
11084{
11085   UChar opc1     = ifieldOPC(theInstr);
11086   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
11087   UChar frB_addr = ifieldRegB(theInstr);
11088   UChar b0       = ifieldBIT0(theInstr);
11089   UInt  opc2     = ifieldOPClo10(theInstr);
11090   IRTemp frB_I64     = newTemp(Ity_I64);
11091
11092   if (opc1 != 0x3F || b0 != 0 ){
11093      vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
11094      return False;
11095   }
11096   assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
11097
11098   switch (opc2) {
11099      case 0x080: // ftdiv
11100      {
11101         UChar frA_addr = ifieldRegA(theInstr);
11102         IRTemp frA_I64     = newTemp(Ity_I64);
11103         UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
11104         if (b21to22 != 0 ) {
11105            vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
11106            return False;
11107         }
11108
11109         assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
11110         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
11111
11112         DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
11113         break;
11114      }
11115      case 0x0A0: // ftsqrt
11116      {
11117         IRTemp flags = newTemp(Ity_I32);
11118         IRTemp  fe_flag, fg_flag;
11119         fe_flag = fg_flag = IRTemp_INVALID;
11120         UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
11121         if ( b18to22 != 0) {
11122            vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
11123            return False;
11124         }
11125         DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
11126         do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
11127         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
11128          * where fl_flag == 1 on ppc64.
11129          */
11130         assign( flags,
11131                 binop( Iop_Or32,
11132                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
11133                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
11134                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
11135         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
11136         break;
11137      }
11138
11139      default:
11140         vex_printf("dis_fp_tests(ppc)(opc2)\n");
11141         return False;
11142
11143   }
11144   return True;
11145}
11146
11147/*
11148  Floating Point Compare Instructions
11149*/
11150static Bool dis_fp_cmp ( UInt theInstr )
11151{
11152   /* X-Form */
11153   UChar opc1     = ifieldOPC(theInstr);
11154   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
11155   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
11156   UChar frA_addr = ifieldRegA(theInstr);
11157   UChar frB_addr = ifieldRegB(theInstr);
11158   UInt  opc2     = ifieldOPClo10(theInstr);
11159   UChar b0       = ifieldBIT0(theInstr);
11160
11161   IRTemp ccIR    = newTemp(Ity_I32);
11162   IRTemp ccPPC32 = newTemp(Ity_I32);
11163
11164   IRTemp frA     = newTemp(Ity_F64);
11165   IRTemp frB     = newTemp(Ity_F64);
11166
11167   if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
11168      vex_printf("dis_fp_cmp(ppc)(instr)\n");
11169      return False;
11170   }
11171
11172   assign( frA, getFReg(frA_addr));
11173   assign( frB, getFReg(frB_addr));
11174
11175   assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
11176
11177   /* Map compare result from IR to PPC32 */
11178   /*
11179     FP cmp result | PPC | IR
11180     --------------------------
11181     UN            | 0x1 | 0x45
11182     EQ            | 0x2 | 0x40
11183     GT            | 0x4 | 0x00
11184     LT            | 0x8 | 0x01
11185   */
11186
11187   // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
11188   //                    | ((ccIR ^ (ccIR>>6)) & 1)
11189   assign(
11190      ccPPC32,
11191      binop(
11192         Iop_Shl32,
11193         mkU32(1),
11194         unop(
11195            Iop_32to8,
11196            binop(
11197               Iop_Or32,
11198               binop(
11199                  Iop_And32,
11200                  unop(
11201                     Iop_Not32,
11202                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
11203                  ),
11204                  mkU32(2)
11205               ),
11206               binop(
11207                  Iop_And32,
11208                  binop(
11209                     Iop_Xor32,
11210                     mkexpr(ccIR),
11211                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
11212                  ),
11213                  mkU32(1)
11214               )
11215            )
11216         )
11217      )
11218   );
11219
11220   putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
11221   putFPCC( mkexpr( ccPPC32 ) );
11222
11223   // XXX XXX XXX FIXME
11224   // Also write the result into FPRF (it's not entirely clear how)
11225
11226   /* Note: Differences between fcmpu and fcmpo are only in exception
11227      flag settings, which aren't supported anyway. */
11228   switch (opc2) {
11229   case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
11230      DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
11231      break;
11232   case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
11233      DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
11234      break;
11235   default:
11236      vex_printf("dis_fp_cmp(ppc)(opc2)\n");
11237      return False;
11238   }
11239   return True;
11240}
11241
11242
11243
11244/*
11245  Floating Point Rounding/Conversion Instructions
11246*/
11247static Bool dis_fp_round ( UInt theInstr )
11248{
11249   /* X-Form */
11250   UChar opc1     = ifieldOPC(theInstr);
11251   UChar b16to20  = ifieldRegA(theInstr);
11252   UChar frD_addr = ifieldRegDS(theInstr);
11253   UChar frB_addr = ifieldRegB(theInstr);
11254   UInt  opc2     = ifieldOPClo10(theInstr);
11255   UChar flag_rC  = ifieldBIT0(theInstr);
11256
11257   IRTemp  frD     = newTemp(Ity_F64);
11258   IRTemp  frB     = newTemp(Ity_F64);
11259   IRTemp  r_tmp32 = newTemp(Ity_I32);
11260   IRTemp  r_tmp64 = newTemp(Ity_I64);
11261   IRExpr* rm      = get_IR_roundingmode();
11262
11263   /* By default, we will examine the results of the operation and set
11264      fpscr[FPRF] accordingly. */
11265   Bool set_FPRF = True;
11266
11267   /* By default, if flag_RC is set, we will clear cr1 after the
11268      operation.  In reality we should set cr1 to indicate the
11269      exception status of the operation, but since we're not
11270      simulating exceptions, the exception status will appear to be
11271      zero.  Hence cr1 should be cleared if this is a . form insn. */
11272   Bool clear_CR1 = True;
11273   if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
11274      vex_printf("dis_fp_round(ppc)(instr)\n");
11275      return False;
11276   }
11277
11278   assign( frB, getFReg(frB_addr));
11279   if (opc1 == 0x3B) {
11280      /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
11281       * they're very similar to the other instructions handled here, but have
11282       * a different primary opcode.
11283       */
11284      switch (opc2) {
11285         case 0x34E: // fcfids (Float convert from signed DWord to single precision)
11286            DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11287            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
11288            assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
11289                                                              mkexpr( r_tmp64 ) ) ) );
11290            goto putFR;
11291
11292         case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
11293            DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11294            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
11295            assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
11296            goto putFR;
11297      }
11298   }
11299
11300
11301   switch (opc2) {
11302   case 0x00C: // frsp (Float Round to Single, PPC32 p423)
11303      DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11304      assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
11305      break;
11306
11307   case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
11308      DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11309      assign( r_tmp32,
11310              binop(Iop_F64toI32S, rm, mkexpr(frB)) );
11311      assign( frD, unop( Iop_ReinterpI64asF64,
11312                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
11313      /* FPRF is undefined after fctiw.  Leave unchanged. */
11314      set_FPRF = False;
11315      break;
11316
11317   case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
11318      DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11319      assign( r_tmp32,
11320              binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
11321      assign( frD, unop( Iop_ReinterpI64asF64,
11322                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
11323      /* FPRF is undefined after fctiwz.  Leave unchanged. */
11324      set_FPRF = False;
11325      break;
11326
11327   case 0x08F: case 0x08E: // fctiwu[z]
11328      DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
11329               flag_rC ? ".":"", frD_addr, frB_addr);
11330      assign( r_tmp32,
11331              binop( Iop_F64toI32U,
11332                     opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
11333                     mkexpr( frB ) ) );
11334      assign( frD, unop( Iop_ReinterpI64asF64,
11335                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
11336      /* FPRF is undefined after fctiwz.  Leave unchanged. */
11337      set_FPRF = False;
11338      break;
11339
11340
11341   case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
11342      DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11343      assign( r_tmp64,
11344              binop(Iop_F64toI64S, rm, mkexpr(frB)) );
11345      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
11346      /* FPRF is undefined after fctid.  Leave unchanged. */
11347      set_FPRF = False;
11348      break;
11349
11350   case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
11351      DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11352      assign( r_tmp64,
11353              binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
11354      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
11355      /* FPRF is undefined after fctidz.  Leave unchanged. */
11356      set_FPRF = False;
11357      break;
11358
11359   case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
11360   {
11361      DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
11362               flag_rC ? ".":"", frD_addr, frB_addr);
11363      assign( r_tmp64,
11364              binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
11365      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
11366      /* FPRF is undefined after fctidz.  Leave unchanged. */
11367      set_FPRF = False;
11368      break;
11369   }
11370   case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
11371      DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11372      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
11373      assign( frD,
11374              binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
11375      break;
11376
11377   case 0x3CE: // fcfidu (Float convert from unsigned DWord)
11378      DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11379      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
11380      assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
11381      break;
11382
11383   case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
11384      switch(opc2) {
11385      case 0x188: // frin (Floating Round to Integer Nearest)
11386         DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11387         assign( r_tmp64,
11388                 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
11389         break;
11390      case 0x1A8: // friz (Floating Round to Integer Toward Zero)
11391         DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11392         assign( r_tmp64,
11393                 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
11394         break;
11395      case 0x1C8: // frip (Floating Round to Integer Plus)
11396         DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11397         assign( r_tmp64,
11398                 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
11399         break;
11400      case 0x1E8: // frim (Floating Round to Integer Minus)
11401         DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11402         assign( r_tmp64,
11403                 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
11404         break;
11405      }
11406
11407      /* don't use the rounded integer if frB is outside -9e18..9e18 */
11408      /* F64 has only log10(2**52) significant digits anyway */
11409      /* need to preserve sign of zero */
11410      /*   frD = (fabs(frB) > 9e18) ? frB :
11411               (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
11412      assign(frD, IRExpr_ITE(
11413                     binop(Iop_CmpNE8,
11414                           unop(Iop_32to8,
11415                                binop(Iop_CmpF64,
11416                                      IRExpr_Const(IRConst_F64(9e18)),
11417                                      unop(Iop_AbsF64, mkexpr(frB)))),
11418                           mkU8(0)),
11419                     mkexpr(frB),
11420                     IRExpr_ITE(
11421                        binop(Iop_CmpNE32,
11422                              binop(Iop_Shr32,
11423                                    unop(Iop_64HIto32,
11424                                         unop(Iop_ReinterpF64asI64,
11425                                              mkexpr(frB))),
11426                                    mkU8(31)),
11427                              mkU32(0)),
11428                        unop(Iop_NegF64,
11429                             unop( Iop_AbsF64,
11430                                   binop(Iop_I64StoF64, mkU32(0),
11431                                         mkexpr(r_tmp64)) )),
11432                        binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
11433                     )
11434      ));
11435      break;
11436
11437   default:
11438      vex_printf("dis_fp_round(ppc)(opc2)\n");
11439      return False;
11440   }
11441putFR:
11442   putFReg( frD_addr, mkexpr(frD) );
11443
11444   if (set_FPRF) {
11445      // XXX XXX XXX FIXME
11446      // set FPRF from frD
11447   }
11448
11449   if (flag_rC && clear_CR1) {
11450      putCR321( 1, mkU8(0) );
11451      putCR0( 1, mkU8(0) );
11452   }
11453
11454   return True;
11455}
11456
11457/*
11458  Floating Point Pair Instructions
11459*/
11460static Bool dis_fp_pair ( UInt theInstr )
11461{
11462   /* X-Form/DS-Form */
11463   UChar  opc1         = ifieldOPC(theInstr);
11464   UChar  frT_hi_addr  = ifieldRegDS(theInstr);
11465   UChar  frT_lo_addr  = frT_hi_addr + 1;
11466   UChar  rA_addr      = ifieldRegA(theInstr);
11467   UChar  rB_addr      = ifieldRegB(theInstr);
11468   UInt  uimm16        = ifieldUIMM16(theInstr);
11469   Int    simm16       = extend_s_16to32(uimm16);
11470   UInt   opc2         = ifieldOPClo10(theInstr);
11471   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
11472   IRTemp EA_hi        = newTemp(ty);
11473   IRTemp EA_lo        = newTemp(ty);
11474   IRTemp frT_hi       = newTemp(Ity_F64);
11475   IRTemp frT_lo       = newTemp(Ity_F64);
11476   UChar b0            = ifieldBIT0(theInstr);
11477   Bool is_load        = 0;
11478
11479   switch (opc1) {
11480   case 0x1F: // register offset
11481      /* These instructions work on a pair of registers.  The specified
11482       * register must be even.
11483       */
11484      if ((frT_hi_addr %2) != 0) {
11485         vex_printf("dis_fp_pair(ppc) ldpx or stdpx: odd frT register\n");
11486         return False;
11487      }
11488
11489      switch(opc2) {
11490      case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
11491         DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
11492         is_load = 1;
11493         break;
11494      case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
11495         DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
11496         break;
11497      default:
11498         vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
11499         return False;
11500      }
11501
11502      if (b0 != 0) {
11503         vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
11504         return False;
11505      }
11506      assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
11507      break;
11508   case 0x39:
11509   {
11510      UInt  DS  = IFIELD( theInstr, 2, 14);
11511      UChar vRT = ifieldRegDS(theInstr);
11512      IRTemp EA = newTemp( ty );
11513
11514      opc2 = ifieldOPC0o2(theInstr);
11515
11516      switch(opc2) {
11517      case 0x0:     // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
11518         /* This instruction works on a pair of registers.  The specified
11519          * register must be even.
11520          */
11521         if ((frT_hi_addr %2) != 0) {
11522            vex_printf("dis_fp_pair(ppc) lfdp : odd frT register\n");
11523            return False;
11524         }
11525
11526         DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
11527         assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
11528         is_load = 1;
11529         break;
11530
11531      case 0x2:     // lxsd (Load VSX Scalar Doubleword)
11532         DIP("lxsd v%u,%d(r%u)\n", vRT, DS, rA_addr);
11533
11534         assign( EA, ea_rAor0_simm( rA_addr, DS<<2  ) );
11535
11536         putVSReg( vRT+32, binop( Iop_64HLtoV128,
11537                                  load( Ity_I64, mkexpr( EA ) ),
11538                                  mkU64( 0 ) ) );
11539         return True;
11540
11541      case 0x3:     // lxssp (Load VSX Scalar Single)
11542         DIP("lxssp v%u,%d(r%u)\n", vRT, DS, rA_addr);
11543
11544         assign( EA, ea_rAor0_simm( rA_addr, DS<<2  ) );
11545
11546         putVSReg( vRT+32, binop( Iop_64HLtoV128,
11547                                  binop( Iop_32HLto64,
11548                                         load( Ity_I32, mkexpr( EA ) ),
11549                                         mkU32( 0 ) ),
11550                                  mkU64( 0 ) ) );
11551         return True;
11552
11553      default:
11554         vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n");
11555         return False;
11556      }
11557      break;
11558   }
11559   case 0x3d:
11560   {
11561      UInt  DS  = IFIELD( theInstr, 2, 14);
11562      UChar vRS = ifieldRegDS(theInstr);
11563      IRTemp EA = newTemp( ty );
11564
11565      opc2 = ifieldOPC0o2(theInstr);
11566
11567      switch(opc2) {
11568      case 0x0:
11569         // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
11570         /* This instruction works on a pair of registers.  The specified
11571          * register must be even.
11572          */
11573         if ((frT_hi_addr %2) != 0) {
11574            vex_printf("dis_fp_pair(ppc) stfdp : odd frT register\n");
11575            return False;
11576         }
11577
11578         DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
11579         assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
11580         break;
11581
11582      case 0x1:
11583      {
11584         UInt ea_off = 8;
11585         IRTemp word[2];
11586         IRExpr* irx_addr;
11587         UInt  T  = IFIELD( theInstr, 21, 5);  // T or S depending on inst
11588         UInt  TX = IFIELD( theInstr,  3, 1);  // TX or SX field
11589
11590         word[0] = newTemp(Ity_I64);
11591         word[1] = newTemp(Ity_I64);
11592         DS  = IFIELD( theInstr, 4, 12);   // DQ in the instruction definition
11593         assign( EA, ea_rAor0_simm( rA_addr, DS<<4  ) );
11594
11595         if ( IFIELD( theInstr, 0, 3) == 1) {
11596            // lxv (Load VSX Vector)
11597            DIP("lxv v%u,%d(r%u)\n", vRS, DS, rA_addr);
11598
11599            assign( word[0], load( Ity_I64, mkexpr( EA ) ) );
11600
11601            irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
11602                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
11603
11604            assign( word[1], load( Ity_I64, irx_addr ) );
11605
11606            if (host_endness == VexEndnessBE)
11607               putVSReg( TX*32+T, binop( Iop_64HLtoV128,
11608                                         mkexpr( word[0] ),
11609                                         mkexpr( word[1] ) ) );
11610            else
11611               putVSReg( TX*32+T, binop( Iop_64HLtoV128,
11612                                         mkexpr( word[1] ),
11613                                         mkexpr( word[0] ) ) );
11614            return True;
11615
11616         } else if ( IFIELD( theInstr, 0, 3) == 5) {
11617            // stxv (Store VSX Vector)
11618            DIP("stxv v%u,%d(r%u)\n", vRS, DS, rA_addr);
11619
11620            if (host_endness == VexEndnessBE) {
11621               store( mkexpr(EA), unop( Iop_V128HIto64,
11622                                        getVSReg( TX*32+T ) ) );
11623               irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
11624                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
11625               store( irx_addr, unop( Iop_V128to64,
11626                                       getVSReg( TX*32+T ) ) );
11627            } else {
11628               store( mkexpr(EA), unop( Iop_V128to64,
11629                                        getVSReg( TX*32+T ) ) );
11630               irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
11631                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
11632               store( irx_addr, unop( Iop_V128HIto64,
11633                                      getVSReg( TX*32+T ) ) );
11634            }
11635            return True;
11636
11637         } else {
11638            vex_printf("dis_fp_pair vector load/store (ppc) : DS-form wrong opc2\n");
11639            return False;
11640         }
11641         break;
11642      }
11643      case 0x2:
11644         // stxsd (Store VSX Scalar Doubleword)
11645         DIP("stxsd v%u,%d(r%u)\n", vRS, DS, rA_addr);
11646
11647         assign( EA, ea_rAor0_simm( rA_addr, DS<<2  ) );
11648
11649         store( mkexpr(EA), unop( Iop_V128HIto64,
11650                                  getVSReg( vRS+32 ) ) );
11651         /* HW is clearing vector element 1.  Don't see that in the ISA but
11652          * matching the HW.
11653          */
11654         putVSReg( vRS+32, binop( Iop_64HLtoV128,
11655                                  unop( Iop_V128HIto64,
11656                                        getVSReg( vRS+32 ) ),
11657                                  mkU64( 0 ) ) );
11658         return True;
11659
11660      case 0x3:
11661         // stxssp (Store VSX Scalar Single)
11662         DIP("stxssp v%u,%d(r%u)\n", vRS, DS, rA_addr);
11663
11664         assign( EA, ea_rAor0_simm( rA_addr, DS<<2  ) );
11665
11666         store( mkexpr(EA), unop( Iop_64HIto32,
11667                                  unop( Iop_V128HIto64,
11668                                        getVSReg( vRS+32 ) ) ) );
11669         return True;
11670
11671      default:
11672         vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n");
11673         return False;
11674      }
11675      break;
11676   }
11677   default:   // immediate offset
11678      vex_printf("dis_fp_pair(ppc)(instr)\n");
11679      return False;
11680   }
11681
11682   if (mode64)
11683      assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
11684   else
11685      assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
11686
11687   assign( frT_hi, getFReg(frT_hi_addr) );
11688   assign( frT_lo, getFReg(frT_lo_addr) );
11689
11690   if (is_load) {
11691      putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) );
11692      putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) );
11693   } else {
11694      store( mkexpr(EA_hi), mkexpr(frT_hi) );
11695      store( mkexpr(EA_lo), mkexpr(frT_lo) );
11696   }
11697
11698   return True;
11699}
11700
11701
11702/*
11703  Floating Point Merge Instructions
11704*/
11705static Bool dis_fp_merge ( UInt theInstr )
11706{
11707   /* X-Form */
11708   UInt  opc2     = ifieldOPClo10(theInstr);
11709   UChar frD_addr = ifieldRegDS(theInstr);
11710   UChar frA_addr = ifieldRegA(theInstr);
11711   UChar frB_addr = ifieldRegB(theInstr);
11712
11713   IRTemp frD = newTemp(Ity_F64);
11714   IRTemp frA = newTemp(Ity_F64);
11715   IRTemp frB = newTemp(Ity_F64);
11716
11717   assign( frA, getFReg(frA_addr));
11718   assign( frB, getFReg(frB_addr));
11719
11720   switch (opc2) {
11721   case 0x3c6: // fmrgew floating merge even word
11722      DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
11723
11724      assign( frD, unop( Iop_ReinterpI64asF64,
11725                         binop( Iop_32HLto64,
11726                                unop( Iop_64HIto32,
11727                                      unop( Iop_ReinterpF64asI64,
11728                                            mkexpr(frA) ) ),
11729                                unop( Iop_64HIto32,
11730                                      unop( Iop_ReinterpF64asI64,
11731                                            mkexpr(frB) ) ) ) ) );
11732   break;
11733
11734   case 0x346: // fmrgow floating merge odd word
11735      DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
11736
11737      assign( frD, unop( Iop_ReinterpI64asF64,
11738                         binop( Iop_32HLto64,
11739                                unop( Iop_64to32,
11740                                      unop( Iop_ReinterpF64asI64,
11741                                            mkexpr(frA) ) ),
11742                                unop( Iop_64to32,
11743                                      unop( Iop_ReinterpF64asI64,
11744                                            mkexpr(frB) ) ) ) ) );
11745   break;
11746
11747   default:
11748      vex_printf("dis_fp_merge(ppc)(opc2)\n");
11749      return False;
11750   }
11751
11752   putFReg( frD_addr, mkexpr(frD) );
11753   return True;
11754}
11755
11756/*
11757  Floating Point Move Instructions
11758*/
11759static Bool dis_fp_move ( UInt theInstr )
11760{
11761   /* X-Form */
11762   UChar opc1     = ifieldOPC(theInstr);
11763   UChar frD_addr = ifieldRegDS(theInstr);
11764   UChar frA_addr = ifieldRegA(theInstr);
11765   UChar frB_addr = ifieldRegB(theInstr);
11766   UInt  opc2     = ifieldOPClo10(theInstr);
11767   UChar flag_rC  = ifieldBIT0(theInstr);
11768
11769   IRTemp frD = newTemp(Ity_F64);
11770   IRTemp frB = newTemp(Ity_F64);
11771   IRTemp itmpB = newTemp(Ity_F64);
11772   IRTemp frA;
11773   IRTemp signA;
11774   IRTemp hiD;
11775
11776   if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
11777      vex_printf("dis_fp_move(ppc)(instr)\n");
11778      return False;
11779   }
11780
11781   assign( frB, getFReg(frB_addr));
11782
11783   switch (opc2) {
11784   case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
11785      DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
11786          frB_addr);
11787      signA = newTemp(Ity_I32);
11788      hiD = newTemp(Ity_I32);
11789      itmpB = newTemp(Ity_I64);
11790      frA = newTemp(Ity_F64);
11791      assign( frA, getFReg(frA_addr) );
11792
11793      /* get A's sign bit */
11794      assign(signA, binop(Iop_And32,
11795                          unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
11796                                                  mkexpr(frA))),
11797                          mkU32(0x80000000)) );
11798
11799      assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
11800
11801      /* mask off B's sign bit and or in A's sign bit */
11802      assign(hiD, binop(Iop_Or32,
11803                        binop(Iop_And32,
11804                              unop(Iop_64HIto32,
11805                                   mkexpr(itmpB)),  /* frB's high 32 bits */
11806                              mkU32(0x7fffffff)),
11807                        mkexpr(signA)) );
11808
11809      /* combine hiD/loB into frD */
11810      assign( frD, unop(Iop_ReinterpI64asF64,
11811                        binop(Iop_32HLto64,
11812                              mkexpr(hiD),
11813                              unop(Iop_64to32,
11814                                   mkexpr(itmpB)))) );   /* frB's low 32 bits */
11815      break;
11816
11817   case 0x028: // fneg (Floating Negate, PPC32 p416)
11818      DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11819      assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
11820      break;
11821
11822   case 0x048: // fmr (Floating Move Register, PPC32 p410)
11823      DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11824      assign( frD, mkexpr(frB) );
11825      break;
11826
11827   case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
11828      DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11829      assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
11830      break;
11831
11832   case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
11833      DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11834      assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
11835      break;
11836
11837   default:
11838      vex_printf("dis_fp_move(ppc)(opc2)\n");
11839      return False;
11840   }
11841
11842   putFReg( frD_addr, mkexpr(frD) );
11843
11844   /* None of these change FPRF.  cr1 is set in the usual way though,
11845      if flag_rC is set. */
11846
11847   if (flag_rC) {
11848      putCR321( 1, mkU8(0) );
11849      putCR0( 1, mkU8(0) );
11850   }
11851
11852   return True;
11853}
11854
11855
11856
11857/*
11858  Floating Point Status/Control Register Instructions
11859*/
11860static Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
11861{
11862   /* Many forms - see each switch case */
11863   UChar opc1    = ifieldOPC(theInstr);
11864   UInt  opc2    = ifieldOPClo10(theInstr);
11865   UChar flag_rC = ifieldBIT0(theInstr);
11866
11867   if (opc1 != 0x3F) {
11868      vex_printf("dis_fp_scr(ppc)(instr)\n");
11869      return False;
11870   }
11871
11872   switch (opc2) {
11873   case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
11874      // Bit crbD of the FPSCR is set.
11875      UChar crbD    = ifieldRegDS(theInstr);
11876      UInt  b11to20 = IFIELD(theInstr, 11, 10);
11877
11878      if (b11to20 != 0) {
11879         vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
11880         return False;
11881      }
11882      DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
11883      putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
11884		     1ULL << ( 31 - crbD ) );
11885      break;
11886   }
11887
11888   case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
11889      UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
11890      UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
11891      UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
11892      UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
11893      IRTemp  tmp     = newTemp(Ity_I32);
11894      IRExpr* fpscr_all;
11895      if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
11896         vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
11897         return False;
11898      }
11899      DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
11900      vassert(crfD < 8);
11901      vassert(crfS < 8);
11902      fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
11903      assign( tmp, binop(Iop_And32,
11904                         binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
11905                        mkU32(0xF)) );
11906      putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
11907      break;
11908   }
11909
11910   case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
11911      // Bit crbD of the FPSCR is cleared.
11912      UChar crbD    = ifieldRegDS(theInstr);
11913      UInt  b11to20 = IFIELD(theInstr, 11, 10);
11914
11915      if (b11to20 != 0) {
11916         vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
11917         return False;
11918      }
11919      DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
11920      putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
11921      break;
11922   }
11923
11924   case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
11925      UInt crfD     = IFIELD( theInstr, 23, 3 );
11926      UChar b17to22 = toUChar( IFIELD( theInstr, 17, 6 ) );
11927      UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
11928      UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
11929      UChar Wbit    = toUChar( IFIELD( theInstr, 16, 1 ) );
11930
11931      if (b17to22 != 0 || b11 != 0 || (Wbit && !GX_level)) {
11932         vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
11933         return False;
11934      }
11935      DIP("mtfsfi%s crf%u,%d%s\n", flag_rC ? ".":"", crfD, IMM, Wbit ? ",1":"");
11936      crfD = crfD + (8 * (1 - Wbit) );
11937      putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
11938      break;
11939   }
11940
11941   case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
11942      UChar   frD_addr  = ifieldRegDS(theInstr);
11943      UChar   frB_addr  = ifieldRegB(theInstr);
11944      IRTemp  frB = newTemp(Ity_F64);
11945      UInt    b11to12   = IFIELD(theInstr, 19, 2);
11946      UInt    b13to15   = IFIELD(theInstr, 16, 3);
11947      UInt    RN        = IFIELD(theInstr, 11, 2);
11948      UInt    DRN       = IFIELD(theInstr, 11, 3);
11949
11950      /* The FPSCR_DRN, FPSCR_RN and FPSCR_FPCC are all stored in
11951       * their own 8-bit entries with distinct offsets.  The FPSCR
11952       * register is handled as two 32-bit values.  We need to
11953       * assemble the pieces into the single 64-bit value to return.
11954       */
11955      IRExpr* fpscr_lower
11956         = binop( Iop_Or32,
11957                  getGST_masked( PPC_GST_FPSCR, (MASK_FPSCR_RN | MASK_FPSCR_C_FPCC) ),
11958                  binop( Iop_Or32,
11959                         binop( Iop_Shl32,
11960                                getC(),
11961                                mkU8(63-47) ) ,
11962                         binop( Iop_Shl32,
11963                                getFPCC(),
11964                                mkU8(63-51) ) ) );
11965      IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN );
11966
11967      if ((b11to12 == 0) && (b13to15 == 0)) {
11968            DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
11969            putFReg( frD_addr,
11970                     unop( Iop_ReinterpI64asF64,
11971                           binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
11972
11973      } else if ((b11to12 == 0) && (b13to15 == 1)) {
11974            DIP("mffsce fr%u\n", frD_addr);
11975            /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE,
11976               or XE but in case that changes in the future, do the masking. */
11977            putFReg( frD_addr,
11978                     unop( Iop_ReinterpI64asF64,
11979                           binop( Iop_32HLto64, fpscr_upper,
11980                                  binop( Iop_And32, fpscr_lower,
11981                                         mkU32( 0xFFFFFF07 ) ) ) ) );
11982
11983      } else if ((b11to12 == 2) && (b13to15 == 4)) {
11984            IRTemp  frB_int = newTemp(Ity_I64);
11985
11986            DIP("mffscdrn fr%u,fr%u\n", frD_addr, frB_addr);
11987
11988            assign( frB, getFReg(frB_addr));
11989            assign( frB_int, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
11990
11991            /* Clear all of the FPSCR bits except for the DRN field, VE,
11992               OE, UE, ZE and XE bits and write the result to the frD
11993               register. Note, currently the exception bits are not tracked but
11994               will mask anyway in case that changes in the future. */
11995            putFReg( frD_addr,
11996                     unop( Iop_ReinterpI64asF64,
11997                           binop( Iop_32HLto64,
11998                                  binop( Iop_And32, mkU32(0x7), fpscr_upper ),
11999                                  binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) );
12000
12001            /* Put new_DRN bits into the FPSCR register */
12002            putGST_masked( PPC_GST_FPSCR, mkexpr( frB_int ), MASK_FPSCR_DRN );
12003
12004      } else if ((b11to12 == 2) && (b13to15 == 5)) {
12005            DIP("mffscdrni fr%u,%d\n", frD_addr, DRN);
12006
12007            /* Clear all of the FPSCR bits except for the DRN field, VE,
12008               OE, UE, ZE and XE bits and write the result to the frD
12009               register. Note, currently the exception bits are not tracked but
12010               will mask anyway in case that changes in the future. */
12011            putFReg( frD_addr,
12012                     unop( Iop_ReinterpI64asF64,
12013                           binop( Iop_32HLto64,
12014                                  binop( Iop_And32, mkU32(0x7), fpscr_upper ),
12015                                  binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) );
12016
12017            /* Put new_DRN bits into the FPSCR register */
12018            putGST_masked( PPC_GST_FPSCR, binop( Iop_32HLto64, mkU32( DRN ),
12019                                                 mkU32( 0 ) ), MASK_FPSCR_DRN );
12020
12021      } else if ((b11to12 == 2) && (b13to15 == 6)) {
12022            IRTemp  frB_int = newTemp(Ity_I64);
12023
12024            DIP("mffscrn fr%u,fr%u\n", frD_addr,frB_addr);
12025
12026            assign( frB, getFReg(frB_addr));
12027            assign( frB_int, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
12028
12029            /* Clear all of the FPSCR bits except for the DRN field, VE,
12030               OE, UE, ZE and XE bits and write the result to the frD
12031               register. Note, currently the exception bits are not tracked but
12032               will mask anyway in case that changes in the future. */
12033            putFReg( frD_addr,
12034                     unop( Iop_ReinterpI64asF64,
12035                           binop( Iop_32HLto64,
12036                                  binop( Iop_And32, mkU32(0x7), fpscr_upper ),
12037                                  binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) );
12038
12039            /* Put new_CRN bits into the FPSCR register */
12040            putGST_masked( PPC_GST_FPSCR, mkexpr( frB_int ), MASK_FPSCR_RN );
12041
12042      } else if ((b11to12 == 2) && (b13to15 == 7)) {
12043            DIP("mffscrni fr%u,%u\n", frD_addr, RN);
12044
12045            /* Clear all of the FPSCR bits except for the DRN field, VE,
12046               OE, UE, ZE and XE bits and write the result to the frD
12047               register. Note, currently the exception bits are not tracked but
12048               will mask anyway in case that changes in the future. */
12049            putFReg( frD_addr,
12050                     unop( Iop_ReinterpI64asF64,
12051                           binop( Iop_32HLto64,
12052                                  binop( Iop_And32, mkU32(0x7), fpscr_upper ),
12053                                  binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) );
12054
12055            /* Put new_RN bits into the FPSCR register */
12056            putGST_masked( PPC_GST_FPSCR, binop( Iop_32HLto64, mkU32( 0 ),
12057                                                 mkU32( RN ) ), MASK_FPSCR_RN );
12058
12059      } else if ((b11to12 == 3) && (b13to15 == 0)) {
12060            DIP("mffsl fr%u\n", frD_addr);
12061            /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE,
12062               XE, FR, FI, C, FL, FG, FE, FU.  Also only track DRN in the upper
12063               bits but in case that changes in the future we will do the
12064               masking. */
12065            putFReg( frD_addr,
12066                     unop( Iop_ReinterpI64asF64,
12067                           binop( Iop_32HLto64,
12068                                  binop( Iop_And32, fpscr_upper,
12069                                         mkU32( 0x7 ) ),
12070                                  binop( Iop_And32, fpscr_lower,
12071                                         mkU32( 0x7F0FF ) ) ) ) );
12072      } else {
12073         vex_printf("dis_fp_scr(ppc)(mff**) Unrecognized instruction.\n");
12074         return False;
12075      }
12076      break;
12077   }
12078
12079   case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
12080      UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
12081      UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
12082      UChar frB_addr = ifieldRegB(theInstr);
12083      IRTemp frB   = newTemp(Ity_F64);
12084      IRTemp rB_64 = newTemp( Ity_I64 );
12085      Int i;
12086      ULong mask;
12087      UChar Wbit;
12088#define BFP_MASK_SEED 0x3000000000000000ULL
12089#define DFP_MASK_SEED 0x7000000000000000ULL
12090
12091      if (GX_level) {
12092         /* This implies that Decimal Floating Point is supported, and the
12093          * FPSCR must be managed as a 64-bit register.
12094          */
12095         Wbit = toUChar( IFIELD(theInstr, 16, 1) );
12096      } else {
12097         Wbit = 0;
12098      }
12099
12100      if (b25 == 1) {
12101         /* new 64 bit move variant for power 6.  If L field (bit 25) is
12102          * a one do a full 64 bit move.  Note, the FPSCR is not really
12103          * properly modeled.  This instruciton only changes the value of
12104          * the rounding mode bit fields RN, FPCC and DRN.  The HW exception bits
12105          * do not get set in the simulator.  1/12/09
12106          */
12107         DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
12108         mask = 0x1F0001F003;
12109
12110      } else {
12111         DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
12112         // Build 32bit mask from FM:
12113         mask = 0;
12114         for (i=0; i<8; i++) {
12115            if ((FM & (1<<(7-i))) == 1) {
12116               /* FPSCR field k is set to the contents of the corresponding
12117                * field of register FRB, where k = i+8x(1-W).  In the Power
12118                * ISA, register field numbering is from left to right, so field
12119                * 15 is the least significant field in a 64-bit register.  To
12120                * generate the mask, we set all the appropriate rounding mode
12121                * bits in the highest order nibble (field 0) and shift right
12122                * 'k x nibble length'.
12123                */
12124               if (Wbit)
12125                  mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
12126               else
12127                  mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
12128            }
12129            if ((FM & (1<<(7-i))) == 0x2) { //set the FPCC bits
12130               mask |= 0xF000;
12131            }
12132            if ((FM & (1<<(7-i))) == 0x4) { //set the Floating-Point Class Descriptor (C) bit
12133               mask |= 0x10000;
12134            }
12135         }
12136      }
12137      assign( frB, getFReg(frB_addr));
12138      assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
12139      putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
12140      break;
12141   }
12142
12143   default:
12144      vex_printf("dis_fp_scr(ppc)(opc2)\n");
12145      return False;
12146   }
12147   return True;
12148}
12149
12150/*------------------------------------------------------------*/
12151/*--- Decimal Floating Point (DFP)  Helper functions       ---*/
12152/*------------------------------------------------------------*/
12153#define DFP_LONG  1
12154#define DFP_EXTND 2
12155#define DFP_LONG_BIAS   398
12156#define DFP_LONG_ENCODED_FIELD_MASK  0x1F00
12157#define DFP_EXTND_BIAS  6176
12158#define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
12159#define DFP_LONG_EXP_MSK   0XFF
12160#define DFP_EXTND_EXP_MSK  0XFFF
12161
12162#define DFP_G_FIELD_LONG_MASK     0x7FFC0000  // upper 32-bits only
12163#define DFP_LONG_GFIELD_RT_SHIFT  (63 - 13 - 32) // adj for upper 32-bits
12164#define DFP_G_FIELD_EXTND_MASK    0x7FFFC000  // upper 32-bits only
12165#define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
12166#define DFP_T_FIELD_LONG_MASK     0x3FFFF  // mask for upper 32-bits
12167#define DFP_T_FIELD_EXTND_MASK    0x03FFFF // mask for upper 32-bits
12168#define DFP_LONG_EXP_MAX          369      // biased max
12169#define DFP_LONG_EXP_MIN          0        // biased min
12170#define DFP_EXTND_EXP_MAX         6111     // biased max
12171#define DFP_EXTND_EXP_MIN         0        // biased min
12172#define DFP_LONG_MAX_SIG_DIGITS   16
12173#define DFP_EXTND_MAX_SIG_DIGITS  34
12174#define MAX_DIGITS_IN_STRING      8
12175
12176
12177#define  AND(x, y) binop( Iop_And32, x, y )
12178#define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
12179#define   OR(x, y) binop( Iop_Or32,  x, y )
12180#define  OR3(x, y, z)    OR( x, OR( y, z ) )
12181#define  OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
12182#define  NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1,  mkexpr( x ) ) ) )
12183
12184#define  SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
12185#define  SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
12186
12187#define BITS5(_b4,_b3,_b2,_b1,_b0) \
12188   (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
12189    ((_b1) << 1) | ((_b0) << 0))
12190
12191static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
12192{
12193   IRTemp lmd_07_mask   = newTemp( Ity_I32 );
12194   IRTemp lmd_8_mask    = newTemp( Ity_I32 );
12195   IRTemp lmd_9_mask    = newTemp( Ity_I32 );
12196   IRTemp lmexp_00_mask = newTemp( Ity_I32 );
12197   IRTemp lmexp_01_mask = newTemp( Ity_I32 );
12198   IRTemp lmexp_10_mask = newTemp( Ity_I32 );
12199   IRTemp lmd_07_val    = newTemp( Ity_I32 );
12200   IRTemp lmd_8_val     = newTemp( Ity_I32 );
12201   IRTemp lmd_9_val     = newTemp( Ity_I32 );
12202
12203   /* The encodig is as follows:
12204    * lmd - left most digit
12205    * lme - left most 2-bits of the exponent
12206    *
12207    *    lmd
12208    *   0 - 7    (lmexp << 3) | lmd
12209    *     8      0b11000 (24 decimal) if lme=0b00;
12210    *            0b11010 (26 decimal) if lme=0b01;
12211    *            0b11100 (28 decimal) if lme=0b10;
12212    *     9      0b11001 (25 decimal) if lme=0b00;
12213    *            0b11011 (27 decimal) if lme=0b01;
12214    *            0b11101 (29 decimal) if lme=0b10;
12215    */
12216
12217   /* Generate the masks for each condition */
12218   assign( lmd_07_mask,
12219           unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
12220   assign( lmd_8_mask,
12221           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
12222   assign( lmd_9_mask,
12223           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
12224   assign( lmexp_00_mask,
12225           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
12226   assign( lmexp_01_mask,
12227           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
12228   assign( lmexp_10_mask,
12229           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
12230
12231   /* Generate the values for each LMD condition, assuming the condition
12232    * is TRUE.
12233    */
12234   assign( lmd_07_val,
12235           binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
12236   assign( lmd_8_val,
12237           binop( Iop_Or32,
12238                  binop( Iop_Or32,
12239                         binop( Iop_And32,
12240                                mkexpr( lmexp_00_mask ),
12241                                mkU32( 24 ) ),
12242                         binop( Iop_And32,
12243                                mkexpr( lmexp_01_mask ),
12244                                mkU32( 26 ) ) ),
12245                  binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
12246   assign( lmd_9_val,
12247           binop( Iop_Or32,
12248                  binop( Iop_Or32,
12249                         binop( Iop_And32,
12250                                mkexpr( lmexp_00_mask ),
12251                                mkU32( 25 ) ),
12252                         binop( Iop_And32,
12253                                mkexpr( lmexp_01_mask ),
12254                                mkU32( 27 ) ) ),
12255                  binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
12256
12257   /* generate the result from the possible LMD values */
12258   return binop( Iop_Or32,
12259                 binop( Iop_Or32,
12260                        binop( Iop_And32,
12261                               mkexpr( lmd_07_mask ),
12262                               mkexpr( lmd_07_val ) ),
12263                        binop( Iop_And32,
12264                               mkexpr( lmd_8_mask ),
12265                               mkexpr( lmd_8_val ) ) ),
12266                 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
12267}
12268
12269static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
12270{
12271   /* Extract the exponent and the left most digit of the mantissa
12272    * from the G field bits [0:4].
12273    */
12274   IRTemp lmd_07_mask   = newTemp( Ity_I32 );
12275   IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
12276   IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
12277   IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
12278   IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
12279   IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
12280   IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
12281
12282   IRTemp lmd_07_val = newTemp( Ity_I32 );
12283   IRTemp lmd_8_val  = newTemp( Ity_I32 );
12284   IRTemp lmd_9_val  = newTemp( Ity_I32 );
12285
12286   /* The left most digit (LMD) encoding is as follows:
12287    *    lmd
12288    *   0 - 7    (lmexp << 3) | lmd
12289    *     8      0b11000 (24 decimal) if lme=0b00;
12290    *            0b11010 (26 decimal) if lme=0b01;
12291    *            0b11100 (28 decimal) if lme=0b10
12292    *     9      0b11001 (25 decimal) if lme=0b00;
12293    *            0b11011 (27 decimal) if lme=0b01;
12294    *            0b11101 (29 decimal) if lme=0b10;
12295    */
12296
12297   /* Generate the masks for each condition of LMD and exponent bits */
12298   assign( lmd_07_mask,
12299           unop( Iop_1Sto32, binop( Iop_CmpLE32U,
12300                                    gfield_0_4,
12301                                    mkU32( BITS5(1,0,1,1,1) ) ) ) );
12302   assign( lmd_8_00_mask,
12303           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12304                                    gfield_0_4,
12305                                    mkU32( BITS5(1,1,0,0,0) ) ) ) );
12306   assign( lmd_8_01_mask,
12307           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12308                                    gfield_0_4,
12309                                    mkU32( BITS5(1,1,0,1,0) ) ) ) );
12310   assign( lmd_8_10_mask,
12311           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12312                                    gfield_0_4,
12313                                    mkU32( BITS5(1,1,1,0,0) ) ) ) );
12314   assign( lmd_9_00_mask,
12315           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12316                                    gfield_0_4,
12317                                    mkU32( BITS5(1,1,0,0,1) ) ) ) );
12318   assign( lmd_9_01_mask,
12319           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12320                                    gfield_0_4,
12321                                    mkU32( BITS5(1,1,0,1,1) ) ) ) );
12322   assign( lmd_9_10_mask,
12323           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12324                                    gfield_0_4,
12325                                    mkU32( BITS5(1,1,1,0,1) ) ) ) );
12326
12327   /* Generate the values for each LMD condition, assuming the condition
12328    * is TRUE.
12329    */
12330   assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
12331   assign( lmd_8_val, mkU32( 0x8 ) );
12332   assign( lmd_9_val, mkU32( 0x9 ) );
12333
12334   assign( *lmd,
12335           OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
12336                     AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
12337                     AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
12338                     OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
12339                          AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
12340                          AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
12341                          AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
12342                     ) ) );
12343}
12344
12345#define DIGIT1_SHR 4    // shift digit 1 to bottom 4 bits
12346#define DIGIT2_SHR 8    // shift digit 2 to bottom 4 bits
12347#define DIGIT3_SHR 12
12348#define DIGIT4_SHR 16
12349#define DIGIT5_SHR 20
12350#define DIGIT6_SHR 24
12351#define DIGIT7_SHR 28
12352
12353static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
12354{
12355   /* 60-bit BCD string stored in two 32-bit values.  Check that each,
12356    * digit is a valid BCD number, i.e. less then 9.
12357    */
12358   IRTemp valid = newTemp( Ity_I32 );
12359
12360   assign( valid,
12361           AND4( AND4 ( unop( Iop_1Sto32,
12362                              binop( Iop_CmpLE32U,
12363                                     binop( Iop_And32,
12364                                            bcd_l,
12365                                            mkU32 ( 0xF ) ),
12366                                      mkU32( 0x9 ) ) ),
12367                        unop( Iop_1Sto32,
12368                              binop( Iop_CmpLE32U,
12369                                     binop( Iop_And32,
12370                                            binop( Iop_Shr32,
12371                                                   bcd_l,
12372                                                   mkU8 ( DIGIT1_SHR ) ),
12373                                             mkU32 ( 0xF ) ),
12374                                      mkU32( 0x9 ) ) ),
12375                        unop( Iop_1Sto32,
12376                              binop( Iop_CmpLE32U,
12377                                     binop( Iop_And32,
12378                                            binop( Iop_Shr32,
12379                                                   bcd_l,
12380                                                   mkU8 ( DIGIT2_SHR ) ),
12381                                            mkU32 ( 0xF ) ),
12382                                      mkU32( 0x9 ) ) ),
12383                        unop( Iop_1Sto32,
12384                              binop( Iop_CmpLE32U,
12385                                     binop( Iop_And32,
12386                                            binop( Iop_Shr32,
12387                                                   bcd_l,
12388                                                   mkU8 ( DIGIT3_SHR ) ),
12389                                             mkU32 ( 0xF ) ),
12390                                      mkU32( 0x9 ) ) ) ),
12391                 AND4 ( unop( Iop_1Sto32,
12392                              binop( Iop_CmpLE32U,
12393                                     binop( Iop_And32,
12394                                            binop( Iop_Shr32,
12395                                                   bcd_l,
12396                                                   mkU8 ( DIGIT4_SHR ) ),
12397                                            mkU32 ( 0xF ) ),
12398                                     mkU32( 0x9 ) ) ),
12399                        unop( Iop_1Sto32,
12400                              binop( Iop_CmpLE32U,
12401                                     binop( Iop_And32,
12402                                            binop( Iop_Shr32,
12403                                                   bcd_l,
12404                                                   mkU8 ( DIGIT5_SHR ) ),
12405                                            mkU32 ( 0xF ) ),
12406                                     mkU32( 0x9 ) ) ),
12407                        unop( Iop_1Sto32,
12408                              binop( Iop_CmpLE32U,
12409                                     binop( Iop_And32,
12410                                            binop( Iop_Shr32,
12411                                                   bcd_l,
12412                                                   mkU8 ( DIGIT6_SHR ) ),
12413                                            mkU32 ( 0xF ) ),
12414                                     mkU32( 0x9 ) ) ),
12415                        unop( Iop_1Sto32,
12416                              binop( Iop_CmpLE32U,
12417                                     binop( Iop_And32,
12418                                            binop( Iop_Shr32,
12419                                                   bcd_l,
12420                                                   mkU8 ( DIGIT7_SHR ) ),
12421                                            mkU32 ( 0xF ) ),
12422                                     mkU32( 0x9 ) ) ) ),
12423                 AND4( unop( Iop_1Sto32,
12424                             binop( Iop_CmpLE32U,
12425                                    binop( Iop_And32,
12426                                           bcd_u,
12427                                           mkU32 ( 0xF ) ),
12428                                    mkU32( 0x9 ) ) ),
12429                       unop( Iop_1Sto32,
12430                             binop( Iop_CmpLE32U,
12431                                    binop( Iop_And32,
12432                                           binop( Iop_Shr32,
12433                                                  bcd_u,
12434                                                  mkU8 ( DIGIT1_SHR ) ),
12435                                           mkU32 ( 0xF ) ),
12436                                    mkU32( 0x9 ) ) ),
12437                       unop( Iop_1Sto32,
12438                             binop( Iop_CmpLE32U,
12439                                    binop( Iop_And32,
12440                                           binop( Iop_Shr32,
12441                                                  bcd_u,
12442                                                  mkU8 ( DIGIT2_SHR ) ),
12443                                           mkU32 ( 0xF ) ),
12444                                    mkU32( 0x9 ) ) ),
12445                       unop( Iop_1Sto32,
12446                             binop( Iop_CmpLE32U,
12447                                    binop( Iop_And32,
12448                                           binop( Iop_Shr32,
12449                                                  bcd_u,
12450                                                  mkU8 ( DIGIT3_SHR ) ),
12451                                           mkU32 ( 0xF ) ),
12452                                    mkU32( 0x9 ) ) ) ),
12453                 AND4( unop( Iop_1Sto32,
12454                             binop( Iop_CmpLE32U,
12455                                    binop( Iop_And32,
12456                                           binop( Iop_Shr32,
12457                                                  bcd_u,
12458                                                  mkU8 ( DIGIT4_SHR ) ),
12459                                           mkU32 ( 0xF ) ),
12460                                    mkU32( 0x9 ) ) ),
12461                       unop( Iop_1Sto32,
12462                             binop( Iop_CmpLE32U,
12463                                    binop( Iop_And32,
12464                                           binop( Iop_Shr32,
12465                                                  bcd_u,
12466                                                  mkU8 ( DIGIT5_SHR ) ),
12467                                           mkU32 ( 0xF ) ),
12468                                    mkU32( 0x9 ) ) ),
12469                       unop( Iop_1Sto32,
12470                             binop( Iop_CmpLE32U,
12471                                    binop( Iop_And32,
12472                                           binop( Iop_Shr32,
12473                                                  bcd_u,
12474                                                  mkU8 ( DIGIT6_SHR ) ),
12475                                           mkU32 ( 0xF ) ),
12476                                    mkU32( 0x9 ) ) ),
12477                       unop( Iop_1Sto32,
12478                             binop( Iop_CmpLE32U,
12479                                    binop( Iop_And32,
12480                                           binop( Iop_Shr32,
12481                                                  bcd_u,
12482                                                  mkU8 ( DIGIT7_SHR ) ),
12483                                           mkU32 ( 0xF ) ),
12484                                    mkU32( 0x9 ) ) ) ) ) );
12485
12486   return unop( Iop_Not32, mkexpr( valid ) );
12487}
12488#undef DIGIT1_SHR
12489#undef DIGIT2_SHR
12490#undef DIGIT3_SHR
12491#undef DIGIT4_SHR
12492#undef DIGIT5_SHR
12493#undef DIGIT6_SHR
12494#undef DIGIT7_SHR
12495
12496static IRExpr * Generate_neg_sign_mask( IRExpr * sign )
12497{
12498   return binop( Iop_Or32,
12499                 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
12500                 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
12501               );
12502}
12503
12504static IRExpr * Generate_pos_sign_mask( IRExpr * sign )
12505{
12506   return binop( Iop_Or32,
12507                 binop( Iop_Or32,
12508                        unop( Iop_1Sto32,
12509                              binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
12510                        unop( Iop_1Sto32,
12511                              binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
12512                 binop( Iop_Or32,
12513                        unop( Iop_1Sto32,
12514                              binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
12515                        unop( Iop_1Sto32,
12516                              binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
12517}
12518
12519static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
12520                                   IRExpr * neg_sign_mask )
12521{
12522   return binop( Iop_Or32,
12523                 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
12524                 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
12525}
12526
12527static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
12528                                   IRExpr * pos_sign_mask,
12529                                   IRExpr * neg_sign_mask )
12530/* first argument is all 1's if the BCD string had an invalid digit in it. */
12531{
12532   return binop( Iop_Or32,
12533                 invalid_bcd_mask,
12534                 unop( Iop_1Sto32,
12535                       binop( Iop_CmpEQ32,
12536                              binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
12537                              mkU32( 0x0 ) ) ) );
12538}
12539
12540static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
12541                                         IRTemp * top_12_l, IRTemp * mid_60_u,
12542                                         IRTemp * mid_60_l, IRTemp * low_60_u,
12543                                         IRTemp * low_60_l)
12544{
12545   IRTemp tmplow60 = newTemp( Ity_I64 );
12546   IRTemp tmpmid60 = newTemp( Ity_I64 );
12547   IRTemp tmptop12 = newTemp( Ity_I64 );
12548   IRTemp low_50   = newTemp( Ity_I64 );
12549   IRTemp mid_50   = newTemp( Ity_I64 );
12550   IRTemp top_10   = newTemp( Ity_I64 );
12551   IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
12552
12553   /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
12554
12555   /* low_50[49:0] = ((frBI64_lo[49:32]  << 14) | frBI64_lo[31:0]) */
12556   assign( low_50,
12557           binop( Iop_32HLto64,
12558                  binop( Iop_And32,
12559                         unop( Iop_64HIto32, frBI64_lo ),
12560                         mkU32( 0x3FFFF ) ),
12561                         unop( Iop_64to32, frBI64_lo ) ) );
12562
12563   /* Convert the 50 bit densely packed BCD string to a 60 bit
12564    * BCD string.
12565    */
12566   assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
12567   assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
12568   assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
12569
12570   /* mid_50[49:0] =  ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
12571    *                 ((frBI64_hi[17:0]  << 14) | frBI64_lo[63:50])
12572    */
12573   assign( mid_50,
12574           binop( Iop_32HLto64,
12575                  binop( Iop_Or32,
12576                         binop( Iop_Shl32,
12577                                binop( Iop_And32,
12578                                       unop( Iop_64HIto32, frBI64_hi ),
12579                                       mkU32( 0xF ) ),
12580                                mkU8( 14 ) ),
12581                         binop( Iop_Shr32,
12582                                unop( Iop_64to32, frBI64_hi ),
12583                                mkU8( 18 ) ) ),
12584                  binop( Iop_Or32,
12585                         binop( Iop_Shl32,
12586                                unop( Iop_64to32, frBI64_hi ),
12587                                mkU8( 14 ) ),
12588                         binop( Iop_Shr32,
12589                                unop( Iop_64HIto32, frBI64_lo ),
12590                                mkU8( 18 ) ) ) ) );
12591
12592   /* Convert the 50 bit densely packed BCD string to a 60 bit
12593    * BCD string.
12594    */
12595   assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
12596   assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
12597   assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
12598
12599   /* top_10[49:0] = frBI64_hi[45:36]) |  */
12600   assign( top_10,
12601           binop( Iop_32HLto64,
12602                  mkU32( 0 ),
12603                  binop( Iop_And32,
12604                         binop( Iop_Shr32,
12605                                unop( Iop_64HIto32, frBI64_hi ),
12606                                mkU8( 4 ) ),
12607                         mkU32( 0x3FF ) ) ) );
12608
12609   /* Convert the 10 bit densely packed BCD string to a 12 bit
12610    * BCD string.
12611    */
12612   assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
12613   assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
12614   assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
12615}
12616
12617static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
12618                         IRTemp * final_cnt, IRTemp * final_flag,
12619                         IRExpr * string )
12620{
12621   IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
12622   int digits = MAX_DIGITS_IN_STRING;
12623   int i;
12624
12625   cnt[start-1] = newTemp( Ity_I8 );
12626   flag[start-1] = newTemp( Ity_I8 );
12627   assign( cnt[start-1], init_cnt);
12628   assign( flag[start-1], init_flag);
12629
12630   for ( i = start; i <= digits; i++) {
12631      cnt[i] = newTemp( Ity_I8 );
12632      flag[i] = newTemp( Ity_I8 );
12633      assign( cnt[i],
12634              binop( Iop_Add8,
12635                     mkexpr( cnt[i-1] ),
12636                     binop(Iop_And8,
12637                           unop( Iop_1Uto8,
12638                                 binop(Iop_CmpEQ32,
12639                                       binop(Iop_And32,
12640                                             string,
12641                                             mkU32( 0xF <<
12642                                                    ( ( digits - i ) * 4) ) ),
12643                                       mkU32( 0 ) ) ),
12644                           binop( Iop_Xor8, /* complement flag */
12645                                  mkexpr( flag[i - 1] ),
12646                                  mkU8( 0xFF ) ) ) ) );
12647
12648      /* set flag to 1 if digit was not a zero */
12649      assign( flag[i],
12650              binop(Iop_Or8,
12651                    unop( Iop_1Sto8,
12652                          binop(Iop_CmpNE32,
12653                                binop(Iop_And32,
12654                                      string,
12655                                      mkU32( 0xF <<
12656                                             ( (digits - i) * 4) ) ),
12657                                mkU32( 0 ) ) ),
12658                    mkexpr( flag[i - 1] ) ) );
12659   }
12660
12661   *final_cnt = cnt[digits];
12662   *final_flag = flag[digits];
12663}
12664
12665static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
12666                                        IRExpr * low_32 )
12667{
12668   IRTemp num_lmd    = newTemp( Ity_I8 );
12669   IRTemp num_upper  = newTemp( Ity_I8 );
12670   IRTemp num_low    = newTemp( Ity_I8 );
12671   IRTemp lmd_flag   = newTemp( Ity_I8 );
12672   IRTemp upper_flag = newTemp( Ity_I8 );
12673   IRTemp low_flag   = newTemp( Ity_I8 );
12674
12675   assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
12676   assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
12677
12678   Count_zeros( 2,
12679                mkexpr( num_lmd ),
12680                mkexpr( lmd_flag ),
12681                &num_upper,
12682                &upper_flag,
12683                upper_28 );
12684
12685   Count_zeros( 1,
12686                mkexpr( num_upper ),
12687                mkexpr( upper_flag ),
12688                &num_low,
12689                &low_flag,
12690                low_32 );
12691
12692   return mkexpr( num_low );
12693}
12694
12695static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
12696                                         IRExpr * mid_60_u, IRExpr * mid_60_l,
12697                                         IRExpr * low_60_u, IRExpr * low_60_l)
12698{
12699   IRTemp num_lmd   = newTemp( Ity_I8 );
12700   IRTemp num_top   = newTemp( Ity_I8 );
12701   IRTemp num_mid_u = newTemp( Ity_I8 );
12702   IRTemp num_mid_l = newTemp( Ity_I8 );
12703   IRTemp num_low_u = newTemp( Ity_I8 );
12704   IRTemp num_low_l = newTemp( Ity_I8 );
12705
12706   IRTemp lmd_flag   = newTemp( Ity_I8 );
12707   IRTemp top_flag   = newTemp( Ity_I8 );
12708   IRTemp mid_u_flag = newTemp( Ity_I8 );
12709   IRTemp mid_l_flag = newTemp( Ity_I8 );
12710   IRTemp low_u_flag = newTemp( Ity_I8 );
12711   IRTemp low_l_flag = newTemp( Ity_I8 );
12712
12713   /* Check the LMD, digit 34, to see if it is zero. */
12714   assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
12715
12716   assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
12717
12718   Count_zeros( 6,
12719                mkexpr( num_lmd ),
12720                mkexpr( lmd_flag ),
12721                &num_top,
12722                &top_flag,
12723                top_12_l );
12724
12725   Count_zeros( 2,
12726                mkexpr( num_top ),
12727                mkexpr( top_flag ),
12728                &num_mid_u,
12729                &mid_u_flag,
12730                binop( Iop_Or32,
12731                       binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
12732                       binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
12733
12734   Count_zeros( 1,
12735                mkexpr( num_mid_u ),
12736                mkexpr( mid_u_flag ),
12737                &num_mid_l,
12738                &mid_l_flag,
12739                mid_60_l );
12740
12741   Count_zeros( 2,
12742                mkexpr( num_mid_l ),
12743                mkexpr( mid_l_flag ),
12744                &num_low_u,
12745                &low_u_flag,
12746                binop( Iop_Or32,
12747                       binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
12748                       binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
12749
12750   Count_zeros( 1,
12751                mkexpr( num_low_u ),
12752                mkexpr( low_u_flag ),
12753                &num_low_l,
12754                &low_l_flag,
12755                low_60_l );
12756
12757   return mkexpr( num_low_l );
12758}
12759
12760static IRExpr * Check_unordered(IRExpr * val)
12761{
12762   IRTemp gfield0to5 = newTemp( Ity_I32 );
12763
12764   /* Extract G[0:4] */
12765   assign( gfield0to5,
12766           binop( Iop_And32,
12767                  binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
12768                  mkU32( 0x1F ) ) );
12769
12770   /* Check for unordered, return all 1'x if true */
12771   return binop( Iop_Or32, /* QNaN check */
12772                 unop( Iop_1Sto32,
12773                       binop( Iop_CmpEQ32,
12774                              mkexpr( gfield0to5 ),
12775                              mkU32( 0x1E ) ) ),
12776                 unop( Iop_1Sto32, /* SNaN check */
12777                       binop( Iop_CmpEQ32,
12778                              mkexpr( gfield0to5 ),
12779                              mkU32( 0x1F ) ) ) );
12780}
12781
12782#undef AND
12783#undef AND4
12784#undef OR
12785#undef OR3
12786#undef OR4
12787#undef NOT
12788#undef SHR
12789#undef SHL
12790#undef BITS5
12791
12792/*------------------------------------------------------------*/
12793/*--- Decimal Floating Point (DFP) instruction translation ---*/
12794/*------------------------------------------------------------*/
12795
12796/* DFP Arithmetic instructions */
12797static Bool dis_dfp_arith(UInt theInstr)
12798{
12799   UInt opc2 = ifieldOPClo10( theInstr );
12800   UChar frS_addr = ifieldRegDS( theInstr );
12801   UChar frA_addr = ifieldRegA( theInstr );
12802   UChar frB_addr = ifieldRegB( theInstr );
12803   UChar flag_rC = ifieldBIT0( theInstr );
12804
12805   IRTemp frA = newTemp( Ity_D64 );
12806   IRTemp frB = newTemp( Ity_D64 );
12807   IRTemp frS = newTemp( Ity_D64 );
12808   IRExpr* round = get_IR_roundingmode_DFP();
12809
12810   /* By default, if flag_RC is set, we will clear cr1 after the
12811    * operation.  In reality we should set cr1 to indicate the
12812    * exception status of the operation, but since we're not
12813    * simulating exceptions, the exception status will appear to be
12814    * zero.  Hence cr1 should be cleared if this is a . form insn.
12815    */
12816   Bool clear_CR1 = True;
12817
12818   assign( frA, getDReg( frA_addr ) );
12819   assign( frB, getDReg( frB_addr ) );
12820
12821   switch (opc2) {
12822   case 0x2: // dadd
12823      DIP( "dadd%s fr%u,fr%u,fr%u\n",
12824           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12825      assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
12826      break;
12827   case 0x202: // dsub
12828      DIP( "dsub%s fr%u,fr%u,fr%u\n",
12829           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12830      assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
12831      break;
12832   case 0x22: // dmul
12833      DIP( "dmul%s fr%u,fr%u,fr%u\n",
12834           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12835      assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
12836      break;
12837   case 0x222: // ddiv
12838      DIP( "ddiv%s fr%u,fr%u,fr%u\n",
12839           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12840      assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
12841      break;
12842   }
12843
12844   putDReg( frS_addr, mkexpr( frS ) );
12845
12846   if (flag_rC && clear_CR1) {
12847      putCR321( 1, mkU8( 0 ) );
12848      putCR0( 1, mkU8( 0 ) );
12849   }
12850
12851   return True;
12852}
12853
12854/* Quad DFP Arithmetic instructions */
12855static Bool dis_dfp_arithq(UInt theInstr)
12856{
12857   UInt opc2 = ifieldOPClo10( theInstr );
12858   UChar frS_addr = ifieldRegDS( theInstr );
12859   UChar frA_addr = ifieldRegA( theInstr );
12860   UChar frB_addr = ifieldRegB( theInstr );
12861   UChar flag_rC = ifieldBIT0( theInstr );
12862
12863   IRTemp frA = newTemp( Ity_D128 );
12864   IRTemp frB = newTemp( Ity_D128 );
12865   IRTemp frS = newTemp( Ity_D128 );
12866   IRExpr* round = get_IR_roundingmode_DFP();
12867
12868   /* By default, if flag_RC is set, we will clear cr1 after the
12869    * operation.  In reality we should set cr1 to indicate the
12870    * exception status of the operation, but since we're not
12871    * simulating exceptions, the exception status will appear to be
12872    * zero.  Hence cr1 should be cleared if this is a . form insn.
12873    */
12874   Bool clear_CR1 = True;
12875
12876   assign( frA, getDReg_pair( frA_addr ) );
12877   assign( frB, getDReg_pair( frB_addr ) );
12878
12879   switch (opc2) {
12880   case 0x2: // daddq
12881      DIP( "daddq%s fr%u,fr%u,fr%u\n",
12882           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12883      assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
12884      break;
12885   case 0x202: // dsubq
12886      DIP( "dsubq%s fr%u,fr%u,fr%u\n",
12887           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12888      assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
12889      break;
12890   case 0x22: // dmulq
12891      DIP( "dmulq%s fr%u,fr%u,fr%u\n",
12892           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12893      assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
12894      break;
12895   case 0x222: // ddivq
12896      DIP( "ddivq%s fr%u,fr%u,fr%u\n",
12897           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12898      assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
12899      break;
12900   }
12901
12902   putDReg_pair( frS_addr, mkexpr( frS ) );
12903
12904   if (flag_rC && clear_CR1) {
12905      putCR321( 1, mkU8( 0 ) );
12906      putCR0( 1, mkU8( 0 ) );
12907   }
12908
12909   return True;
12910}
12911
12912/* DFP 64-bit logical shift instructions  */
12913static Bool dis_dfp_shift(UInt theInstr) {
12914   UInt opc2       = ifieldOPClo9( theInstr );
12915   UChar frS_addr  = ifieldRegDS( theInstr );
12916   UChar frA_addr  = ifieldRegA( theInstr );
12917   UChar shift_val = IFIELD(theInstr, 10, 6);
12918   UChar flag_rC   = ifieldBIT0( theInstr );
12919
12920   IRTemp frA = newTemp( Ity_D64 );
12921   IRTemp frS = newTemp( Ity_D64 );
12922   Bool clear_CR1 = True;
12923
12924   assign( frA, getDReg( frA_addr ) );
12925
12926   switch (opc2) {
12927   case 0x42: // dscli
12928      DIP( "dscli%s fr%u,fr%u,%u\n",
12929           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
12930      assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
12931      break;
12932   case 0x62: // dscri
12933      DIP( "dscri%s fr%u,fr%u,%u\n",
12934           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
12935      assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
12936      break;
12937   }
12938
12939   putDReg( frS_addr, mkexpr( frS ) );
12940
12941   if (flag_rC && clear_CR1) {
12942      putCR321( 1, mkU8( 0 ) );
12943      putCR0( 1, mkU8( 0 ) );
12944   }
12945
12946   return True;
12947}
12948
12949/* Quad DFP  logical shift instructions  */
12950static Bool dis_dfp_shiftq(UInt theInstr) {
12951   UInt opc2       = ifieldOPClo9( theInstr );
12952   UChar frS_addr  = ifieldRegDS( theInstr );
12953   UChar frA_addr  = ifieldRegA( theInstr );
12954   UChar shift_val = IFIELD(theInstr, 10, 6);
12955   UChar flag_rC   = ifieldBIT0( theInstr );
12956
12957   IRTemp frA = newTemp( Ity_D128 );
12958   IRTemp frS = newTemp( Ity_D128 );
12959   Bool clear_CR1 = True;
12960
12961   assign( frA, getDReg_pair( frA_addr ) );
12962
12963   switch (opc2) {
12964   case 0x42: // dscliq
12965      DIP( "dscliq%s fr%u,fr%u,%u\n",
12966           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
12967      assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
12968      break;
12969   case 0x62: // dscriq
12970      DIP( "dscriq%s fr%u,fr%u,%u\n",
12971           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
12972      assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
12973      break;
12974   }
12975
12976   putDReg_pair( frS_addr, mkexpr( frS ) );
12977
12978   if (flag_rC && clear_CR1) {
12979      putCR321( 1, mkU8( 0 ) );
12980      putCR0( 1, mkU8( 0 ) );
12981   }
12982
12983   return True;
12984}
12985
12986/* DFP 64-bit format conversion instructions */
12987static Bool dis_dfp_fmt_conv(UInt theInstr) {
12988   UInt opc2      = ifieldOPClo10( theInstr );
12989   UChar frS_addr = ifieldRegDS( theInstr );
12990   UChar frB_addr = ifieldRegB( theInstr );
12991   IRExpr* round  = get_IR_roundingmode_DFP();
12992   UChar flag_rC  = ifieldBIT0( theInstr );
12993   IRTemp frB;
12994   IRTemp frS;
12995   Bool clear_CR1 = True;
12996
12997   switch (opc2) {
12998   case 0x102: //dctdp
12999      DIP( "dctdp%s fr%u,fr%u\n",
13000           flag_rC ? ".":"", frS_addr, frB_addr );
13001
13002      frB = newTemp( Ity_D32 );
13003      frS = newTemp( Ity_D64 );
13004      assign( frB, getDReg32( frB_addr ) );
13005      assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
13006      putDReg( frS_addr, mkexpr( frS ) );
13007      break;
13008   case 0x302: // drsp
13009      DIP( "drsp%s fr%u,fr%u\n",
13010           flag_rC ? ".":"", frS_addr, frB_addr );
13011      frB = newTemp( Ity_D64 );
13012      frS = newTemp( Ity_D32 );
13013      assign( frB, getDReg( frB_addr ) );
13014      assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
13015      putDReg32( frS_addr, mkexpr( frS ) );
13016      break;
13017   case 0x122: // dctfix
13018      {
13019         IRTemp tmp = newTemp( Ity_I64 );
13020
13021         DIP( "dctfix%s fr%u,fr%u\n",
13022              flag_rC ? ".":"", frS_addr, frB_addr );
13023         frB = newTemp( Ity_D64 );
13024         frS = newTemp( Ity_D64 );
13025         assign( frB, getDReg( frB_addr ) );
13026         assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
13027         assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
13028         putDReg( frS_addr, mkexpr( frS ) );
13029      }
13030      break;
13031   case 0x322: // dcffix
13032      DIP( "dcffix%s fr%u,fr%u\n",
13033           flag_rC ? ".":"", frS_addr, frB_addr );
13034      frB = newTemp( Ity_D64 );
13035      frS = newTemp( Ity_D64 );
13036      assign( frB, getDReg( frB_addr ) );
13037      assign( frS, binop( Iop_I64StoD64,
13038                          round,
13039                          unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
13040      putDReg( frS_addr, mkexpr( frS ) );
13041      break;
13042   }
13043
13044   if (flag_rC && clear_CR1) {
13045      putCR321( 1, mkU8( 0 ) );
13046      putCR0( 1, mkU8( 0 ) );
13047   }
13048
13049   return True;
13050}
13051
13052/* Quad DFP format conversion instructions */
13053static Bool dis_dfp_fmt_convq(UInt theInstr) {
13054   UInt opc2      = ifieldOPClo10( theInstr );
13055   UChar frS_addr = ifieldRegDS( theInstr );
13056   UChar frB_addr = ifieldRegB( theInstr );
13057   IRExpr* round  = get_IR_roundingmode_DFP();
13058   IRTemp frB64   = newTemp( Ity_D64 );
13059   IRTemp frB128  = newTemp( Ity_D128 );
13060   IRTemp frS64   = newTemp( Ity_D64 );
13061   IRTemp frS128  = newTemp( Ity_D128 );
13062   UChar flag_rC  = ifieldBIT0( theInstr );
13063   Bool clear_CR1 = True;
13064
13065   switch (opc2) {
13066   case 0x102: // dctqpq
13067      DIP( "dctqpq%s fr%u,fr%u\n",
13068           flag_rC ? ".":"", frS_addr, frB_addr );
13069      assign( frB64, getDReg( frB_addr ) );
13070      assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
13071      putDReg_pair( frS_addr, mkexpr( frS128 ) );
13072      break;
13073   case 0x122: // dctfixq
13074      {
13075         IRTemp tmp = newTemp( Ity_I64 );
13076
13077         DIP( "dctfixq%s fr%u,fr%u\n",
13078              flag_rC ? ".":"", frS_addr, frB_addr );
13079         assign( frB128, getDReg_pair( frB_addr ) );
13080         assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
13081         assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
13082         putDReg( frS_addr, mkexpr( frS64 ) );
13083      }
13084      break;
13085   case 0x302: //drdpq
13086      DIP( "drdpq%s fr%u,fr%u\n",
13087           flag_rC ? ".":"", frS_addr, frB_addr );
13088      assign( frB128, getDReg_pair( frB_addr ) );
13089      assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
13090      putDReg( frS_addr, mkexpr( frS64 ) );
13091      break;
13092   case 0x322: // dcffixq
13093     {
13094      /* Have to introduce an IOP for this instruction so it will work
13095       * on POWER 6 because emulating the instruction requires a POWER 7
13096       * DFP instruction in the emulation code.
13097       */
13098      DIP( "dcffixq%s fr%u,fr%u\n",
13099           flag_rC ? ".":"", frS_addr, frB_addr );
13100      assign( frB64, getDReg( frB_addr ) );
13101      assign( frS128, unop( Iop_I64StoD128,
13102                            unop( Iop_ReinterpD64asI64,
13103                                  mkexpr( frB64 ) ) ) );
13104      putDReg_pair( frS_addr, mkexpr( frS128 ) );
13105      break;
13106     }
13107   }
13108
13109   if (flag_rC && clear_CR1) {
13110      putCR321( 1, mkU8( 0 ) );
13111      putCR0( 1, mkU8( 0 ) );
13112   }
13113
13114   return True;
13115}
13116
13117static Bool dis_dfp_round( UInt theInstr ) {
13118   UChar frS_addr = ifieldRegDS(theInstr);
13119   UChar R        = IFIELD(theInstr, 16, 1);
13120   UChar RMC      = IFIELD(theInstr, 9, 2);
13121   UChar frB_addr = ifieldRegB( theInstr );
13122   UChar flag_rC  = ifieldBIT0( theInstr );
13123   IRTemp frB     = newTemp( Ity_D64 );
13124   IRTemp frS     = newTemp( Ity_D64 );
13125   UInt opc2      = ifieldOPClo8( theInstr );
13126   Bool clear_CR1 = True;
13127
13128   switch (opc2) {
13129   /* drintn, is the same as drintx.  The only difference is this
13130    * instruction does not generate an exception for an inexact operation.
13131    * Currently not supporting inexact exceptions.
13132    */
13133   case 0x63: // drintx
13134   case 0xE3: // drintn
13135      DIP( "drintx/drintn%s fr%u,fr%u\n",
13136           flag_rC ? ".":"", frS_addr, frB_addr );
13137
13138      /* NOTE, this instruction takes a DFP value and rounds to the
13139       * neares floating point integer value, i.e. fractional part
13140       * is zero.  The result is a floating point number.
13141       */
13142      /* pass the value of R and RMC in the same field */
13143      assign( frB, getDReg( frB_addr ) );
13144      assign( frS, binop( Iop_RoundD64toInt,
13145                          mkU32( ( R << 3 ) | RMC ),
13146                          mkexpr( frB ) ) );
13147      putDReg( frS_addr, mkexpr( frS ) );
13148      break;
13149   default:
13150      vex_printf("dis_dfp_round(ppc)(opc2)\n");
13151      return False;
13152   }
13153
13154   if (flag_rC && clear_CR1) {
13155      putCR321( 1, mkU8( 0 ) );
13156      putCR0( 1, mkU8( 0 ) );
13157   }
13158
13159   return True;
13160}
13161
13162static Bool dis_dfp_roundq(UInt theInstr) {
13163   UChar frS_addr = ifieldRegDS( theInstr );
13164   UChar frB_addr = ifieldRegB( theInstr );
13165   UChar R = IFIELD(theInstr, 16, 1);
13166   UChar RMC = IFIELD(theInstr, 9, 2);
13167   UChar flag_rC = ifieldBIT0( theInstr );
13168   IRTemp frB = newTemp( Ity_D128 );
13169   IRTemp frS = newTemp( Ity_D128 );
13170   Bool clear_CR1 = True;
13171   UInt opc2 = ifieldOPClo8( theInstr );
13172
13173   switch (opc2) {
13174   /* drintnq, is the same as drintxq.  The only difference is this
13175    * instruction does not generate an exception for an inexact operation.
13176    * Currently not supporting inexact exceptions.
13177    */
13178   case 0x63: // drintxq
13179   case 0xE3: // drintnq
13180      DIP( "drintxq/drintnq%s fr%u,fr%u\n",
13181           flag_rC ? ".":"", frS_addr, frB_addr );
13182
13183      /* pass the value of R and RMC in the same field */
13184      assign( frB, getDReg_pair( frB_addr ) );
13185      assign( frS, binop( Iop_RoundD128toInt,
13186                          mkU32( ( R << 3 ) | RMC ),
13187                          mkexpr( frB ) ) );
13188      putDReg_pair( frS_addr, mkexpr( frS ) );
13189      break;
13190   default:
13191      vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
13192      return False;
13193   }
13194
13195   if (flag_rC && clear_CR1) {
13196      putCR321( 1, mkU8( 0 ) );
13197      putCR0( 1, mkU8( 0 ) );
13198   }
13199
13200   return True;
13201}
13202
13203static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
13204   UInt opc2 = ifieldOPClo8( theInstr );
13205   UChar frS_addr = ifieldRegDS( theInstr );
13206   UChar frA_addr = ifieldRegA( theInstr );
13207   UChar frB_addr = ifieldRegB( theInstr );
13208   UChar flag_rC = ifieldBIT0( theInstr );
13209   UInt TE_value = IFIELD(theInstr, 16, 4);
13210   UInt TE_sign  = IFIELD(theInstr, 20, 1);
13211   UInt RMC = IFIELD(theInstr, 9, 2);
13212   IRTemp frA = newTemp( Ity_D64 );
13213   IRTemp frB = newTemp( Ity_D64 );
13214   IRTemp frS = newTemp( Ity_D64 );
13215   Bool clear_CR1 = True;
13216
13217   assign( frB, getDReg( frB_addr ) );
13218
13219   switch (opc2) {
13220   case 0x43: // dquai
13221      DIP( "dquai%s fr%u,fr%u,fr%u\n",
13222           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13223      IRTemp TE_I64 = newTemp( Ity_I64 );
13224
13225      /* Generate a reference DFP value frA with the desired exponent
13226       * given by TE using significand from frB.  Need to add the bias
13227       * 398 to TE.  TE is stored as a 2's complement number.
13228       */
13229      if (TE_sign == 1) {
13230         /* Take 2's complement of the 5-bit value and subtract from bias.
13231          *  Bias is adjusted for the +1 required when taking 2's complement.
13232          */
13233         assign( TE_I64,
13234                 unop( Iop_32Uto64,
13235                       binop( Iop_Sub32, mkU32( 397 ),
13236                              binop( Iop_And32, mkU32( 0xF ),
13237                                     unop( Iop_Not32, mkU32( TE_value ) )
13238                                     ) ) ) );
13239
13240      } else {
13241          assign( TE_I64,
13242                  unop( Iop_32Uto64,
13243                        binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
13244                        ) );
13245      }
13246
13247      assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
13248                          unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
13249
13250      assign( frS, triop( Iop_QuantizeD64,
13251                          mkU32( RMC ),
13252                          mkexpr( frA ),
13253                          mkexpr( frB ) ) );
13254      break;
13255
13256   case 0x3: // dqua
13257      DIP( "dqua%s fr%u,fr%u,fr%u\n",
13258           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13259      assign( frA, getDReg( frA_addr ) );
13260      assign( frS, triop( Iop_QuantizeD64,
13261                          mkU32( RMC ),
13262                          mkexpr( frA ),
13263                          mkexpr( frB ) ) );
13264      break;
13265   case 0x23: // drrnd
13266      {
13267         IRTemp tmp = newTemp( Ity_I8 );
13268
13269         DIP( "drrnd%s fr%u,fr%u,fr%u\n",
13270              flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13271         assign( frA, getDReg( frA_addr ) );
13272         /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
13273         assign( tmp, unop( Iop_32to8,
13274                            unop( Iop_64to32,
13275                                  unop( Iop_ReinterpD64asI64,
13276                                        mkexpr( frA ) ) ) ) );
13277         assign( frS, triop( Iop_SignificanceRoundD64,
13278                             mkU32( RMC ),
13279                             mkexpr( tmp ),
13280                             mkexpr( frB ) ) );
13281      }
13282      break;
13283   default:
13284      vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
13285      return False;
13286   }
13287   putDReg( frS_addr, mkexpr( frS ) );
13288
13289   if (flag_rC && clear_CR1) {
13290      putCR321( 1, mkU8( 0 ) );
13291      putCR0( 1, mkU8( 0 ) );
13292   }
13293
13294   return True;
13295}
13296
13297static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
13298   UInt opc2 = ifieldOPClo8( theInstr );
13299   UChar frS_addr = ifieldRegDS( theInstr );
13300   UChar frA_addr = ifieldRegA( theInstr );
13301   UChar frB_addr = ifieldRegB( theInstr );
13302   UChar flag_rC = ifieldBIT0( theInstr );
13303   UInt TE_value = IFIELD(theInstr, 16, 4);
13304   UInt TE_sign  = IFIELD(theInstr, 20, 1);
13305   UInt RMC = IFIELD(theInstr, 9, 2);
13306   IRTemp frA = newTemp( Ity_D128 );
13307   IRTemp frB = newTemp( Ity_D128 );
13308   IRTemp frS = newTemp( Ity_D128 );
13309   Bool clear_CR1 = True;
13310
13311   assign( frB, getDReg_pair( frB_addr ) );
13312
13313   switch (opc2) {
13314   case 0x43: // dquaiq
13315      DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
13316           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13317      IRTemp TE_I64 = newTemp( Ity_I64 );
13318
13319      /* Generate a reference DFP value frA with the desired exponent
13320       * given by TE using significand of 1.  Need to add the bias
13321       * 6176 to TE.
13322       */
13323      if (TE_sign == 1) {
13324         /* Take 2's complement of the 5-bit value and subtract from bias.
13325          *  Bias adjusted for the +1 required when taking 2's complement.
13326          */
13327         assign( TE_I64,
13328                 unop( Iop_32Uto64,
13329                       binop( Iop_Sub32, mkU32( 6175 ),
13330                              binop( Iop_And32, mkU32( 0xF ),
13331                                     unop( Iop_Not32, mkU32( TE_value ) )
13332                                     ) ) ) );
13333
13334      } else {
13335         assign( TE_I64,
13336                 unop( Iop_32Uto64,
13337                       binop( Iop_Add32,
13338                             mkU32( 6176 ),
13339                             mkU32( TE_value ) ) ) );
13340      }
13341
13342      assign( frA,
13343              binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
13344                     unop( Iop_D64toD128,
13345                           unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
13346      assign( frS, triop( Iop_QuantizeD128,
13347                          mkU32( RMC ),
13348                          mkexpr( frA ),
13349                          mkexpr( frB ) ) );
13350      break;
13351   case 0x3: // dquaq
13352      DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
13353           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13354      assign( frA, getDReg_pair( frA_addr ) );
13355      assign( frS, triop( Iop_QuantizeD128,
13356                          mkU32( RMC ),
13357                          mkexpr( frA ),
13358                          mkexpr( frB ) ) );
13359      break;
13360   case 0x23: // drrndq
13361      {
13362         IRTemp tmp = newTemp( Ity_I8 );
13363
13364         DIP( "drrndq%s fr%u,fr%u,fr%u\n",
13365              flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13366         assign( frA, getDReg_pair( frA_addr ) );
13367         assign( tmp, unop( Iop_32to8,
13368                            unop( Iop_64to32,
13369                                  unop( Iop_ReinterpD64asI64,
13370                                        unop( Iop_D128HItoD64,
13371                                              mkexpr( frA ) ) ) ) ) );
13372         assign( frS, triop( Iop_SignificanceRoundD128,
13373                             mkU32( RMC ),
13374                             mkexpr( tmp ),
13375                             mkexpr( frB ) ) );
13376      }
13377      break;
13378   default:
13379      vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
13380      return False;
13381   }
13382   putDReg_pair( frS_addr, mkexpr( frS ) );
13383
13384   if (flag_rC && clear_CR1) {
13385      putCR321( 1, mkU8( 0 ) );
13386      putCR0( 1, mkU8( 0 ) );
13387   }
13388
13389   return True;
13390}
13391
13392static Bool dis_dfp_extract_insert(UInt theInstr) {
13393   UInt opc2 = ifieldOPClo10( theInstr );
13394   UChar frS_addr = ifieldRegDS( theInstr );
13395   UChar frA_addr = ifieldRegA( theInstr );
13396   UChar frB_addr = ifieldRegB( theInstr );
13397   UChar flag_rC = ifieldBIT0( theInstr );
13398   Bool clear_CR1 = True;
13399
13400   IRTemp frA = newTemp( Ity_D64 );
13401   IRTemp frB = newTemp( Ity_D64 );
13402   IRTemp frS = newTemp( Ity_D64 );
13403   IRTemp tmp = newTemp( Ity_I64 );
13404
13405   assign( frA, getDReg( frA_addr ) );
13406   assign( frB, getDReg( frB_addr ) );
13407
13408   switch (opc2) {
13409   case 0x162: // dxex
13410      DIP( "dxex%s fr%u,fr%u,fr%u\n",
13411           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13412      assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
13413      assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
13414      break;
13415   case 0x362: // diex
13416      DIP( "diex%s fr%u,fr%u,fr%u\n",
13417           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13418      assign( frS, binop( Iop_InsertExpD64,
13419                          unop( Iop_ReinterpD64asI64,
13420                                mkexpr( frA ) ),
13421                          mkexpr( frB ) ) );
13422      break;
13423   default:
13424      vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
13425      return False;
13426   }
13427
13428   putDReg( frS_addr, mkexpr( frS ) );
13429
13430   if (flag_rC && clear_CR1) {
13431      putCR321( 1, mkU8( 0 ) );
13432      putCR0( 1, mkU8( 0 ) );
13433   }
13434
13435   return True;
13436}
13437
13438static Bool dis_dfp_extract_insertq(UInt theInstr) {
13439   UInt opc2 = ifieldOPClo10( theInstr );
13440   UChar frS_addr = ifieldRegDS( theInstr );
13441   UChar frA_addr = ifieldRegA( theInstr );
13442   UChar frB_addr = ifieldRegB( theInstr );
13443   UChar flag_rC = ifieldBIT0( theInstr );
13444
13445   IRTemp frA   = newTemp( Ity_D64 );
13446   IRTemp frB   = newTemp( Ity_D128 );
13447   IRTemp frS64 = newTemp( Ity_D64 );
13448   IRTemp frS   = newTemp( Ity_D128 );
13449   IRTemp tmp   = newTemp( Ity_I64 );
13450   Bool clear_CR1 = True;
13451
13452   assign( frB, getDReg_pair( frB_addr ) );
13453
13454   switch (opc2) {
13455   case 0x162:  // dxexq
13456      DIP( "dxexq%s fr%u,fr%u\n",
13457           flag_rC ? ".":"", frS_addr,  frB_addr );
13458      /* Instruction actually returns a 64-bit result.  So as to be
13459       * consistent and not have to add a new struct, the emulation returns
13460       * the 64-bit result in the upper and lower register.
13461       */
13462      assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
13463      assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
13464      putDReg( frS_addr, mkexpr( frS64 ) );
13465      break;
13466   case 0x362:  // diexq
13467      DIP( "diexq%s fr%u,fr%u,fr%u\n",
13468           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13469      assign( frA, getDReg( frA_addr ) );
13470      assign( frS, binop( Iop_InsertExpD128,
13471                          unop( Iop_ReinterpD64asI64, mkexpr( frA ) ),
13472                          mkexpr( frB ) ) );
13473      putDReg_pair( frS_addr, mkexpr( frS ) );
13474      break;
13475   default:
13476      vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
13477      return False;
13478   }
13479
13480   if (flag_rC && clear_CR1) {
13481      putCR321( 1, mkU8( 0 ) );
13482      putCR0( 1, mkU8( 0 ) );
13483   }
13484
13485   return True;
13486}
13487
13488/* DFP 64-bit comparison instructions */
13489static Bool dis_dfp_compare(UInt theInstr) {
13490   /* X-Form */
13491   UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
13492   UChar frA_addr = ifieldRegA( theInstr );
13493   UChar frB_addr = ifieldRegB( theInstr );
13494   UInt opc1 = ifieldOPC( theInstr );
13495   IRTemp frA;
13496   IRTemp frB;
13497
13498   IRTemp ccIR = newTemp( Ity_I32 );
13499   IRTemp ccPPC32 = newTemp( Ity_I32 );
13500
13501
13502   /* Note: Differences between dcmpu and dcmpo are only in exception
13503    flag settings, which aren't supported anyway. */
13504   switch (opc1) {
13505   case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
13506      DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
13507      frA = newTemp( Ity_D64 );
13508      frB = newTemp( Ity_D64 );
13509
13510      assign( frA, getDReg( frA_addr ) );
13511      assign( frB, getDReg( frB_addr ) );
13512
13513      assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
13514      break;
13515   case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
13516      DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
13517      frA = newTemp( Ity_D128 );
13518      frB = newTemp( Ity_D128 );
13519
13520      assign( frA, getDReg_pair( frA_addr ) );
13521      assign( frB, getDReg_pair( frB_addr ) );
13522      assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
13523      break;
13524   default:
13525      vex_printf("dis_dfp_compare(ppc)(opc2)\n");
13526      return False;
13527   }
13528
13529   /* Map compare result from IR to PPC32 */
13530   /*
13531    FP cmp result | PPC | IR
13532    --------------------------
13533    UN            | 0x1 | 0x45
13534    EQ            | 0x2 | 0x40
13535    GT            | 0x4 | 0x00
13536    LT            | 0x8 | 0x01
13537    */
13538
13539   assign( ccPPC32,
13540           binop( Iop_Shl32,
13541                  mkU32( 1 ),
13542                  unop( Iop_32to8,
13543                        binop( Iop_Or32,
13544                               binop( Iop_And32,
13545                                      unop( Iop_Not32,
13546                                            binop( Iop_Shr32,
13547                                                   mkexpr( ccIR ),
13548                                                   mkU8( 5 ) ) ),
13549                                      mkU32( 2 ) ),
13550                               binop( Iop_And32,
13551                                      binop( Iop_Xor32,
13552                                             mkexpr( ccIR ),
13553                                             binop( Iop_Shr32,
13554                                                    mkexpr( ccIR ),
13555                                                    mkU8( 6 ) ) ),
13556                                      mkU32( 1 ) ) ) ) ) );
13557
13558   putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
13559   putFPCC( mkexpr( ccPPC32 ) );
13560   return True;
13561}
13562
13563/* Test class/group/exponent/significance instructions. */
13564static Bool dis_dfp_exponent_test ( UInt theInstr )
13565{
13566   UChar frA_addr   = ifieldRegA( theInstr );
13567   UChar frB_addr   = ifieldRegB( theInstr );
13568   UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );
13569   IRTemp frA       = newTemp( Ity_D64 );
13570   IRTemp frB       = newTemp( Ity_D64 );
13571   IRTemp frA128    = newTemp( Ity_D128 );
13572   IRTemp frB128    = newTemp( Ity_D128 );
13573   UInt opc1        = ifieldOPC( theInstr );
13574   IRTemp gfield_A  = newTemp( Ity_I32 );
13575   IRTemp gfield_B  = newTemp( Ity_I32 );
13576   IRTemp gfield_mask   = newTemp( Ity_I32 );
13577   IRTemp exponent_A    = newTemp( Ity_I32 );
13578   IRTemp exponent_B    = newTemp( Ity_I32 );
13579   IRTemp A_NaN_true    = newTemp( Ity_I32 );
13580   IRTemp B_NaN_true    = newTemp( Ity_I32 );
13581   IRTemp A_inf_true    = newTemp( Ity_I32 );
13582   IRTemp B_inf_true    = newTemp( Ity_I32 );
13583   IRTemp A_equals_B    = newTemp( Ity_I32 );
13584   IRTemp finite_number = newTemp( Ity_I32 );
13585   IRTemp cc0 = newTemp( Ity_I32 );
13586   IRTemp cc1 = newTemp( Ity_I32 );
13587   IRTemp cc2 = newTemp( Ity_I32 );
13588   IRTemp cc3 = newTemp( Ity_I32 );
13589   IRTemp cc  = newTemp( Ity_I32 );
13590
13591   /* The dtstex and dtstexg instructions only differ in the size of the
13592    * exponent field.  The following switch statement takes care of the size
13593    * specific setup.  Once the value of the exponents, the G-field shift
13594    * and mask is setup the remaining code is identical.
13595    */
13596   switch (opc1) {
13597   case 0x3b: // dtstex       Extended instruction setup
13598      DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
13599      assign( frA, getDReg( frA_addr ) );
13600      assign( frB, getDReg( frB_addr ) );
13601      assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
13602      assign(exponent_A, unop( Iop_64to32,
13603                               unop( Iop_ExtractExpD64,
13604                                     mkexpr( frA ) ) ) );
13605      assign(exponent_B, unop( Iop_64to32,
13606                               unop( Iop_ExtractExpD64,
13607                                     mkexpr( frB ) ) ) );
13608      break;
13609
13610   case 0x3F: //  dtstexq      Quad instruction setup
13611      DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
13612      assign( frA128, getDReg_pair( frA_addr ) );
13613      assign( frB128, getDReg_pair( frB_addr ) );
13614      assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
13615      assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
13616      assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
13617      assign( exponent_A, unop( Iop_64to32,
13618                                unop( Iop_ExtractExpD128,
13619                                      mkexpr( frA128 ) ) ) );
13620      assign( exponent_B, unop( Iop_64to32,
13621                                unop( Iop_ExtractExpD128,
13622                                      mkexpr( frB128 ) ) ) );
13623      break;
13624   default:
13625      vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
13626      return False;
13627   }
13628
13629   /* Extract the Gfield */
13630   assign( gfield_A, binop( Iop_And32,
13631                            mkexpr( gfield_mask ),
13632                            unop( Iop_64HIto32,
13633                                  unop( Iop_ReinterpD64asI64,
13634                                        mkexpr(frA) ) ) ) );
13635
13636   assign( gfield_B, binop( Iop_And32,
13637                            mkexpr( gfield_mask ),
13638                            unop( Iop_64HIto32,
13639                                  unop( Iop_ReinterpD64asI64,
13640                                        mkexpr(frB) ) ) ) );
13641
13642   /* check for NAN */
13643   assign( A_NaN_true, binop(Iop_Or32,
13644                             unop( Iop_1Sto32,
13645                                   binop( Iop_CmpEQ32,
13646                                          mkexpr( gfield_A ),
13647                                          mkU32( 0x7C000000 ) ) ),
13648                             unop( Iop_1Sto32,
13649                                   binop( Iop_CmpEQ32,
13650                                          mkexpr( gfield_A ),
13651                                          mkU32( 0x7E000000 ) )
13652                                   ) ) );
13653   assign( B_NaN_true, binop(Iop_Or32,
13654                             unop( Iop_1Sto32,
13655                                   binop( Iop_CmpEQ32,
13656                                          mkexpr( gfield_B ),
13657                                          mkU32( 0x7C000000 ) ) ),
13658                             unop( Iop_1Sto32,
13659                                   binop( Iop_CmpEQ32,
13660                                          mkexpr( gfield_B ),
13661                                          mkU32( 0x7E000000 ) )
13662                             ) ) );
13663
13664   /* check for infinity */
13665   assign( A_inf_true,
13666           unop( Iop_1Sto32,
13667                 binop( Iop_CmpEQ32,
13668                        mkexpr( gfield_A ),
13669                        mkU32( 0x78000000 ) ) ) );
13670
13671   assign( B_inf_true,
13672           unop( Iop_1Sto32,
13673                 binop( Iop_CmpEQ32,
13674                        mkexpr( gfield_B ),
13675                        mkU32( 0x78000000 ) ) ) );
13676
13677   assign( finite_number,
13678           unop( Iop_Not32,
13679                 binop( Iop_Or32,
13680                        binop( Iop_Or32,
13681                               mkexpr( A_NaN_true ),
13682                               mkexpr( B_NaN_true ) ),
13683                        binop( Iop_Or32,
13684                               mkexpr( A_inf_true ),
13685                               mkexpr( B_inf_true ) ) ) ) );
13686
13687   /* Calculate the condition code bits
13688    * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
13689    * regardless of the value of the comparisons and cc3 is 1.  Otherwise,
13690    * cc0, cc1 and cc0 reflect the results of the comparisons.
13691    */
13692   assign( A_equals_B,
13693           binop( Iop_Or32,
13694                  unop( Iop_1Uto32,
13695                  binop( Iop_CmpEQ32,
13696                         mkexpr( exponent_A ),
13697                         mkexpr( exponent_B ) ) ),
13698                  binop( Iop_Or32,
13699                         binop( Iop_And32,
13700                                mkexpr( A_inf_true ),
13701                                mkexpr( B_inf_true ) ),
13702                         binop( Iop_And32,
13703                                mkexpr( A_NaN_true ),
13704                                mkexpr( B_NaN_true ) ) ) ) );
13705
13706   assign( cc0, binop( Iop_And32,
13707                       mkexpr( finite_number ),
13708                       binop( Iop_Shl32,
13709                              unop( Iop_1Uto32,
13710                                    binop( Iop_CmpLT32U,
13711                                           mkexpr( exponent_A ),
13712                                           mkexpr( exponent_B ) ) ),
13713                                           mkU8( 3 ) ) ) );
13714
13715   assign( cc1, binop( Iop_And32,
13716                       mkexpr( finite_number ),
13717                       binop( Iop_Shl32,
13718                              unop( Iop_1Uto32,
13719                                    binop( Iop_CmpLT32U,
13720                                           mkexpr( exponent_B ),
13721                                           mkexpr( exponent_A ) ) ),
13722                                           mkU8( 2 ) ) ) );
13723
13724   assign( cc2, binop( Iop_Shl32,
13725                       binop( Iop_And32,
13726                              mkexpr( A_equals_B ),
13727                              mkU32( 1 ) ),
13728                              mkU8( 1 ) ) );
13729
13730   assign( cc3, binop( Iop_And32,
13731                       unop( Iop_Not32, mkexpr( A_equals_B ) ),
13732                       binop( Iop_And32,
13733                              mkU32( 0x1 ),
13734                              binop( Iop_Or32,
13735                                     binop( Iop_Or32,
13736                                            mkexpr ( A_inf_true ),
13737                                            mkexpr ( B_inf_true ) ),
13738                                            binop( Iop_Or32,
13739                                                   mkexpr ( A_NaN_true ),
13740                                                   mkexpr ( B_NaN_true ) ) )
13741                              ) ) );
13742
13743   /* store the condition code */
13744   assign( cc, binop( Iop_Or32,
13745                      mkexpr( cc0 ),
13746                      binop( Iop_Or32,
13747                             mkexpr( cc1 ),
13748                             binop( Iop_Or32,
13749                                    mkexpr( cc2 ),
13750                                    mkexpr( cc3 ) ) ) ) );
13751   putGST_field( PPC_GST_CR, mkexpr( cc ), crfD );
13752   putFPCC( mkexpr( cc ) );
13753   return True;
13754}
13755
13756/* Test class/group/exponent/significance instructions. */
13757static Bool dis_dfp_class_test ( UInt theInstr )
13758{
13759   UChar frA_addr   = ifieldRegA( theInstr );
13760   IRTemp frA       = newTemp( Ity_D64 );
13761   IRTemp abs_frA   = newTemp( Ity_D64 );
13762   IRTemp frAI64_hi = newTemp( Ity_I64 );
13763   IRTemp frAI64_lo = newTemp( Ity_I64 );
13764   UInt opc1        = ifieldOPC( theInstr );
13765   UInt opc2        = ifieldOPClo9( theInstr );
13766   UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );  // AKA BF
13767   UInt DCM         = IFIELD( theInstr, 10, 6 );
13768   IRTemp DCM_calc  = newTemp( Ity_I32 );
13769   UInt max_exp     = 0;
13770   UInt min_exp     = 0;
13771   IRTemp min_subnormalD64  = newTemp( Ity_D64 );
13772   IRTemp min_subnormalD128 = newTemp( Ity_D128 );
13773   IRTemp significand64  = newTemp( Ity_D64 );
13774   IRTemp significand128 = newTemp( Ity_D128 );
13775   IRTemp exp_min_normal = newTemp( Ity_I64 );
13776   IRTemp exponent       = newTemp( Ity_I32 );
13777
13778   IRTemp infinity_true  = newTemp( Ity_I32 );
13779   IRTemp SNaN_true      = newTemp( Ity_I32 );
13780   IRTemp QNaN_true      = newTemp( Ity_I32 );
13781   IRTemp subnormal_true = newTemp( Ity_I32 );
13782   IRTemp normal_true    = newTemp( Ity_I32 );
13783   IRTemp extreme_true   = newTemp( Ity_I32 );
13784   IRTemp lmd            = newTemp( Ity_I32 );
13785   IRTemp lmd_zero_true  = newTemp( Ity_I32 );
13786   IRTemp zero_true      = newTemp( Ity_I32 );
13787   IRTemp sign           = newTemp( Ity_I32 );
13788   IRTemp field          = newTemp( Ity_I32 );
13789   IRTemp ccIR_zero      = newTemp( Ity_I32 );
13790   IRTemp ccIR_subnormal = newTemp( Ity_I32 );
13791
13792   /* UInt size     = DFP_LONG;  JRS:unused */
13793   IRTemp gfield = newTemp( Ity_I32 );
13794   IRTemp gfield_0_4_shift  = newTemp( Ity_I8 );
13795   IRTemp gfield_mask       = newTemp( Ity_I32 );
13796   IRTemp dcm0 = newTemp( Ity_I32 );
13797   IRTemp dcm1 = newTemp( Ity_I32 );
13798   IRTemp dcm2 = newTemp( Ity_I32 );
13799   IRTemp dcm3 = newTemp( Ity_I32 );
13800   IRTemp dcm4 = newTemp( Ity_I32 );
13801   IRTemp dcm5 = newTemp( Ity_I32 );
13802
13803   /* The only difference between the dtstdc and dtstdcq instructions is
13804    * size of the T and G fields.  The calculation of the 4 bit field
13805    * is the same.  Setup the parameters and values that are DFP size
13806    * specific.  The rest of the code is independent of the DFP size.
13807    *
13808    * The Io_CmpD64 is used below.  The instruction sets the ccIR values.
13809    * The interpretation of the ccIR values is as follows:
13810    *
13811    *    DFP cmp result | IR
13812    * --------------------------
13813    *	 UN             | 0x45
13814    *	 EQ             | 0x40
13815    *	 GT             | 0x00
13816    *	 LT             | 0x01
13817    */
13818
13819   assign( frA, getDReg( frA_addr ) );
13820   assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
13821
13822   assign( abs_frA, unop( Iop_ReinterpI64asD64,
13823                          binop( Iop_And64,
13824                                 unop( Iop_ReinterpD64asI64,
13825                                       mkexpr( frA ) ),
13826                                 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
13827   assign( gfield_0_4_shift, mkU8( 31 - 5 ) );  // G-field[0:4]
13828   switch (opc1) {
13829   case 0x3b: // dtstdc, dtstdg
13830      DIP("dtstd%s %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
13831               crfD, frA_addr, DCM);
13832      /* setup the parameters for the long format of the two instructions */
13833      assign( frAI64_lo, mkU64( 0 ) );
13834      assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
13835      max_exp = DFP_LONG_EXP_MAX;
13836      min_exp = DFP_LONG_EXP_MIN;
13837
13838      assign( exponent, unop( Iop_64to32,
13839                              unop( Iop_ExtractExpD64,
13840                                    mkexpr( frA ) ) ) );
13841      assign( significand64,
13842              unop( Iop_ReinterpI64asD64,
13843                    mkU64( 0x2234000000000001ULL ) ) );  // dfp 1.0
13844      assign( exp_min_normal,mkU64( 398 - 383 ) );
13845      assign( min_subnormalD64,
13846              binop( Iop_InsertExpD64,
13847                     mkexpr( exp_min_normal ),
13848                     mkexpr( significand64 ) ) );
13849
13850      assign( ccIR_subnormal,
13851              binop( Iop_CmpD64,
13852                     mkexpr( abs_frA ),
13853                     mkexpr( min_subnormalD64 ) ) );
13854
13855      /* compare absolute value of frA with zero */
13856      assign( ccIR_zero,
13857              binop( Iop_CmpD64,
13858                     mkexpr( abs_frA ),
13859                     unop( Iop_ReinterpI64asD64,
13860                           mkU64( 0x2238000000000000ULL ) ) ) );
13861
13862      /* size = DFP_LONG; JRS: unused */
13863      break;
13864
13865   case 0x3F:   // dtstdcq, dtstdgq
13866      DIP("dtstd%sq %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
13867               crfD, frA_addr, DCM);
13868      /* setup the parameters for the extended format of the
13869       * two instructions
13870       */
13871      assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
13872                               getDReg( frA_addr+1 ) ) );
13873
13874      assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
13875      max_exp = DFP_EXTND_EXP_MAX;
13876      min_exp = DFP_EXTND_EXP_MIN;
13877      assign( exponent, unop( Iop_64to32,
13878                              unop( Iop_ExtractExpD128,
13879                                    getDReg_pair( frA_addr) ) ) );
13880
13881      /* create quand exponent for minimum normal number */
13882      assign( exp_min_normal, mkU64( 6176 - 6143 ) );
13883      assign( significand128,
13884              unop( Iop_D64toD128,
13885                    unop( Iop_ReinterpI64asD64,
13886                          mkU64( 0x2234000000000001ULL ) ) ) );  // dfp 1.0
13887
13888      assign( min_subnormalD128,
13889              binop( Iop_InsertExpD128,
13890                     mkexpr( exp_min_normal ),
13891                     mkexpr( significand128 ) ) );
13892
13893      assign( ccIR_subnormal,
13894              binop( Iop_CmpD128,
13895                     binop( Iop_D64HLtoD128,
13896                            unop( Iop_ReinterpI64asD64,
13897                                  binop( Iop_And64,
13898                                         unop( Iop_ReinterpD64asI64,
13899                                               mkexpr( frA ) ),
13900                                         mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
13901                            getDReg( frA_addr+1 ) ),
13902                     mkexpr( min_subnormalD128 ) ) );
13903      assign( ccIR_zero,
13904              binop( Iop_CmpD128,
13905                     binop( Iop_D64HLtoD128,
13906                            mkexpr( abs_frA ),
13907                            getDReg( frA_addr+1 ) ),
13908                     unop( Iop_D64toD128,
13909                           unop( Iop_ReinterpI64asD64,
13910                                 mkU64( 0x0ULL ) ) ) ) );
13911
13912      /* size = DFP_EXTND; JRS:unused */
13913      break;
13914   default:
13915      vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
13916      return False;
13917   }
13918
13919   /* The G-field is in the upper 32-bits.  The I64 logical operations
13920    * do not seem to be supported in 32-bit mode so keep things as 32-bit
13921    * operations.
13922    */
13923   assign( gfield, binop( Iop_And32,
13924                          mkexpr( gfield_mask ),
13925                          unop( Iop_64HIto32,
13926                                mkexpr(frAI64_hi) ) ) );
13927
13928   /* There is a lot of code that is the same to do the class and group
13929    * instructions.  Later there is an if statement to handle the specific
13930    * instruction.
13931    *
13932    * Will be using I32 values, compares, shifts and logical operations for
13933    * this code as the 64-bit compare, shifts, logical operations are not
13934    * supported in 32-bit mode.
13935    */
13936
13937   /* Check the bits for Infinity, QNaN or Signaling NaN */
13938   assign( infinity_true,
13939           unop( Iop_1Sto32,
13940                 binop( Iop_CmpEQ32,
13941                        binop( Iop_And32,
13942                               mkU32( 0x7C000000 ),
13943                               mkexpr( gfield ) ),
13944                        mkU32( 0x78000000 ) ) ) );
13945
13946   assign( SNaN_true,
13947           unop( Iop_1Sto32,
13948                 binop( Iop_CmpEQ32,
13949                        binop( Iop_And32,
13950                               mkU32( 0x7E000000 ),
13951                               mkexpr( gfield ) ),
13952                        mkU32( 0x7E000000 ) ) ) );
13953
13954   assign( QNaN_true,
13955           binop( Iop_And32,
13956                  unop( Iop_1Sto32,
13957                       binop( Iop_CmpEQ32,
13958                              binop( Iop_And32,
13959                                     mkU32( 0x7E000000 ),
13960                                     mkexpr( gfield ) ),
13961                              mkU32( 0x7C000000 ) ) ),
13962                  unop( Iop_Not32,
13963                        mkexpr( SNaN_true ) ) ) );
13964
13965   assign( zero_true,
13966           binop( Iop_And32,
13967                  unop(Iop_1Sto32,
13968                       binop( Iop_CmpEQ32,
13969                              mkexpr( ccIR_zero ),
13970                              mkU32( 0x40 ) ) ),  // ccIR code for Equal
13971                  unop( Iop_Not32,
13972                        binop( Iop_Or32,
13973                               mkexpr( infinity_true ),
13974                               binop( Iop_Or32,
13975                                      mkexpr( QNaN_true ),
13976                                      mkexpr( SNaN_true ) ) ) ) ) );
13977
13978   /* Do compare of frA the minimum normal value.  Comparison is size
13979    * depenent and was done above to get the ccIR value.
13980    */
13981   assign( subnormal_true,
13982           binop( Iop_And32,
13983                  binop( Iop_Or32,
13984                         unop( Iop_1Sto32,
13985                               binop( Iop_CmpEQ32,
13986                                      mkexpr( ccIR_subnormal ),
13987                                      mkU32( 0x40 ) ) ), // ccIR code for Equal
13988                         unop( Iop_1Sto32,
13989                               binop( Iop_CmpEQ32,
13990                                      mkexpr( ccIR_subnormal ),
13991                                      mkU32( 0x1 ) ) ) ), // ccIR code for LT
13992           unop( Iop_Not32,
13993                 binop( Iop_Or32,
13994                        binop( Iop_Or32,
13995                               mkexpr( infinity_true ),
13996                               mkexpr( zero_true) ),
13997                        binop( Iop_Or32,
13998                               mkexpr( QNaN_true ),
13999                               mkexpr( SNaN_true ) ) ) ) ) );
14000
14001   /* Normal number is not subnormal, infinity, NaN or Zero */
14002   assign( normal_true,
14003           unop( Iop_Not32,
14004                 binop( Iop_Or32,
14005                        binop( Iop_Or32,
14006                               mkexpr( infinity_true ),
14007                               mkexpr( zero_true ) ),
14008                        binop( Iop_Or32,
14009                               mkexpr( subnormal_true ),
14010                               binop( Iop_Or32,
14011                                      mkexpr( QNaN_true ),
14012                                      mkexpr( SNaN_true ) ) ) ) ) );
14013
14014   /* Calculate the DCM bit field based on the tests for the specific
14015    * instruction
14016    */
14017   if (opc2 == 0xC2) {    // dtstdc, dtstdcq
14018      /* DCM[0:5] Bit   Data Class definition
14019       *   0   Zero
14020       *   1   Subnormal
14021       *   2   Normal
14022       *   3   Infinity
14023       *   4   Quiet NaN
14024       *   5   Signaling NaN
14025       */
14026
14027      assign( dcm0, binop( Iop_Shl32,
14028                           mkexpr( zero_true ),
14029                           mkU8( 5 ) ) );
14030      assign( dcm1, binop( Iop_Shl32,
14031                           binop( Iop_And32,
14032                                  mkexpr( subnormal_true ),
14033                                  mkU32( 1 ) ),
14034                           mkU8( 4 ) ) );
14035      assign( dcm2, binop( Iop_Shl32,
14036                           binop( Iop_And32,
14037                                  mkexpr( normal_true ),
14038                                  mkU32( 1 ) ),
14039                           mkU8( 3 ) ) );
14040      assign( dcm3, binop( Iop_Shl32,
14041                           binop( Iop_And32,
14042                                  mkexpr( infinity_true),
14043                                  mkU32( 1 ) ),
14044                           mkU8( 2 ) ) );
14045      assign( dcm4, binop( Iop_Shl32,
14046                           binop( Iop_And32,
14047                                  mkexpr( QNaN_true ),
14048                                  mkU32( 1 ) ),
14049                           mkU8( 1 ) ) );
14050      assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
14051
14052   } else if (opc2 == 0xE2) {   // dtstdg, dtstdgq
14053      /* check if the exponent is extreme */
14054      assign( extreme_true, binop( Iop_Or32,
14055                                   unop( Iop_1Sto32,
14056                                         binop( Iop_CmpEQ32,
14057                                                mkexpr( exponent ),
14058                                                mkU32( max_exp ) ) ),
14059                                   unop( Iop_1Sto32,
14060                                         binop( Iop_CmpEQ32,
14061                                                mkexpr( exponent ),
14062                                                mkU32( min_exp ) ) ) ) );
14063
14064      /* Check if LMD is zero */
14065      Get_lmd( &lmd, binop( Iop_Shr32,
14066                            mkexpr( gfield ), mkU8( 31 - 5 ) ) );
14067
14068      assign( lmd_zero_true, unop( Iop_1Sto32,
14069                                   binop( Iop_CmpEQ32,
14070                                          mkexpr( lmd ),
14071                                          mkU32( 0 ) ) ) );
14072
14073      /* DCM[0:5] Bit   Data Class definition
14074       *  0   Zero with non-extreme exponent
14075       *  1   Zero with extreme exponent
14076       *  2   Subnormal or (Normal with extreme exponent)
14077       *  3   Normal with non-extreme exponent and
14078       *      leftmost zero digit in significand
14079       *  4   Normal with non-extreme exponent and
14080       *      leftmost nonzero digit in significand
14081       *  5   Special symbol (Infinity, QNaN, or SNaN)
14082       */
14083      assign( dcm0, binop( Iop_Shl32,
14084                           binop( Iop_And32,
14085                                  binop( Iop_And32,
14086                                         unop( Iop_Not32,
14087                                               mkexpr( extreme_true ) ),
14088                                         mkexpr( zero_true ) ),
14089                                  mkU32( 0x1 ) ),
14090                           mkU8( 5 ) ) );
14091
14092      assign( dcm1, binop( Iop_Shl32,
14093                           binop( Iop_And32,
14094                                  binop( Iop_And32,
14095                                         mkexpr( extreme_true ),
14096                                         mkexpr( zero_true ) ),
14097                                  mkU32( 0x1 ) ),
14098                           mkU8( 4 ) ) );
14099
14100      assign( dcm2, binop( Iop_Shl32,
14101                           binop( Iop_And32,
14102                                  binop( Iop_Or32,
14103                                         binop( Iop_And32,
14104                                                mkexpr( extreme_true ),
14105                                                mkexpr( normal_true ) ),
14106                                         mkexpr( subnormal_true ) ),
14107                                  mkU32( 0x1 ) ),
14108                           mkU8( 3 ) ) );
14109
14110      assign( dcm3, binop( Iop_Shl32,
14111                           binop( Iop_And32,
14112                                  binop( Iop_And32,
14113                                         binop( Iop_And32,
14114                                                unop( Iop_Not32,
14115                                                      mkexpr( extreme_true ) ),
14116                                                      mkexpr( normal_true ) ),
14117                                         unop( Iop_1Sto32,
14118                                               binop( Iop_CmpEQ32,
14119                                                      mkexpr( lmd ),
14120                                                      mkU32( 0 ) ) ) ),
14121                                  mkU32( 0x1 ) ),
14122                           mkU8( 2 ) ) );
14123
14124      assign( dcm4, binop( Iop_Shl32,
14125                           binop( Iop_And32,
14126                                  binop( Iop_And32,
14127                                         binop( Iop_And32,
14128                                                unop( Iop_Not32,
14129                                                      mkexpr( extreme_true ) ),
14130                                                mkexpr( normal_true ) ),
14131                                          unop( Iop_1Sto32,
14132                                                binop( Iop_CmpNE32,
14133                                                       mkexpr( lmd ),
14134                                                       mkU32( 0 ) ) ) ),
14135                                  mkU32( 0x1 ) ),
14136                           mkU8( 1 ) ) );
14137
14138      assign( dcm5, binop( Iop_And32,
14139                           binop( Iop_Or32,
14140                                  mkexpr( SNaN_true),
14141                                  binop( Iop_Or32,
14142                                         mkexpr( QNaN_true),
14143                                         mkexpr( infinity_true) ) ),
14144                           mkU32( 0x1 ) ) );
14145   }
14146
14147   /* create DCM field */
14148   assign( DCM_calc,
14149           binop( Iop_Or32,
14150                  mkexpr( dcm0 ),
14151                  binop( Iop_Or32,
14152                         mkexpr( dcm1 ),
14153                         binop( Iop_Or32,
14154                                mkexpr( dcm2 ),
14155                                binop( Iop_Or32,
14156                                       mkexpr( dcm3 ),
14157                                       binop( Iop_Or32,
14158                                              mkexpr( dcm4 ),
14159                                              mkexpr( dcm5 ) ) ) ) ) ) );
14160
14161   /* Get the sign of the DFP number, ignore sign for QNaN */
14162   assign( sign,
14163           unop( Iop_1Uto32,
14164                 binop( Iop_CmpEQ32,
14165                        binop( Iop_Shr32,
14166                               unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
14167                               mkU8( 63 - 32 ) ),
14168                        mkU32( 1 ) ) ) );
14169
14170   /* This instruction generates a four bit field to be stored in the
14171    * condition code register.  The condition code register consists of 7
14172    * fields.  The field to be written to is specified by the BF (AKA crfD)
14173    * field.
14174    *
14175    * The field layout is as follows:
14176    *
14177    *      Field          Meaning
14178    *      0000           Operand positive with no match
14179    *      0100           Operand positive with at least one match
14180    *      0001           Operand negative with no match
14181    *      0101           Operand negative with at least one match
14182    */
14183   assign( field, binop( Iop_Or32,
14184                         binop( Iop_Shl32,
14185                                mkexpr( sign ),
14186                                mkU8( 3 ) ),
14187                                binop( Iop_Shl32,
14188                                       unop( Iop_1Uto32,
14189                                             binop( Iop_CmpNE32,
14190                                                    binop( Iop_And32,
14191                                                           mkU32( DCM ),
14192                                                           mkexpr( DCM_calc ) ),
14193                                                     mkU32( 0 ) ) ),
14194                                       mkU8( 1 ) ) ) );
14195
14196   putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
14197   putFPCC( mkexpr( field ) );
14198   return True;
14199}
14200
14201static Bool dis_dfp_bcd(UInt theInstr) {
14202   UInt opc2        = ifieldOPClo10( theInstr );
14203   ULong sp         = IFIELD(theInstr, 19, 2);
14204   ULong s          = IFIELD(theInstr, 20, 1);
14205   UChar frT_addr   = ifieldRegDS( theInstr );
14206   UChar frB_addr   = ifieldRegB( theInstr );
14207   IRTemp frB       = newTemp( Ity_D64 );
14208   IRTemp frBI64    = newTemp( Ity_I64 );
14209   IRTemp result    = newTemp( Ity_I64 );
14210   IRTemp resultD64 = newTemp( Ity_D64 );
14211   IRTemp bcd64     = newTemp( Ity_I64 );
14212   IRTemp bcd_u     = newTemp( Ity_I32 );
14213   IRTemp bcd_l     = newTemp( Ity_I32 );
14214   IRTemp dbcd_u    = newTemp( Ity_I32 );
14215   IRTemp dbcd_l    = newTemp( Ity_I32 );
14216   IRTemp lmd       = newTemp( Ity_I32 );
14217
14218   assign( frB, getDReg( frB_addr ) );
14219   assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
14220
14221   switch ( opc2 ) {
14222   case 0x142: // ddedpd   DFP Decode DPD to BCD
14223      DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
14224
14225         assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
14226         assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
14227         assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
14228
14229      if ( ( sp == 0 ) || ( sp == 1 ) ) {
14230         /* Unsigned BCD string */
14231         Get_lmd( &lmd,
14232                  binop( Iop_Shr32,
14233                         unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14234                         mkU8( 31 - 5 ) ) ); // G-field[0:4]
14235
14236         assign( result,
14237                 binop( Iop_32HLto64,
14238                        binop( Iop_Or32,
14239                               binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
14240                               mkexpr( bcd_u ) ),
14241                        mkexpr( bcd_l ) ) );
14242
14243      } else {
14244         /* Signed BCD string, the cases for sp 2 and 3 only differ in how
14245          * the positive and negative values are encoded in the least
14246          * significant bits.
14247          */
14248         IRTemp sign = newTemp( Ity_I32 );
14249
14250         if (sp == 2) {
14251            /* Positive sign = 0xC, negative sign = 0xD */
14252
14253            assign( sign,
14254                    binop( Iop_Or32,
14255                           binop( Iop_Shr32,
14256                                  unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14257                                  mkU8( 31 ) ),
14258                           mkU32( 0xC ) ) );
14259
14260         } else if ( sp == 3 ) {
14261            /* Positive sign = 0xF, negative sign = 0xD */
14262            IRTemp tmp32 = newTemp( Ity_I32 );
14263
14264            /* Complement sign bit then OR into bit position 1 */
14265            assign( tmp32,
14266                    binop( Iop_Xor32,
14267                           binop( Iop_Shr32,
14268                                  unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14269                                  mkU8( 30 ) ),
14270                           mkU32( 0x2 ) ) );
14271
14272            assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
14273
14274         } else {
14275            vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
14276         }
14277
14278         /* Put sign in bottom 4 bits, move most significant 4-bits from
14279          * bcd_l to bcd_u.
14280          */
14281         assign( result,
14282                 binop( Iop_32HLto64,
14283                        binop( Iop_Or32,
14284                               binop( Iop_Shr32,
14285                                      mkexpr( bcd_l ),
14286                                      mkU8( 28 ) ),
14287                               binop( Iop_Shl32,
14288                                      mkexpr( bcd_u ),
14289                                      mkU8( 4 ) ) ),
14290                        binop( Iop_Or32,
14291                                      mkexpr( sign ),
14292                               binop( Iop_Shl32,
14293                                      mkexpr( bcd_l ),
14294                                      mkU8( 4 ) ) ) ) );
14295      }
14296
14297      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
14298      break;
14299
14300   case 0x342: // denbcd   DFP Encode BCD to DPD
14301   {
14302      IRTemp valid_mask   = newTemp( Ity_I32 );
14303      IRTemp invalid_mask = newTemp( Ity_I32 );
14304      IRTemp without_lmd  = newTemp( Ity_I64 );
14305      IRTemp tmp64        = newTemp( Ity_I64 );
14306      IRTemp dbcd64       = newTemp( Ity_I64 );
14307      IRTemp left_exp     = newTemp( Ity_I32 );
14308      IRTemp g0_4         = newTemp( Ity_I32 );
14309
14310      DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
14311
14312      if ( s == 0 ) {
14313         /* Unsigned BCD string */
14314         assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
14315         assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
14316         assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
14317
14318         assign( lmd,
14319                 binop( Iop_Shr32,
14320                        binop( Iop_And32,
14321                               unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14322                               mkU32( 0xF0000000 ) ),
14323                        mkU8( 28 ) ) );
14324
14325         assign( invalid_mask,
14326                 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14327                                  unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
14328         assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
14329
14330         assign( without_lmd,
14331                 unop( Iop_ReinterpD64asI64,
14332                       binop( Iop_InsertExpD64,
14333                              mkU64( DFP_LONG_BIAS ),
14334                              unop( Iop_ReinterpI64asD64,
14335                                    binop( Iop_32HLto64,
14336                                           mkexpr( dbcd_u ),
14337                                           mkexpr( dbcd_l ) ) ) ) ) );
14338         assign( left_exp,
14339                 binop( Iop_Shr32,
14340                        binop( Iop_And32,
14341                               unop( Iop_64HIto32, mkexpr( without_lmd ) ),
14342                               mkU32( 0x60000000 ) ),
14343                        mkU8( 29 ) ) );
14344
14345         assign( g0_4,
14346                 binop( Iop_Shl32,
14347                        Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
14348                        mkU8( 26 ) ) );
14349
14350         assign( tmp64,
14351                 binop( Iop_32HLto64,
14352                        binop( Iop_Or32,
14353                               binop( Iop_And32,
14354                                      unop( Iop_64HIto32,
14355                                            mkexpr( without_lmd ) ),
14356                                      mkU32( 0x83FFFFFF ) ),
14357                               mkexpr( g0_4 ) ),
14358                        unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
14359
14360      } else if ( s == 1 ) {
14361         IRTemp sign = newTemp( Ity_I32 );
14362         IRTemp sign_bit = newTemp( Ity_I32 );
14363         IRTemp pos_sign_mask = newTemp( Ity_I32 );
14364         IRTemp neg_sign_mask = newTemp( Ity_I32 );
14365         IRTemp tmp = newTemp( Ity_I64 );
14366
14367         /* Signed BCD string, least significant 4 bits are sign bits
14368          * positive sign = 0xC, negative sign = 0xD
14369          */
14370         assign( tmp, unop( Iop_BCDtoDPB,
14371                            binop( Iop_32HLto64,
14372                                   binop( Iop_Shr32,
14373                                          unop( Iop_64HIto32,
14374                                                mkexpr( frBI64 ) ),
14375                                                mkU8( 4 ) ),
14376                                   binop( Iop_Or32,
14377                                          binop( Iop_Shr32,
14378                                                 unop( Iop_64to32,
14379                                                       mkexpr( frBI64 ) ),
14380                                                  mkU8( 4 ) ),
14381                                          binop( Iop_Shl32,
14382                                                 unop( Iop_64HIto32,
14383                                                       mkexpr( frBI64 ) ),
14384                                                       mkU8( 28 ) ) ) ) ) );
14385
14386         assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
14387         assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
14388
14389         /* Get the sign of the BCD string. */
14390         assign( sign,
14391                 binop( Iop_And32,
14392                        unop( Iop_64to32, mkexpr( frBI64 ) ),
14393                        mkU32( 0xF ) ) );
14394
14395         assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
14396         assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
14397         assign( sign_bit,
14398                 Generate_sign_bit( mkexpr( pos_sign_mask ),
14399                                    mkexpr( neg_sign_mask ) ) );
14400
14401         /* Check for invalid sign and BCD digit.  Don't check the bottom
14402          * four bits of bcd_l as that is the sign value.
14403          */
14404         assign( invalid_mask,
14405                 Generate_inv_mask(
14406                                   bcd_digit_inval( unop( Iop_64HIto32,
14407                                                          mkexpr( frBI64 ) ),
14408                                                    binop( Iop_Shr32,
14409                                                           unop( Iop_64to32,
14410                                                                 mkexpr( frBI64 ) ),
14411                                                           mkU8( 4 ) ) ),
14412                                   mkexpr( pos_sign_mask ),
14413                                   mkexpr( neg_sign_mask ) ) );
14414
14415         assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
14416
14417         /* Generate the result assuming the sign value was valid. */
14418         assign( tmp64,
14419                 unop( Iop_ReinterpD64asI64,
14420                       binop( Iop_InsertExpD64,
14421                              mkU64( DFP_LONG_BIAS ),
14422                              unop( Iop_ReinterpI64asD64,
14423                                    binop( Iop_32HLto64,
14424                                           binop( Iop_Or32,
14425                                                  mkexpr( dbcd_u ),
14426                                                  mkexpr( sign_bit ) ),
14427                                           mkexpr( dbcd_l ) ) ) ) ) );
14428      }
14429
14430      /* Generate the value to store depending on the validity of the
14431       * sign value and the validity of the BCD digits.
14432       */
14433      assign( resultD64,
14434              unop( Iop_ReinterpI64asD64,
14435                    binop( Iop_32HLto64,
14436                           binop( Iop_Or32,
14437                                  binop( Iop_And32,
14438                                         mkexpr( valid_mask ),
14439                                         unop( Iop_64HIto32,
14440                                               mkexpr( tmp64 ) ) ),
14441                                  binop( Iop_And32,
14442                                         mkU32( 0x7C000000 ),
14443                                         mkexpr( invalid_mask ) ) ),
14444                           binop( Iop_Or32,
14445                                  binop( Iop_And32,
14446                                         mkexpr( valid_mask ),
14447                                         unop( Iop_64to32, mkexpr( tmp64 ) ) ),
14448                                  binop( Iop_And32,
14449                                         mkU32( 0x0 ),
14450                                         mkexpr( invalid_mask ) ) ) ) ) );
14451      putDReg( frT_addr, mkexpr( resultD64 ) );
14452   }
14453   break;
14454   default:
14455      vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
14456      return False;
14457   }
14458   return True;
14459}
14460
14461static Bool dis_dfp_bcdq( UInt theInstr )
14462{
14463   UInt opc2        = ifieldOPClo10( theInstr );
14464   ULong sp         = IFIELD(theInstr, 19, 2);
14465   ULong s          = IFIELD(theInstr, 20, 1);
14466   IRTemp frB_hi    = newTemp( Ity_D64 );
14467   IRTemp frB_lo    = newTemp( Ity_D64 );
14468   IRTemp frBI64_hi = newTemp( Ity_I64 );
14469   IRTemp frBI64_lo = newTemp( Ity_I64 );
14470   UChar frT_addr   = ifieldRegDS( theInstr );
14471   UChar frB_addr   = ifieldRegB( theInstr );
14472
14473   IRTemp lmd       = newTemp( Ity_I32 );
14474   IRTemp result_hi = newTemp( Ity_I64 );
14475   IRTemp result_lo = newTemp( Ity_I64 );
14476
14477   assign( frB_hi, getDReg( frB_addr ) );
14478   assign( frB_lo, getDReg( frB_addr + 1 ) );
14479   assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
14480   assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
14481
14482   switch ( opc2 ) {
14483   case 0x142: // ddedpdq   DFP Decode DPD to BCD
14484   {
14485      IRTemp low_60_u = newTemp( Ity_I32 );
14486      IRTemp low_60_l = newTemp( Ity_I32 );
14487      IRTemp mid_60_u = newTemp( Ity_I32 );
14488      IRTemp mid_60_l = newTemp( Ity_I32 );
14489      IRTemp top_12_l = newTemp( Ity_I32 );
14490
14491      DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
14492
14493      /* Note, instruction only stores the lower 32 BCD digits in
14494       * the result
14495       */
14496      Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
14497                                   mkexpr( frBI64_lo ),
14498                                   &top_12_l,
14499                                   &mid_60_u,
14500                                   &mid_60_l,
14501                                   &low_60_u,
14502                                   &low_60_l );
14503
14504      if ( ( sp == 0 ) || ( sp == 1 ) ) {
14505         /* Unsigned BCD string */
14506         assign( result_hi,
14507                 binop( Iop_32HLto64,
14508                        binop( Iop_Or32,
14509                               binop( Iop_Shl32,
14510                                      mkexpr( top_12_l ),
14511                                      mkU8( 24 ) ),
14512                               binop( Iop_Shr32,
14513                                      mkexpr( mid_60_u ),
14514                                      mkU8( 4 ) ) ),
14515                        binop( Iop_Or32,
14516                               binop( Iop_Shl32,
14517                                      mkexpr( mid_60_u ),
14518                                      mkU8( 28 ) ),
14519                               binop( Iop_Shr32,
14520                                      mkexpr( mid_60_l ),
14521                                      mkU8( 4 ) ) ) ) );
14522
14523         assign( result_lo,
14524                 binop( Iop_32HLto64,
14525                        binop( Iop_Or32,
14526                               binop( Iop_Shl32,
14527                                      mkexpr( mid_60_l ),
14528                                      mkU8( 28 ) ),
14529                               mkexpr( low_60_u ) ),
14530                        mkexpr( low_60_l ) ) );
14531
14532      } else {
14533         /* Signed BCD string, the cases for sp 2 and 3 only differ in how
14534          * the positive and negative values are encoded in the least
14535          * significant bits.
14536          */
14537         IRTemp sign = newTemp( Ity_I32 );
14538
14539         if ( sp == 2 ) {
14540            /* Positive sign = 0xC, negative sign = 0xD */
14541            assign( sign,
14542                    binop( Iop_Or32,
14543                           binop( Iop_Shr32,
14544                                  unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
14545                                  mkU8( 31 ) ),
14546                           mkU32( 0xC ) ) );
14547
14548         } else if ( sp == 3 ) {
14549            IRTemp tmp32 = newTemp( Ity_I32 );
14550
14551            /* Positive sign = 0xF, negative sign = 0xD.
14552             * Need to complement sign bit then OR into bit position 1.
14553             */
14554            assign( tmp32,
14555                    binop( Iop_Xor32,
14556                           binop( Iop_Shr32,
14557                                  unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
14558                                  mkU8( 30 ) ),
14559                           mkU32( 0x2 ) ) );
14560
14561            assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
14562
14563         } else {
14564            vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
14565         }
14566
14567         assign( result_hi,
14568                 binop( Iop_32HLto64,
14569                        binop( Iop_Or32,
14570                               binop( Iop_Shl32,
14571                                      mkexpr( top_12_l ),
14572                                      mkU8( 28 ) ),
14573                               mkexpr( mid_60_u ) ),
14574                        mkexpr( mid_60_l ) ) );
14575
14576         assign( result_lo,
14577                 binop( Iop_32HLto64,
14578                        binop( Iop_Or32,
14579                               binop( Iop_Shl32,
14580                                      mkexpr( low_60_u ),
14581                                      mkU8( 4 ) ),
14582                               binop( Iop_Shr32,
14583                                      mkexpr( low_60_l ),
14584                                      mkU8( 28 ) ) ),
14585                        binop( Iop_Or32,
14586                               binop( Iop_Shl32,
14587                                      mkexpr( low_60_l ),
14588                                      mkU8( 4 ) ),
14589                               mkexpr( sign ) ) ) );
14590      }
14591
14592      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
14593      putDReg( frT_addr + 1,
14594               unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
14595   }
14596   break;
14597   case 0x342: // denbcdq   DFP Encode BCD to DPD
14598   {
14599      IRTemp valid_mask      = newTemp( Ity_I32 );
14600      IRTemp invalid_mask    = newTemp( Ity_I32 );
14601      IRTemp result128       = newTemp( Ity_D128 );
14602      IRTemp dfp_significand = newTemp( Ity_D128 );
14603      IRTemp tmp_hi          = newTemp( Ity_I64 );
14604      IRTemp tmp_lo          = newTemp( Ity_I64 );
14605      IRTemp dbcd_top_l      = newTemp( Ity_I32 );
14606      IRTemp dbcd_mid_u      = newTemp( Ity_I32 );
14607      IRTemp dbcd_mid_l      = newTemp( Ity_I32 );
14608      IRTemp dbcd_low_u      = newTemp( Ity_I32 );
14609      IRTemp dbcd_low_l      = newTemp( Ity_I32 );
14610      IRTemp bcd_top_8       = newTemp( Ity_I64 );
14611      IRTemp bcd_mid_60      = newTemp( Ity_I64 );
14612      IRTemp bcd_low_60      = newTemp( Ity_I64 );
14613      IRTemp sign_bit        = newTemp( Ity_I32 );
14614      IRTemp tmptop10        = newTemp( Ity_I64 );
14615      IRTemp tmpmid50        = newTemp( Ity_I64 );
14616      IRTemp tmplow50        = newTemp( Ity_I64 );
14617      IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
14618
14619      DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
14620
14621      if ( s == 0 ) {
14622         /* Unsigned BCD string */
14623         assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
14624
14625         assign( bcd_top_8,
14626                 binop( Iop_32HLto64,
14627                        mkU32( 0 ),
14628                        binop( Iop_And32,
14629                               binop( Iop_Shr32,
14630                                      unop( Iop_64HIto32,
14631                                            mkexpr( frBI64_hi ) ),
14632                                      mkU8( 24 ) ),
14633                               mkU32( 0xFF ) ) ) );
14634         assign( bcd_mid_60,
14635                 binop( Iop_32HLto64,
14636                        binop( Iop_Or32,
14637                               binop( Iop_Shr32,
14638                                      unop( Iop_64to32,
14639                                            mkexpr( frBI64_hi ) ),
14640                                      mkU8( 28 ) ),
14641                               binop( Iop_Shl32,
14642                                      unop( Iop_64HIto32,
14643                                            mkexpr( frBI64_hi ) ),
14644                                      mkU8( 4 ) ) ),
14645                        binop( Iop_Or32,
14646                               binop( Iop_Shl32,
14647                                      unop( Iop_64to32,
14648                                            mkexpr( frBI64_hi ) ),
14649                                      mkU8( 4 ) ),
14650                               binop( Iop_Shr32,
14651                                      unop( Iop_64HIto32,
14652                                            mkexpr( frBI64_lo ) ),
14653                                      mkU8( 28 ) ) ) ) );
14654
14655         /* Note, the various helper functions ignores top 4-bits */
14656         assign( bcd_low_60, mkexpr( frBI64_lo ) );
14657
14658         assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
14659         assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
14660
14661         assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
14662         assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
14663         assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
14664
14665         assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
14666         assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
14667         assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
14668
14669         /* The entire BCD string fits in lower 110-bits.  The LMD = 0,
14670          * value is not part of the final result. Only the right most
14671          * BCD digits are stored.
14672          */
14673         assign( lmd, mkU32( 0 ) );
14674
14675         assign( invalid_mask,
14676                 binop( Iop_Or32,
14677                        bcd_digit_inval( mkU32( 0 ),
14678                                         unop( Iop_64to32,
14679                                               mkexpr( bcd_top_8 ) ) ),
14680                        binop( Iop_Or32,
14681                               bcd_digit_inval( unop( Iop_64HIto32,
14682                                                      mkexpr( bcd_mid_60 ) ),
14683                                                unop( Iop_64to32,
14684                                                      mkexpr( bcd_mid_60 ) ) ),
14685                               bcd_digit_inval( unop( Iop_64HIto32,
14686                                                      mkexpr( bcd_low_60 ) ),
14687                                                unop( Iop_64to32,
14688                                                      mkexpr( bcd_low_60 ) )
14689                                                ) ) ) );
14690
14691      } else if ( s == 1 ) {
14692         IRTemp sign          = newTemp( Ity_I32 );
14693         IRTemp zero          = newTemp( Ity_I32 );
14694         IRTemp pos_sign_mask = newTemp( Ity_I32 );
14695         IRTemp neg_sign_mask = newTemp( Ity_I32 );
14696
14697         /* The sign of the BCD string is stored in lower 4 bits */
14698         assign( sign,
14699                 binop( Iop_And32,
14700                        unop( Iop_64to32, mkexpr( frBI64_lo ) ),
14701                        mkU32( 0xF ) ) );
14702         assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
14703         assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
14704         assign( sign_bit,
14705                 Generate_sign_bit( mkexpr( pos_sign_mask ),
14706                                    mkexpr( neg_sign_mask ) ) );
14707
14708         /* Generate the value assuminig the sign and BCD digits are vaild */
14709         assign( bcd_top_8,
14710                 binop( Iop_32HLto64,
14711                        mkU32( 0x0 ),
14712                        binop( Iop_Shr32,
14713                               unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
14714                               mkU8( 28 ) ) ) );
14715
14716         /* The various helper routines ignore the upper 4-bits */
14717         assign( bcd_mid_60, mkexpr( frBI64_hi ) );
14718
14719         /* Remove bottom four sign bits */
14720         assign( bcd_low_60,
14721                 binop( Iop_32HLto64,
14722                        binop( Iop_Shr32,
14723                               unop( Iop_64HIto32,
14724                                     mkexpr( frBI64_lo ) ),
14725                               mkU8( 4 ) ),
14726                               binop( Iop_Or32,
14727                                      binop( Iop_Shl32,
14728                                             unop( Iop_64HIto32,
14729                                                   mkexpr( frBI64_lo ) ),
14730                                             mkU8( 28 ) ),
14731                                      binop( Iop_Shr32,
14732                                             unop( Iop_64to32,
14733                                                   mkexpr( frBI64_lo ) ),
14734                                             mkU8( 4 ) ) ) ) );
14735         assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
14736         assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
14737
14738         assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
14739         assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
14740         assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
14741
14742         assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
14743         assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
14744         assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
14745
14746         /* The entire BCD string fits in lower 110-bits.  The LMD value
14747          * is not stored in the final result for the DFP Long instruction.
14748          */
14749         assign( lmd, mkU32( 0 ) );
14750
14751         /* Check for invalid sign and invalid BCD digit.  Don't check the
14752          *  bottom four bits of frBI64_lo as that is the sign value.
14753          */
14754         assign( zero, mkU32( 0 ) );
14755         assign( inval_bcd_digit_mask,
14756                 binop( Iop_Or32,
14757                        bcd_digit_inval( mkexpr( zero ),
14758                                         unop( Iop_64to32,
14759                                               mkexpr( bcd_top_8 ) ) ),
14760                        binop( Iop_Or32,
14761                               bcd_digit_inval( unop( Iop_64HIto32,
14762                                                     mkexpr( bcd_mid_60 ) ),
14763                                               unop( Iop_64to32,
14764                                                     mkexpr( bcd_mid_60 ) ) ),
14765                               bcd_digit_inval( unop( Iop_64HIto32,
14766                                                     mkexpr( frBI64_lo ) ),
14767                                               binop( Iop_Shr32,
14768                                                      unop( Iop_64to32,
14769                                                            mkexpr( frBI64_lo ) ),
14770                                                        mkU8( 4 ) ) ) ) ) );
14771         assign( invalid_mask,
14772                 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
14773                                    mkexpr( pos_sign_mask ),
14774                                    mkexpr( neg_sign_mask ) ) );
14775
14776      }
14777
14778      assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
14779
14780      /* Calculate the value of the result assuming sign and BCD digits
14781       * are all valid.
14782       */
14783      assign( dfp_significand,
14784              binop( Iop_D64HLtoD128,
14785                     unop( Iop_ReinterpI64asD64,
14786                           binop( Iop_32HLto64,
14787                                  binop( Iop_Or32,
14788                                         mkexpr( sign_bit ),
14789                                         mkexpr( dbcd_top_l ) ),
14790                                  binop( Iop_Or32,
14791                                         binop( Iop_Shl32,
14792                                                mkexpr( dbcd_mid_u ),
14793                                                mkU8( 18 ) ),
14794                                         binop( Iop_Shr32,
14795                                                mkexpr( dbcd_mid_l ),
14796                                                mkU8( 14 ) ) ) ) ),
14797                     unop( Iop_ReinterpI64asD64,
14798                           binop( Iop_32HLto64,
14799                                  binop( Iop_Or32,
14800                                         mkexpr( dbcd_low_u ),
14801                                         binop( Iop_Shl32,
14802                                                mkexpr( dbcd_mid_l ),
14803                                                mkU8( 18 ) ) ),
14804                                  mkexpr( dbcd_low_l ) ) ) ) );
14805
14806      /* Break the result back down to 32-bit chunks and replace chunks.
14807       * If there was an invalid BCD digit or invalid sign value, replace
14808       * the calculated result with the invalid bit string.
14809       */
14810      assign( result128,
14811              binop( Iop_InsertExpD128,
14812                     mkU64( DFP_EXTND_BIAS ),
14813                     mkexpr( dfp_significand ) ) );
14814
14815      assign( tmp_hi,
14816              unop( Iop_ReinterpD64asI64,
14817                    unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
14818
14819      assign( tmp_lo,
14820              unop( Iop_ReinterpD64asI64,
14821                    unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
14822
14823      assign( result_hi,
14824              binop( Iop_32HLto64,
14825                     binop( Iop_Or32,
14826                            binop( Iop_And32,
14827                                   mkexpr( valid_mask ),
14828                                   unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
14829                            binop( Iop_And32,
14830                                   mkU32( 0x7C000000 ),
14831                                   mkexpr( invalid_mask ) ) ),
14832                     binop( Iop_Or32,
14833                            binop( Iop_And32,
14834                                   mkexpr( valid_mask ),
14835                                   unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
14836                            binop( Iop_And32,
14837                                   mkU32( 0x0 ),
14838                                   mkexpr( invalid_mask ) ) ) ) );
14839
14840      assign( result_lo,
14841              binop( Iop_32HLto64,
14842                     binop( Iop_Or32,
14843                            binop( Iop_And32,
14844                                   mkexpr( valid_mask ),
14845                                   unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
14846                            binop( Iop_And32,
14847                                   mkU32( 0x0 ),
14848                                   mkexpr( invalid_mask ) ) ),
14849                     binop( Iop_Or32,
14850                            binop( Iop_And32,
14851                                   mkexpr( valid_mask ),
14852                                   unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
14853                            binop( Iop_And32,
14854                                   mkU32( 0x0 ),
14855                                   mkexpr( invalid_mask ) ) ) ) );
14856
14857      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
14858      putDReg( frT_addr + 1,
14859               unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
14860
14861   }
14862   break;
14863   default:
14864      vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
14865      break;
14866   }
14867   return True;
14868}
14869
14870static Bool dis_dfp_significant_digits( UInt theInstr )
14871{
14872   UInt opc1      = ifieldOPC( theInstr );
14873   UInt opc2      = ifieldOPClo10(theInstr);
14874   UChar frA_addr = ifieldRegA( theInstr );
14875   UChar frB_addr = ifieldRegB( theInstr );
14876   IRTemp frA     = newTemp( Ity_D64 );
14877   IRTemp B_sig   = newTemp( Ity_I8 );
14878   IRTemp K       = newTemp( Ity_I8 );
14879   IRTemp lmd_B   = newTemp( Ity_I32 );
14880   IRTemp field   = newTemp( Ity_I32 );
14881   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
14882   IRTemp Unordered_true     = newTemp( Ity_I32 );
14883   IRTemp Eq_true_mask       = newTemp( Ity_I32 );
14884   IRTemp Lt_true_mask       = newTemp( Ity_I32 );
14885   IRTemp Gt_true_mask       = newTemp( Ity_I32 );
14886   IRTemp KisZero_true_mask  = newTemp( Ity_I32 );
14887   IRTemp KisZero_false_mask = newTemp( Ity_I32 );
14888   IRTemp cc = newTemp( Ity_I32 );
14889   UChar  UIM     = toUChar( IFIELD( theInstr, 16, 6 ) );
14890   IRTemp BCD_valid  = newTemp( Ity_I32 );
14891
14892   if (opc2 == 0x2A2) {        // dtstsf   DFP Test Significance
14893                               // dtstsfq  DFP Test Significance Quad
14894      /* Get the reference singificance stored in frA */
14895      assign( frA, getDReg( frA_addr ) );
14896
14897      /* Convert from 64 bit to 8 bits in two steps.  The Iop_64to8 is not
14898       * supported in 32-bit mode.
14899       */
14900      assign( K, unop( Iop_32to8,
14901                       binop( Iop_And32,
14902                              unop( Iop_64to32,
14903                                    unop( Iop_ReinterpD64asI64,
14904                                          mkexpr( frA ) ) ),
14905                              mkU32( 0x3F ) ) ) );
14906
14907   } else if (opc2 == 0x2A3) { // dtstsfi  DFP Test Significance Immediate
14908                               // dtstsfiq DFP Test Significance Quad Immediate
14909      /* get the significane from the immediate field */
14910      assign( K, mkU8( UIM) );
14911
14912   } else {
14913      vex_printf("dis_dfp_significant_digits(ppc)(opc2) wrong\n");
14914      return False;
14915   }
14916
14917   switch ( opc1 ) {
14918   case 0x3b: // dtstsf   DFP Test Significance
14919              // dtstsfi  DFP Test Significance Immediate
14920   {
14921      IRTemp frB     = newTemp( Ity_D64 );
14922      IRTemp frBI64  = newTemp( Ity_I64 );
14923      IRTemp B_bcd_u = newTemp( Ity_I32 );
14924      IRTemp B_bcd_l = newTemp( Ity_I32 );
14925      IRTemp tmp64   = newTemp( Ity_I64 );
14926
14927      if (opc2 == 0x2A2) {
14928         DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
14929      } else {
14930         DIP( "dtstsfi %u,%u,r%u\n", crfD, UIM, frB_addr );
14931      }
14932
14933      assign( frB, getDReg( frB_addr ) );
14934      assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
14935
14936      /* Get the BCD string for the value stored in a series of I32 values.
14937       * Count the number of leading zeros.  Subtract the number of leading
14938       * zeros from 16 (maximum number of significant digits in DFP
14939       * Long).
14940       */
14941      Get_lmd( &lmd_B,
14942               binop( Iop_Shr32,
14943                      unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14944                      mkU8( 31 - 5 ) ) ); // G-field[0:4]
14945
14946      assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
14947      assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
14948      assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
14949
14950      assign( B_sig,
14951              binop( Iop_Sub8,
14952                     mkU8( DFP_LONG_MAX_SIG_DIGITS ),
14953                     Count_leading_zeros_60( mkexpr( lmd_B ),
14954                                             mkexpr( B_bcd_u ),
14955                                             mkexpr( B_bcd_l ) ) ) );
14956
14957      assign( BCD_valid,
14958              binop( Iop_Or32,
14959                     bcd_digit_inval( mkexpr( B_bcd_u), mkexpr( B_bcd_l) ),
14960                     bcd_digit_inval( mkexpr( lmd_B), mkU32( 0 ) ) ) );
14961
14962      /* Set unordered to True if the number is NaN, Inf or an invalid
14963       * digit.
14964       */
14965      assign( Unordered_true,
14966              binop( Iop_Or32,
14967                     Check_unordered( mkexpr( frBI64 ) ),
14968                     mkexpr( BCD_valid) ) );
14969   }
14970   break;
14971   case 0x3F: // dtstsfq     DFP Test Significance
14972              // dtstsfqi    DFP Test Significance Immediate
14973   {
14974      IRTemp frB_hi     = newTemp( Ity_D64 );
14975      IRTemp frB_lo     = newTemp( Ity_D64 );
14976      IRTemp frBI64_hi  = newTemp( Ity_I64 );
14977      IRTemp frBI64_lo  = newTemp( Ity_I64 );
14978      IRTemp B_low_60_u = newTemp( Ity_I32 );
14979      IRTemp B_low_60_l = newTemp( Ity_I32 );
14980      IRTemp B_mid_60_u = newTemp( Ity_I32 );
14981      IRTemp B_mid_60_l = newTemp( Ity_I32 );
14982      IRTemp B_top_12_l = newTemp( Ity_I32 );
14983
14984      if (opc2 == 0x2A2) {
14985         DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
14986      } else {
14987         DIP( "dtstsfiq %u,%u,r%u\n", crfD, UIM, frB_addr );
14988      }
14989
14990      assign( frB_hi, getDReg( frB_addr ) );
14991      assign( frB_lo, getDReg( frB_addr + 1 ) );
14992
14993      assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
14994      assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
14995
14996      /* Get the BCD string for the value stored in a series of I32 values.
14997       * Count the number of leading zeros.  Subtract the number of leading
14998       * zeros from 32 (maximum number of significant digits in DFP
14999       * extended).
15000       */
15001      Get_lmd( &lmd_B,
15002               binop( Iop_Shr32,
15003                      unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
15004                      mkU8( 31 - 5 ) ) ); // G-field[0:4]
15005
15006      Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
15007                                   mkexpr( frBI64_lo ),
15008                                   &B_top_12_l,
15009                                   &B_mid_60_u,
15010                                   &B_mid_60_l,
15011                                   &B_low_60_u,
15012                                   &B_low_60_l );
15013
15014      assign( BCD_valid,
15015              binop( Iop_Or32,
15016                     binop( Iop_Or32,
15017                            bcd_digit_inval( mkexpr( lmd_B ),
15018                                             mkexpr( B_top_12_l ) ),
15019                            bcd_digit_inval( mkexpr( B_mid_60_u ),
15020                                             mkexpr( B_mid_60_l ) ) ),
15021                     bcd_digit_inval( mkexpr( B_low_60_u ),
15022                                      mkexpr( B_low_60_l ) ) ) );
15023
15024      assign( B_sig,
15025              binop( Iop_Sub8,
15026                     mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
15027                     Count_leading_zeros_128( mkexpr( lmd_B ),
15028                                              mkexpr( B_top_12_l ),
15029                                              mkexpr( B_mid_60_u ),
15030                                              mkexpr( B_mid_60_l ),
15031                                              mkexpr( B_low_60_u ),
15032                                              mkexpr( B_low_60_l ) ) ) );
15033
15034      /* Set unordered to True if the number is NaN, Inf or an invalid
15035       * digit.
15036       */
15037      assign( Unordered_true,
15038              binop( Iop_Or32,
15039                     Check_unordered( mkexpr( frBI64_hi ) ),
15040                     mkexpr( BCD_valid) ) );
15041   }
15042   break;
15043   }
15044
15045   /* Compare (16 - cnt[0]) against K and set the condition code field
15046    * accordingly.
15047    *
15048    * The field layout is as follows:
15049    *
15050    * bit[3:0]    Description
15051    *    3     K != 0 and K < Number of significant digits if FRB
15052    *    2     K != 0 and K > Number of significant digits if FRB OR K = 0
15053    *    1     K != 0 and K = Number of significant digits if FRB
15054    *    0     K ? Number of significant digits if FRB
15055    */
15056   assign( Eq_true_mask,
15057           unop( Iop_1Sto32,
15058                 binop( Iop_CmpEQ32,
15059                        unop( Iop_8Uto32, mkexpr( K ) ),
15060                        unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
15061   assign( Lt_true_mask,
15062           unop( Iop_1Sto32,
15063                 binop( Iop_CmpLT32U,
15064                        unop( Iop_8Uto32, mkexpr( K ) ),
15065                        unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
15066   assign( Gt_true_mask,
15067           unop( Iop_1Sto32,
15068                 binop( Iop_CmpLT32U,
15069                        unop( Iop_8Uto32, mkexpr( B_sig ) ),
15070                        unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
15071
15072   assign( KisZero_true_mask,
15073           unop( Iop_1Sto32,
15074                 binop( Iop_CmpEQ32,
15075                        unop( Iop_8Uto32, mkexpr( K ) ),
15076                        mkU32( 0 ) ) ) );
15077   assign( KisZero_false_mask,
15078           unop( Iop_1Sto32,
15079                 binop( Iop_CmpNE32,
15080                        unop( Iop_8Uto32, mkexpr( K ) ),
15081                        mkU32( 0 ) ) ) );
15082
15083   assign( field,
15084           binop( Iop_Or32,
15085                  binop( Iop_And32,
15086                         mkexpr( KisZero_false_mask ),
15087                         binop( Iop_Or32,
15088                                binop( Iop_And32,
15089                                       mkexpr( Lt_true_mask ),
15090                                       mkU32( 0x8 ) ),
15091                                binop( Iop_Or32,
15092                                       binop( Iop_And32,
15093                                              mkexpr( Gt_true_mask ),
15094                                              mkU32( 0x4 ) ),
15095                                       binop( Iop_And32,
15096                                              mkexpr( Eq_true_mask ),
15097                                              mkU32( 0x2 ) ) ) ) ),
15098                  binop( Iop_And32,
15099                         mkexpr( KisZero_true_mask ),
15100                         mkU32( 0x4 ) ) ) );
15101
15102   assign( cc, binop( Iop_Or32,
15103                      binop( Iop_And32,
15104                             mkexpr( Unordered_true ),
15105                             mkU32( 0x1 ) ),
15106                      binop( Iop_And32,
15107                             unop( Iop_Not32, mkexpr( Unordered_true ) ),
15108                             mkexpr( field ) ) ) );
15109
15110   putGST_field( PPC_GST_CR, mkexpr( cc ), crfD );
15111   putFPCC( mkexpr( cc ) );
15112
15113   return True;
15114}
15115/*------------------------------------------------------------*/
15116/*--- AltiVec Instruction Translation                      ---*/
15117/*------------------------------------------------------------*/
15118
15119/*
15120  Altivec Cache Control Instructions (Data Streams)
15121*/
15122static Bool dis_av_datastream ( UInt theInstr )
15123{
15124   /* X-Form */
15125   UChar opc1     = ifieldOPC(theInstr);
15126   UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
15127   UChar flag_A   = flag_T;
15128   UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
15129   UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
15130   UChar rA_addr  = ifieldRegA(theInstr);
15131   UChar rB_addr  = ifieldRegB(theInstr);
15132   UInt  opc2     = ifieldOPClo10(theInstr);
15133   UChar b0       = ifieldBIT0(theInstr);
15134
15135   if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
15136      vex_printf("dis_av_datastream(ppc)(instr)\n");
15137      return False;
15138   }
15139
15140   switch (opc2) {
15141   case 0x156: // dst (Data Stream Touch, AV p115)
15142      DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
15143                                rA_addr, rB_addr, STRM);
15144      break;
15145
15146   case 0x176: // dstst (Data Stream Touch for Store, AV p117)
15147      DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
15148                                  rA_addr, rB_addr, STRM);
15149      break;
15150
15151   case 0x336: // dss (Data Stream Stop, AV p114)
15152      if (rA_addr != 0 || rB_addr != 0) {
15153         vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
15154         return False;
15155      }
15156      if (flag_A == 0) {
15157         DIP("dss %d\n", STRM);
15158      } else {
15159         DIP("dssall\n");
15160      }
15161      break;
15162
15163   default:
15164      vex_printf("dis_av_datastream(ppc)(opc2)\n");
15165      return False;
15166   }
15167   return True;
15168}
15169
15170/*
15171  AltiVec Processor Control Instructions
15172*/
15173static Bool dis_av_procctl ( UInt theInstr )
15174{
15175   /* VX-Form */
15176   UChar opc1    = ifieldOPC(theInstr);
15177   UChar vD_addr = ifieldRegDS(theInstr);
15178   UChar vA_addr = ifieldRegA(theInstr);
15179   UChar vB_addr = ifieldRegB(theInstr);
15180   UInt  opc2    = IFIELD( theInstr, 0, 11 );
15181
15182   if (opc1 != 0x4) {
15183      vex_printf("dis_av_procctl(ppc)(instr)\n");
15184      return False;
15185   }
15186
15187   switch (opc2) {
15188   case 0x604: // mfvscr (Move from VSCR, AV p129)
15189      if (vA_addr != 0 || vB_addr != 0) {
15190         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
15191         return False;
15192      }
15193      DIP("mfvscr v%d\n", vD_addr);
15194      putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
15195      break;
15196
15197   case 0x644: { // mtvscr (Move to VSCR, AV p130)
15198      IRTemp vB = newTemp(Ity_V128);
15199      if (vD_addr != 0 || vA_addr != 0) {
15200         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
15201         return False;
15202      }
15203      DIP("mtvscr v%d\n", vB_addr);
15204      assign( vB, getVReg(vB_addr));
15205      putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
15206      break;
15207   }
15208   default:
15209      vex_printf("dis_av_procctl(ppc)(opc2)\n");
15210      return False;
15211   }
15212   return True;
15213}
15214
15215/*
15216Vector Extend Sign Instructions
15217*/
15218static Bool dis_av_extend_sign_count_zero ( UInt theInstr, UInt allow_isa_3_0 )
15219{
15220   /* VX-Form, sort of, the A register field is used to select the specific
15221    * sign extension instruction or count leading/trailing zero LSB
15222    * instruction.
15223    */
15224
15225   UChar opc1    = ifieldOPC( theInstr );
15226   UChar rT_addr = ifieldRegDS (theInstr );
15227   UChar rA_addr = ifieldRegA( theInstr );
15228   UChar vB_addr = ifieldRegB( theInstr );
15229   UInt  opc2    = IFIELD( theInstr, 0, 11 );
15230
15231   IRTemp vB    = newTemp( Ity_V128 );
15232   IRTemp vT    = newTemp( Ity_V128 );
15233
15234   assign( vB, getVReg ( vB_addr ) );
15235
15236   if ( ( opc1 != 0x4 ) && ( opc2 != 0x602 ) )  {
15237      vex_printf("dis_av_extend_sign(ppc)(instr)\n");
15238      return False;
15239   }
15240
15241   switch ( rA_addr ) {
15242   case 0:
15243   case 1:
15244   {
15245      UInt i;
15246      IRTemp count[17];
15247      IRTemp bit_zero[16];
15248      IRTemp byte_mask[17];
15249
15250      /* These instructions store the result in the general purpose
15251       * register in the rT_addr field.
15252       */
15253
15254      byte_mask[0] = newTemp( Ity_I32 );
15255      count[0] = newTemp( Ity_I32 );
15256      assign( count[0], mkU32( 0 ) );
15257      assign( byte_mask[0], mkU32( 0x1 ) );
15258
15259      if ( rA_addr == 0 ) {
15260         // vclzlsbb (Vector Count Leading Zero Least-Significant Bits Byte)
15261         DIP("vclzlsbb %d,v%d\n", rT_addr, vB_addr);
15262
15263      } else {
15264         // vctzlsbb (Vector Count Trailing Zero Least-Significant Bits Byte)
15265         DIP("vctzlsbb %d,v%d\n", rT_addr, vB_addr);
15266      }
15267
15268      for( i = 0; i < 16; i++ ) {
15269         byte_mask[i+1] = newTemp( Ity_I32 );
15270         count[i+1] = newTemp( Ity_I32 );
15271         bit_zero[i] = newTemp( Ity_I1 );
15272
15273         /* bit_zero[i] = 0x0 until the first 1 bit is found in lsb of
15274          * byte.  When the first 1 bit is found it causes the byte_mask
15275          * to change from 0x1 to 0x0.  Thus the AND of the lsb and byte_mask
15276          * will be zero  which will be equal to the zero byte_mask causing
15277          * the value of bit_zero[i] to be equal to 0x1 for all remaining bits.
15278          */
15279
15280         if ( rA_addr == 0 )
15281            /* leading zero bit in byte count,
15282               work bytes from left to right
15283            */
15284            assign( bit_zero[i],
15285                    binop( Iop_CmpEQ32,
15286                           binop( Iop_And32,
15287                                  unop( Iop_V128to32,
15288                                        binop( Iop_ShrV128,
15289                                               mkexpr( vB ),
15290                                               mkU8( ( 15 - i) * 8 ) ) ),
15291                                  mkexpr( byte_mask[i] ) ),
15292                           mkexpr( byte_mask[i] ) ) );
15293
15294         else if ( rA_addr == 1 )
15295            /* trailing zero bit in byte count,
15296             * work bytes from right to left
15297             */
15298            assign( bit_zero[i],
15299                    binop( Iop_CmpEQ32,
15300                           binop( Iop_And32,
15301                                  unop( Iop_V128to32,
15302                                        binop( Iop_ShrV128,
15303                                               mkexpr( vB ),
15304                                               mkU8( i * 8 ) ) ),
15305                                  mkexpr( byte_mask[i] ) ),
15306                           mkexpr( byte_mask[i] ) ) );
15307
15308         /* Increment count as long as bit_zero = 0 */
15309         assign( count[i+1], binop( Iop_Add32,
15310                                    mkexpr( count[i] ),
15311                                    unop( Iop_1Uto32,
15312                                          unop( Iop_Not1,
15313                                                mkexpr( bit_zero[i] ) ) ) ) );
15314
15315         /* If comparison fails to find a zero bit, set the byte_mask to zero
15316          * for all future comparisons so there will be no more matches.
15317          */
15318         assign( byte_mask[i+1],
15319                 binop( Iop_And32,
15320                        unop( Iop_1Uto32,
15321                              unop( Iop_Not1,
15322                                    mkexpr( bit_zero[i] ) ) ),
15323                        mkexpr( byte_mask[i] )  ) );
15324      }
15325      putIReg( rT_addr, unop( Iop_32Uto64, mkexpr( count[16] ) ) );
15326      return True;
15327   }
15328
15329   case 6: // vnegw,  Vector Negate Word
15330      DIP("vnegw  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15331
15332      /* multiply each word by -1 */
15333      assign( vT, binop( Iop_Mul32x4, mkexpr( vB ), mkV128( 0xFFFF ) ) );
15334      break;
15335
15336   case 7: // vnegd,  Vector Negate Doubleword
15337      DIP("vnegd  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15338
15339      /* multiply each word by -1 */
15340      assign( vT, binop( Iop_64HLtoV128,
15341                         binop( Iop_Mul64,
15342                                unop( Iop_V128HIto64,
15343                                      mkexpr( vB ) ),
15344                                mkU64( 0xFFFFFFFFFFFFFFFF ) ),
15345                         binop( Iop_Mul64,
15346                               unop( Iop_V128to64,
15347                                      mkexpr( vB ) ),
15348                                mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) );
15349      break;
15350
15351   case 8:  // vprtybw,  Vector Parity Byte Word
15352   case 9:  // vprtybd,  Vector Parity Byte Doubleword
15353   case 10: // vprtybq,  Vector Parity Byte Quadword
15354      {
15355         UInt i;
15356         IRTemp bit_in_byte[16];
15357         IRTemp word_parity[4];
15358
15359         for( i = 0; i < 16; i++ ) {
15360            bit_in_byte[i] = newTemp( Ity_I32 );
15361            assign( bit_in_byte[i],
15362                    binop( Iop_And32,
15363                           unop( Iop_V128to32,
15364                                 binop( Iop_ShrV128,
15365                                        mkexpr( vB ),
15366                                        mkU8( ( 15 - i ) * 8 ) ) ),
15367                           mkU32( 0x1 ) ) );
15368         }
15369
15370         for( i = 0; i < 4; i++ ) {
15371            word_parity[i] = newTemp(Ity_I32);
15372            assign( word_parity[i],
15373                    mkXOr4_32( bit_in_byte[0 + i * 4],
15374                               bit_in_byte[1 + i * 4],
15375                               bit_in_byte[2 + i * 4],
15376                               bit_in_byte[3 + i * 4] ) );
15377         }
15378
15379         if ( rA_addr == 8 ) {
15380            DIP("vprtybw  v%d,v%d", rT_addr, vB_addr);
15381
15382            assign( vT, mkV128from32( word_parity[0], word_parity[1],
15383                                      word_parity[2], word_parity[3] ) );
15384
15385         } else if ( rA_addr == 9 ) {
15386            DIP("vprtybd  v%d,v%d", rT_addr, vB_addr);
15387
15388            assign( vT,
15389                    binop( Iop_64HLtoV128,
15390                           binop( Iop_32HLto64,
15391                                  mkU32( 0 ),
15392                                  binop( Iop_Xor32,
15393                                         mkexpr( word_parity[0] ),
15394                                         mkexpr( word_parity[1] ) ) ),
15395                           binop( Iop_32HLto64,
15396                                  mkU32( 0 ),
15397                                  binop( Iop_Xor32,
15398                                         mkexpr( word_parity[2] ),
15399                                         mkexpr( word_parity[3] ) ) ) ) );
15400
15401         } else if ( rA_addr == 10 ) {
15402            DIP("vprtybq  v%d,v%d", rT_addr, vB_addr);
15403
15404            assign( vT,
15405                    binop( Iop_64HLtoV128,
15406                           mkU64( 0 ),
15407                           unop( Iop_32Uto64,
15408                                 mkXOr4_32( word_parity[0],
15409                                            word_parity[1],
15410                                            word_parity[2],
15411                                            word_parity[3] ) ) ) );
15412         }
15413      }
15414      break;
15415
15416   case 16: // vextsb2w,  Vector Extend Sign Byte to Word
15417      DIP("vextsb2w  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15418
15419      /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to
15420       * two byte sign extended result.  Then do a two byte to four byte sign
15421       * extended multiply.  Note contents of upper three bytes in word are
15422       * "over written". So just take source and multiply by 1.
15423       */
15424      assign( vT, binop( Iop_MullEven16Sx8,
15425                         binop( Iop_64HLtoV128,
15426                                mkU64( 0x0000000100000001 ),
15427                                mkU64( 0x0000000100000001 ) ),
15428                         binop( Iop_MullEven8Sx16,
15429                                mkexpr( vB ),
15430                                binop( Iop_64HLtoV128,
15431                                       mkU64( 0x0001000100010001 ),
15432                                       mkU64( 0x0001000100010001 ) ) ) ) );
15433      break;
15434
15435   case 17: // vextsh2w,  Vector Extend Sign Halfword to Word
15436      DIP("vextsh2w  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15437
15438      /* Iop_MullEven16Sx8 does a signed widening multiply of four byte
15439       * 8 bytes.  Note contents of upper two bytes in word are
15440       * "over written". So just take source and multiply by 1.
15441       */
15442      assign( vT, binop( Iop_MullEven16Sx8,
15443                         binop( Iop_64HLtoV128,
15444                                mkU64( 0x0000000100000001 ),
15445                                mkU64( 0x0000000100000001 ) ),
15446                        mkexpr( vB ) ) );
15447
15448      break;
15449
15450   case 24: // vextsb2d,  Vector Extend Sign Byte to Doubleword
15451      DIP("vextsb2d  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15452
15453      /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to
15454       * two byte sign extended result.  Then do a two byte to four byte sign
15455       * extended multiply. Then do four byte to eight byte multiply.
15456       */
15457      assign( vT, binop( Iop_MullEven32Sx4,
15458                         binop( Iop_64HLtoV128,
15459                                mkU64( 0x0000000000000001 ),
15460                                mkU64( 0x0000000000000001 ) ),
15461                        binop( Iop_MullEven16Sx8,
15462                               binop( Iop_64HLtoV128,
15463                                      mkU64( 0x0000000100000001 ),
15464                                      mkU64( 0x0000000100000001 ) ),
15465                              binop( Iop_MullEven8Sx16,
15466                                     binop( Iop_64HLtoV128,
15467                                            mkU64( 0x0001000100010001 ),
15468                                            mkU64( 0x0001000100010001 ) ),
15469                                    mkexpr( vB ) ) ) ) );
15470      break;
15471
15472   case 25: // vextsh2d,  Vector Extend Sign Halfword to Doubleword
15473      DIP("vextsh2d  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15474
15475      assign( vT, binop( Iop_MullEven32Sx4,
15476                         binop( Iop_64HLtoV128,
15477                                mkU64( 0x0000000000000001 ),
15478                                mkU64( 0x0000000000000001 ) ),
15479                        binop( Iop_MullEven16Sx8,
15480                               binop( Iop_64HLtoV128,
15481                                      mkU64( 0x0000000100000001 ),
15482                                      mkU64( 0x0000000100000001 ) ),
15483                               mkexpr( vB ) ) ) );
15484      break;
15485
15486   case 26: // vextsw2d,  Vector Extend Sign Word to Doubleword
15487      DIP("vextsw2d  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15488
15489      assign( vT, binop( Iop_MullEven32Sx4,
15490                         binop( Iop_64HLtoV128,
15491                                mkU64( 0x0000000000000001 ),
15492                                mkU64( 0x0000000000000001 ) ),
15493                        mkexpr( vB ) ) );
15494      break;
15495
15496   case 28: // vctzb,  Vector Count Trailing Zeros Byte
15497      {
15498         DIP("vctzb  v%d,v%d", rT_addr, vB_addr);
15499
15500         /* This instruction is only available in the ISA 3.0 */
15501         if ( !mode64 || !allow_isa_3_0 ) {
15502            vex_printf("\n vctzb instruction not supported on non ISA 3.0 platform\n\n");
15503            return False;
15504         }
15505         assign( vT, unop( Iop_Ctz8x16, mkexpr( vB ) ) );
15506      }
15507      break;
15508
15509   case 29: // vctzh,  Vector Count Trailing Zeros Halfword
15510      {
15511         DIP("vctzh  v%d,v%d", rT_addr, vB_addr);
15512
15513         /* This instruction is only available in the ISA 3.0 */
15514         if ( !mode64 || !allow_isa_3_0 ) {
15515            vex_printf("\n vctzh instruction not supported on non ISA 3.0 platform\n\n");
15516            return False;
15517         }
15518         assign( vT, unop( Iop_Ctz16x8, mkexpr( vB ) ) );
15519      }
15520      break;
15521
15522   case 30: // vctzw,  Vector Count Trailing Zeros Word
15523      {
15524         DIP("vctzw  v%d,v%d", rT_addr, vB_addr);
15525
15526         /* This instruction is only available in the ISA 3.0 */
15527         if ( !mode64 || !allow_isa_3_0 ) {
15528            vex_printf("\n vctzw instruction not supported on non ISA 3.0 platform\n\n");
15529            return False;
15530         }
15531         assign( vT, unop( Iop_Ctz32x4, mkexpr( vB ) ) );
15532      }
15533      break;
15534
15535   case 31: // vctzd,  Vector Count Trailing Zeros Double word
15536      {
15537         DIP("vctzd  v%d,v%d", rT_addr, vB_addr);
15538
15539         /* This instruction is only available in the ISA 3.0 */
15540         if ( !mode64 || !allow_isa_3_0 ) {
15541            vex_printf("\n vctzd instruction not supported on non ISA 3.0 platform\n\n");
15542            return False;
15543         }
15544         assign( vT, unop( Iop_Ctz64x2, mkexpr( vB ) ) );
15545      }
15546      break;
15547
15548   default:
15549      vex_printf("dis_av_extend_sign(ppc)(Unsupported vector extend sign instruction)\n");
15550      return False;
15551   }
15552
15553   putVReg( rT_addr, mkexpr( vT ) );
15554   return True;
15555}
15556
15557/*
15558Vector Rotate Instructions
15559*/
15560static Bool dis_av_rotate ( UInt theInstr )
15561{
15562   /* VX-Form */
15563
15564   UChar opc1    = ifieldOPC( theInstr );
15565   UChar vT_addr = ifieldRegDS( theInstr );
15566   UChar vA_addr = ifieldRegA( theInstr );
15567   UChar vB_addr = ifieldRegB( theInstr );
15568   UInt  opc2    = IFIELD( theInstr, 0, 11 );
15569
15570   IRTemp vA    = newTemp( Ity_V128 );
15571   IRTemp vB    = newTemp( Ity_V128 );
15572   IRTemp src3  = newTemp( Ity_V128 );
15573   IRTemp vT    = newTemp( Ity_V128 );
15574   IRTemp field_mask = newTemp( Ity_V128 );
15575   IRTemp mask128 = newTemp( Ity_V128 );
15576   IRTemp vA_word[4];
15577   IRTemp left_bits[4];
15578   IRTemp right_bits[4];
15579   IRTemp shift[4];
15580   IRTemp mask[4];
15581   IRTemp tmp128[4];
15582   UInt i;
15583   UInt num_words;
15584   UInt word_size;
15585   unsigned long long word_mask;
15586
15587   if ( opc1 != 0x4 ) {
15588      vex_printf("dis_av_rotate(ppc)(instr)\n");
15589      return False;
15590   }
15591
15592   assign( vA, getVReg( vA_addr ) );
15593   assign( vB, getVReg( vB_addr ) );
15594
15595   switch (opc2) {
15596   case 0x85: // vrlwmi,  Vector Rotate Left Word then Mask Insert
15597   case 0x185: // vrlwnm,  Vector Rotate Left Word then AND with Mask
15598      num_words = 4;
15599      word_size = 32;
15600      assign( field_mask, binop( Iop_64HLtoV128,
15601                                 mkU64( 0 ),
15602                                 mkU64( 0x1F ) ) );
15603      word_mask = 0xFFFFFFFF;
15604      break;
15605
15606   case 0x0C5: // vrldmi,  Vector Rotate Left Doubleword then Mask Insert
15607   case 0x1C5: // vrldnm,  Vector Rotate Left Doubleword then AND with Mask
15608      num_words = 2;
15609      word_size = 64;
15610      assign( field_mask, binop( Iop_64HLtoV128,
15611                                 mkU64( 0 ),
15612                                 mkU64( 0x3F ) ) );
15613      word_mask = 0xFFFFFFFFFFFFFFFFULL;
15614      break;
15615   default:
15616      vex_printf("dis_av_rotate(ppc)(opc2)\n");
15617      return False;
15618   }
15619
15620   for( i = 0; i < num_words; i++ ) {
15621      left_bits[i]  = newTemp( Ity_I8 );
15622      right_bits[i] = newTemp( Ity_I8 );
15623      shift[i] = newTemp( Ity_I8 );
15624      mask[i]  = newTemp( Ity_V128 );
15625      tmp128[i] = newTemp( Ity_V128 );
15626      vA_word[i] = newTemp( Ity_V128 );
15627
15628      assign( shift[i],
15629              unop( Iop_64to8,
15630                    unop( Iop_V128to64,
15631                          binop( Iop_AndV128,
15632                                 binop( Iop_ShrV128,
15633                                        mkexpr( vB ),
15634                                        mkU8( (num_words - 1 - i )
15635                                              * word_size ) ),
15636                                 mkexpr( field_mask ) ) ) ) );
15637
15638      /* left_bits = 63 - mb.  Tells us how many bits to the left
15639       * of mb to clear. Note for a word left_bits = 32+mb, for a double
15640       * word left_bits = mb
15641       */
15642      assign( left_bits[i],
15643              unop( Iop_64to8,
15644                    binop( Iop_Add64,
15645                           mkU64( 64 - word_size ),
15646                           unop( Iop_V128to64,
15647                                 binop( Iop_AndV128,
15648                                        binop( Iop_ShrV128,
15649                                               mkexpr( vB ),
15650                                               mkU8( ( num_words - 1 - i )
15651                                                     * word_size + 16 ) ),
15652                                        mkexpr( field_mask ) ) ) ) ) );
15653      /* right_bits = 63 - me.  Tells us how many bits to the right
15654       * of me to clear. Note for a word, left_bits = me+32, for a double
15655       * word left_bits = me
15656       */
15657      assign( right_bits[i],
15658              unop( Iop_64to8,
15659                    binop( Iop_Sub64,
15660                           mkU64( word_size - 1 ),
15661                           unop( Iop_V128to64,
15662                                 binop( Iop_AndV128,
15663                                        binop( Iop_ShrV128,
15664                                               mkexpr( vB ),
15665                                               mkU8( ( num_words - 1 - i )
15666                                                     * word_size + 8 ) ),
15667                                        mkexpr( field_mask ) ) ) ) ) );
15668
15669      /* create mask for 32-bit word or 64-bit word */
15670      assign( mask[i],
15671              binop( Iop_64HLtoV128,
15672                     mkU64( 0 ),
15673                     binop( Iop_Shl64,
15674                            binop( Iop_Shr64,
15675                                   binop( Iop_Shr64,
15676                                          binop( Iop_Shl64,
15677                                                 mkU64( 0xFFFFFFFFFFFFFFFF ),
15678                                                 mkexpr( left_bits[i] ) ),
15679                                          mkexpr( left_bits[i] ) ),
15680                                   mkexpr( right_bits[i] ) ),
15681                            mkexpr( right_bits[i] ) ) ) );
15682
15683      /* Need to rotate vA using a left and right shift of vA OR'd together
15684       * then ANDed with the mask.
15685       */
15686      assign( vA_word[i], binop( Iop_AndV128,
15687                                 mkexpr( vA ),
15688                                 binop( Iop_ShlV128,
15689                                        binop( Iop_64HLtoV128,
15690                                               mkU64( 0 ),
15691                                               mkU64( word_mask ) ),
15692                                        mkU8( ( num_words - 1 - i )
15693                                              * word_size ) ) ) );
15694      assign( tmp128[i],
15695              binop( Iop_AndV128,
15696                     binop( Iop_ShlV128,
15697                            mkexpr( mask[i] ),
15698                            mkU8( ( num_words - 1 - i) * word_size ) ),
15699                     binop( Iop_OrV128,
15700                            binop( Iop_ShlV128,
15701                                   mkexpr( vA_word[i] ),
15702                                   mkexpr( shift[i] ) ),
15703                            binop( Iop_ShrV128,
15704                                   mkexpr( vA_word[i] ),
15705                                   unop( Iop_32to8,
15706                                         binop(Iop_Sub32,
15707                                               mkU32( word_size ),
15708                                               unop( Iop_8Uto32,
15709                                                     mkexpr( shift[i] ) ) )
15710                                         ) ) ) ) );
15711   }
15712
15713   switch (opc2) {
15714   case 0x85: // vrlwmi,  Vector Rotate Left Word then Mask Insert
15715      DIP("vrlwmi %d,%d,v%d", vT_addr, vA_addr, vB_addr);
15716
15717      assign( src3, getVReg( vT_addr ) );
15718      assign( mask128, unop( Iop_NotV128,
15719                             mkOr4_V128_expr( binop( Iop_ShlV128,
15720                                                     mkexpr( mask[0] ),
15721                                                     mkU8( 96 ) ),
15722                                              binop( Iop_ShlV128,
15723                                                     mkexpr( mask[1] ),
15724                                                     mkU8( 64 ) ),
15725                                              binop( Iop_ShlV128,
15726                                                     mkexpr( mask[2] ),
15727                                                     mkU8( 32 ) ),
15728                                              mkexpr( mask[3] ) ) ) );
15729      assign( vT, binop( Iop_OrV128,
15730                         binop( Iop_AndV128,
15731                                mkexpr( src3 ),
15732                                mkexpr( mask128 ) ),
15733                         mkOr4_V128( tmp128[0], tmp128[1],
15734                                     tmp128[2], tmp128[3] ) ) );
15735      break;
15736
15737   case 0xC5: // vrldmi,  Vector Rotate Left Double word then Mask Insert
15738      DIP("vrldmi %d,%d,v%d", vT_addr, vA_addr, vB_addr);
15739
15740      assign( src3, getVReg( vT_addr ) );
15741      assign( mask128, unop( Iop_NotV128,
15742                             binop( Iop_OrV128,
15743                                    binop( Iop_ShlV128,
15744                                           mkexpr( mask[0] ),
15745                                           mkU8( 64 ) ),
15746                                    mkexpr( mask[1] ) ) ) );
15747
15748      assign( vT, binop( Iop_OrV128,
15749                         binop( Iop_AndV128,
15750                                mkexpr( src3 ),
15751                                mkexpr( mask128 ) ),
15752                         binop( Iop_OrV128,
15753                                mkexpr( tmp128[0] ),
15754                                mkexpr( tmp128[1] ) ) ) );
15755      break;
15756
15757   case 0x185: // vrlwnm,  Vector Rotate Left Word then AND with Mask
15758      DIP("vrlwnm %d,%d,v%d", vT_addr, vA_addr, vB_addr);
15759      assign( vT, mkOr4_V128( tmp128[0], tmp128[1], tmp128[2], tmp128[3] ) );
15760      break;
15761
15762   case 0x1C5: // vrldnm,  Vector Rotate Left Doubleword then AND with Mask
15763      DIP("vrldnm %d,%d,v%d", vT_addr, vA_addr, vB_addr);
15764      assign( vT, binop( Iop_OrV128,
15765                         mkexpr( tmp128[0] ),
15766                         mkexpr( tmp128[1] ) ) );
15767      break;
15768   }
15769
15770   putVReg( vT_addr, mkexpr( vT ) );
15771   return True;
15772}
15773
15774/*
15775  AltiVec Vector Extract Element Instructions
15776*/
15777static Bool dis_av_extract_element ( UInt theInstr )
15778{
15779   /* VX-Form,
15780    * sorta destination and first source are GPR not vector registers
15781    */
15782
15783   UChar opc1    = ifieldOPC( theInstr );
15784   UChar rT_addr = ifieldRegDS( theInstr );
15785   UChar rA_addr = ifieldRegA( theInstr );
15786   UChar vB_addr = ifieldRegB( theInstr );
15787   UInt  opc2    = IFIELD( theInstr, 0, 11 );
15788
15789   IRTemp vB = newTemp( Ity_V128 );
15790   IRTemp rA = newTemp( Ity_I64 );
15791   IRTemp rT = newTemp( Ity_I64 );
15792
15793   assign( vB, getVReg( vB_addr ) );
15794   assign( rA, getIReg( rA_addr ) );
15795
15796   if ( opc1 != 0x4 ) {
15797      vex_printf("dis_av_extract_element(ppc)(instr)\n");
15798      return False;
15799   }
15800
15801   switch ( opc2 ) {
15802   case 0x60D: // vextublx, vector extract unsigned Byte Left-indexed
15803      DIP("vextublx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15804
15805      assign( rT, extract_field_from_vector( vB,
15806                                             binop( Iop_Sub64,
15807                                                    mkU64( 15 ),
15808                                                    mkexpr( rA ) ),
15809                                             0xFF ) );
15810
15811      break;
15812
15813   case 0x64D: // vextuhlx, vector extract unsigned Halfword Left-indexed
15814      DIP("vextuhlx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15815
15816      assign( rT, extract_field_from_vector( vB,
15817                                             binop( Iop_Sub64,
15818                                                    mkU64( 14 ),
15819                                                    mkexpr( rA ) ),
15820                                             0xFFFF ) );
15821      break;
15822
15823   case 0x68D: // vextuwlx, vector extract unsigned Word Left-indexed
15824      DIP("vextuwlx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15825
15826      assign( rT, extract_field_from_vector( vB,
15827                                             binop( Iop_Sub64,
15828                                                    mkU64( 12 ),
15829                                                    mkexpr( rA ) ),
15830                                             0xFFFFFFFF ) );
15831      break;
15832
15833   case 0x70D: // vextubrx, vector extract unsigned Byte Right-indexed
15834      DIP("vextubrx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15835
15836      assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFF ) );
15837      break;
15838
15839   case 0x74D: // vextuhrx, vector extract unsigned Halfword Right-indexed
15840      DIP("vextuhrx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15841
15842      assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFFFF ) );
15843      break;
15844
15845   case 0x78D: // vextuwrx, vector extract unsigned Word Right-indexed
15846      DIP("vextuwrx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15847
15848      assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFFFFFFFF ) );
15849      break;
15850
15851   default:
15852      vex_printf("dis_av_extract_element(ppc)(opc2)\n");
15853      return False;
15854   }
15855   putIReg( rT_addr, mkexpr( rT ) );
15856   return True;
15857}
15858
15859/*
15860 * VSX scalar and vector convert instructions
15861 */
15862static Bool
15863dis_vx_conv ( UInt theInstr, UInt opc2 )
15864{
15865   /* XX2-Form */
15866   UChar opc1 = ifieldOPC( theInstr );
15867   UChar XT = ifieldRegXT( theInstr );
15868   UChar XB = ifieldRegXB( theInstr );
15869   IRTemp xB, xB2;
15870   IRTemp b3, b2, b1, b0;
15871   xB = xB2 = IRTemp_INVALID;
15872
15873   if (opc1 != 0x3C) {
15874      vex_printf( "dis_vx_conv(ppc)(instr)\n" );
15875      return False;
15876   }
15877
15878   /* Create and assign temps only as needed for the given instruction. */
15879   switch (opc2) {
15880      // scalar double-precision floating point argument
15881      case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
15882         xB = newTemp(Ity_F64);
15883         assign( xB,
15884                 unop( Iop_ReinterpI64asF64,
15885                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
15886         break;
15887      // vector double-precision floating point arguments
15888      case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
15889
15890         xB = newTemp(Ity_F64);
15891         xB2 = newTemp(Ity_F64);
15892         assign( xB,
15893                 unop( Iop_ReinterpI64asF64,
15894                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
15895         assign( xB2,
15896                 unop( Iop_ReinterpI64asF64,
15897                       unop( Iop_V128to64, getVSReg( XB ) ) ) );
15898         break;
15899      // vector single precision or [un]signed integer word arguments
15900      case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
15901      case 0x1f0: case 0x1d0:
15902         b3 = b2 = b1 = b0 = IRTemp_INVALID;
15903         breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
15904         break;
15905         // vector [un]signed integer doubleword argument
15906      case 0x3f0: case 0x370: case 0x3d0: case 0x350:
15907         xB = newTemp(Ity_I64);
15908         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
15909         xB2 = newTemp(Ity_I64);
15910         assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
15911         break;
15912      // scalar [un]signed integer doubleword argument
15913      case 0x250: case 0x270: case 0x2D0: case 0x2F0:
15914         xB = newTemp(Ity_I64);
15915         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
15916         break;
15917      // scalar single precision argument
15918      case 0x292: // xscvspdp
15919         xB  = newTemp(Ity_I32);
15920
15921         assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
15922                                                  unop( Iop_V128HIto64,
15923                                                        getVSReg( XB ) ) ) ) );
15924         break;
15925      case 0x296: // xscvspdpn (non signaling version of xscvpdp)
15926         xB = newTemp(Ity_I32);
15927         assign( xB,
15928                 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
15929         break;
15930
15931      /* Certain instructions have their complete implementation in the main switch statement
15932       * that follows this one; thus we have a "do nothing" case for those instructions here.
15933       */
15934      case 0x170: case 0x150:
15935         break; // do nothing
15936
15937      default:
15938         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
15939         return False;
15940   }
15941
15942
15943   switch (opc2) {
15944      case 0x2B0:
15945         // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
15946         //             to Signed Integer Doubleword format with Saturate)
15947         DIP("xscvdpsxds v%u,v%u\n", XT, XB);
15948         putVSReg( XT,
15949                   binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
15950                                                 mkU32( Irrm_ZERO ),
15951                                                 mkexpr( xB ) ), mkU64( 0 ) ) );
15952         break;
15953      case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
15954                  //             Convert to Signed Integer Word format with Saturate)
15955         DIP("xscvdpsxws v%u,v%u\n", XT, XB);
15956         putVSReg( XT,
15957                   binop( Iop_64HLtoV128,
15958                          unop( Iop_32Sto64,
15959                                binop( Iop_F64toI32S,
15960                                       mkU32( Irrm_ZERO ),
15961                                       mkexpr( xB ) ) ),
15962                                       mkU64( 0ULL ) ) );
15963         break;
15964      case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
15965                  //             to Unsigned Integer Doubleword format with Saturate)
15966         DIP("xscvdpuxds v%u,v%u\n", XT, XB);
15967         putVSReg( XT,
15968                   binop( Iop_64HLtoV128,
15969                          binop( Iop_F64toI64U,
15970                                 mkU32( Irrm_ZERO ),
15971                                 mkexpr( xB ) ),
15972                                 mkU64( 0ULL ) ) );
15973         break;
15974      case 0x270:
15975         // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
15976         //             to Single-Precision format)
15977         DIP("xscvsxdsp v%u,v%u\n", XT, XB);
15978         putVSReg( XT,
15979                   binop( Iop_64HLtoV128,
15980                          unop( Iop_ReinterpF64asI64,
15981                                binop( Iop_RoundF64toF32,
15982                                       get_IR_roundingmode(),
15983                                       binop( Iop_I64StoF64,
15984                                              get_IR_roundingmode(),
15985                                              mkexpr( xB ) ) ) ),
15986                          mkU64( 0 ) ) );
15987         break;
15988      case 0x2F0:
15989         // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
15990         //            Double-Precision format)
15991         DIP("xscvsxddp v%u,v%u\n", XT, XB);
15992         putVSReg( XT,
15993                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
15994                                                binop( Iop_I64StoF64, get_IR_roundingmode(),
15995                                                       mkexpr( xB ) ) ),
15996                                                       mkU64( 0 ) ) );
15997         break;
15998      case 0x250:
15999         // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
16000         //            Doubleword to Singel-Precision format)
16001         DIP("xscvuxdsp v%u,v%u\n", XT, XB);
16002         putVSReg( XT,
16003                   binop( Iop_64HLtoV128,
16004                          unop( Iop_ReinterpF64asI64,
16005                                binop( Iop_RoundF64toF32,
16006                                       get_IR_roundingmode(),
16007                                       binop( Iop_I64UtoF64,
16008                                              get_IR_roundingmode(),
16009                                              mkexpr( xB ) ) ) ),
16010                          mkU64( 0 ) ) );
16011         break;
16012      case 0x2D0:
16013         // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
16014         //            Double-Precision format)
16015         DIP("xscvuxddp v%u,v%u\n", XT, XB);
16016         putVSReg( XT,
16017                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
16018                                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
16019                                                       mkexpr( xB ) ) ),
16020                                                       mkU64( 0 ) ) );
16021         break;
16022      case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
16023                  //             to Signed Integer Word format with Saturate)
16024      {
16025         IRTemp hiResult_32 = newTemp(Ity_I32);
16026         IRTemp loResult_32 = newTemp(Ity_I32);
16027         IRExpr* rmZero = mkU32(Irrm_ZERO);
16028
16029         DIP("xvcvdpsxws v%u,v%u\n",  XT, XB);
16030         assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
16031         assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
16032         putVSReg( XT,
16033                   binop( Iop_64HLtoV128,
16034                          unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
16035                          unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
16036         break;
16037      }
16038      case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
16039         //  (VSX Vector truncate Single-Precision to integer and
16040         //   Convert to [Un]signed Integer Word format with Saturate)
16041      {
16042         IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
16043         IRTemp tempResult = newTemp(Ity_V128);
16044         IRTemp res0 = newTemp(Ity_I32);
16045         IRTemp res1 = newTemp(Ity_I32);
16046         IRTemp res2 = newTemp(Ity_I32);
16047         IRTemp res3 = newTemp(Ity_I32);
16048         IRTemp hi64 = newTemp(Ity_I64);
16049         IRTemp lo64 = newTemp(Ity_I64);
16050         Bool un_signed = (opc2 == 0x110);
16051         IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
16052
16053         DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", XT, XB);
16054         /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
16055          * then result is set to 0x80000000.  */
16056         assign(tempResult, unop(op, getVSReg(XB)));
16057         assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
16058         assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
16059         assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
16060         assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
16061         assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
16062         assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
16063
16064         b3_result = IRExpr_ITE(is_NaN(Ity_I32, b3),
16065                                // then: result is 0x{8|0}80000000
16066                                mkU32(un_signed ? 0x00000000 : 0x80000000),
16067                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16068                                mkexpr(res3));
16069         b2_result = IRExpr_ITE(is_NaN(Ity_I32, b2),
16070                                // then: result is 0x{8|0}80000000
16071                                mkU32(un_signed ? 0x00000000 : 0x80000000),
16072                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16073                                mkexpr(res2));
16074         b1_result = IRExpr_ITE(is_NaN(Ity_I32, b1),
16075                                // then: result is 0x{8|0}80000000
16076                                mkU32(un_signed ? 0x00000000 : 0x80000000),
16077                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16078                                mkexpr(res1));
16079         b0_result = IRExpr_ITE(is_NaN(Ity_I32, b0),
16080                                // then: result is 0x{8|0}80000000
16081                                mkU32(un_signed ? 0x00000000 : 0x80000000),
16082                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16083                                mkexpr(res0));
16084
16085         putVSReg( XT,
16086                   binop( Iop_64HLtoV128,
16087                          binop( Iop_32HLto64, b3_result, b2_result ),
16088                          binop( Iop_32HLto64, b1_result, b0_result ) ) );
16089         break;
16090      }
16091      case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
16092                  //           Convert to Single-Precision format
16093         DIP("xscvdpsp v%u,v%u\n", XT, XB);
16094         putVSReg( XT,
16095                   binop( Iop_64HLtoV128,
16096                          binop( Iop_32HLto64,
16097                                 unop( Iop_ReinterpF32asI32,
16098                                       unop( Iop_TruncF64asF32,
16099                                             binop( Iop_RoundF64toF32,
16100                                                    get_IR_roundingmode(),
16101                                                    mkexpr( xB ) ) ) ),
16102                                 mkU32( 0 ) ),
16103                          mkU64( 0ULL ) ) );
16104         break;
16105      case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
16106                              vector Single-Precision non-signalling */
16107         DIP("xscvdpspn v%u,v%u\n", XT, XB);
16108         putVSReg( XT,
16109                   binop( Iop_64HLtoV128,
16110                          binop( Iop_32HLto64,
16111                                 unop( Iop_ReinterpF32asI32,
16112                                       unop( Iop_TruncF64asF32,
16113                                             mkexpr( xB ) ) ),
16114                                 mkU32( 0 ) ),
16115                          mkU64( 0ULL ) ) );
16116         break;
16117      case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
16118                  //             and Convert to Unsigned Integer Word format with Saturate)
16119         DIP("xscvdpuxws v%u,v%u\n", XT, XB);
16120         putVSReg( XT,
16121                   binop( Iop_64HLtoV128,
16122                          binop( Iop_32HLto64,
16123                                 mkU32( 0 ),
16124                                 binop( Iop_F64toI32U,
16125                                        mkU32( Irrm_ZERO ),
16126                                        mkexpr( xB ) ) ),
16127                          mkU64( 0ULL ) ) );
16128         break;
16129      case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
16130         DIP("xscvspdp v%u,v%u\n", XT, XB);
16131         putVSReg( XT,
16132                   binop( Iop_64HLtoV128,
16133                          unop( Iop_ReinterpF64asI64,
16134                                unop( Iop_F32toF64,
16135                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
16136                          mkU64( 0ULL ) ) );
16137         break;
16138      case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
16139         DIP("xscvspdpn v%u,v%u\n", XT, XB);
16140         putVSReg( XT,
16141                   binop( Iop_64HLtoV128,
16142                          unop( Iop_ReinterpF64asI64,
16143                                unop( Iop_F32toF64,
16144                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
16145                                      mkU64( 0ULL ) ) );
16146         break;
16147      case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
16148                  //           and Convert to Single-Precision format)
16149         DIP("xvcvdpsp v%u,v%u\n", XT, XB);
16150         putVSReg( XT,
16151                   binop( Iop_64HLtoV128,
16152                          binop( Iop_32HLto64,
16153                                 unop( Iop_ReinterpF32asI32,
16154                                       unop( Iop_TruncF64asF32,
16155                                             binop( Iop_RoundF64toF32,
16156                                                    get_IR_roundingmode(),
16157                                                    mkexpr( xB ) ) ) ),
16158                                 mkU32( 0 ) ),
16159                          binop( Iop_32HLto64,
16160                                 unop( Iop_ReinterpF32asI32,
16161                                       unop( Iop_TruncF64asF32,
16162                                             binop( Iop_RoundF64toF32,
16163                                                    get_IR_roundingmode(),
16164                                                    mkexpr( xB2 ) ) ) ),
16165                                 mkU32( 0 ) ) ) );
16166         break;
16167      case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
16168                  //             and Convert to Unsigned Integer Doubleword format
16169                  //             with Saturate)
16170         DIP("xvcvdpuxds v%u,v%u\n", XT, XB);
16171         putVSReg( XT,
16172                   binop( Iop_64HLtoV128,
16173                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
16174                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
16175         break;
16176      case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
16177                  //             Convert to Unsigned Integer Word format with Saturate)
16178         DIP("xvcvdpuxws v%u,v%u\n", XT, XB);
16179         putVSReg( XT,
16180                   binop( Iop_64HLtoV128,
16181                          binop( Iop_32HLto64,
16182                                 binop( Iop_F64toI32U,
16183                                        mkU32( Irrm_ZERO ),
16184                                        mkexpr( xB ) ),
16185                                 mkU32( 0 ) ),
16186                          binop( Iop_32HLto64,
16187                                 binop( Iop_F64toI32U,
16188                                        mkU32( Irrm_ZERO ),
16189                                        mkexpr( xB2 ) ),
16190                                 mkU32( 0 ) ) ) );
16191         break;
16192      case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
16193         DIP("xvcvspdp v%u,v%u\n", XT, XB);
16194         putVSReg( XT,
16195                   binop( Iop_64HLtoV128,
16196                          unop( Iop_ReinterpF64asI64,
16197                                unop( Iop_F32toF64,
16198                                      unop( Iop_ReinterpI32asF32,
16199                                            handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
16200                          unop( Iop_ReinterpF64asI64,
16201                                unop( Iop_F32toF64,
16202                                      unop( Iop_ReinterpI32asF32,
16203                                            handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
16204         break;
16205      case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
16206                  //           Convert to Signed Integer Doubleword format with Saturate)
16207         DIP("xvcvspsxds v%u,v%u\n", XT, XB);
16208         putVSReg( XT,
16209                   binop( Iop_64HLtoV128,
16210                          binop( Iop_F64toI64S,
16211                                 mkU32( Irrm_ZERO ),
16212                                 unop( Iop_F32toF64,
16213                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
16214                          binop( Iop_F64toI64S,
16215                                 mkU32( Irrm_ZERO ),
16216                                 unop( Iop_F32toF64,
16217                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
16218         break;
16219      case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
16220                  //            Convert to Unsigned Integer Doubleword format with Saturate)
16221         DIP("xvcvspuxds v%u,v%u\n", XT, XB);
16222         putVSReg( XT,
16223                   binop( Iop_64HLtoV128,
16224                          binop( Iop_F64toI64U,
16225                                 mkU32( Irrm_ZERO ),
16226                                 unop( Iop_F32toF64,
16227                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
16228                          binop( Iop_F64toI64U,
16229                                 mkU32( Irrm_ZERO ),
16230                                 unop( Iop_F32toF64,
16231                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
16232         break;
16233      case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
16234                  //             Convert to Signed Integer Doubleword format with Saturate)
16235         DIP("xvcvdpsxds v%u,v%u\n", XT, XB);
16236         putVSReg( XT,
16237                   binop( Iop_64HLtoV128,
16238                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
16239                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
16240         break;
16241      case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
16242                  //            to Double-Precision format)
16243         DIP("xvcvsxddp v%u,v%u\n", XT, XB);
16244         putVSReg( XT,
16245                   binop( Iop_64HLtoV128,
16246                          unop( Iop_ReinterpF64asI64,
16247                                binop( Iop_I64StoF64,
16248                                       get_IR_roundingmode(),
16249                                       mkexpr( xB ) ) ),
16250                          unop( Iop_ReinterpF64asI64,
16251                                binop( Iop_I64StoF64,
16252                                       get_IR_roundingmode(),
16253                                       mkexpr( xB2 ) ) ) ) );
16254         break;
16255      case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
16256                  //            to Double-Precision format)
16257         DIP("xvcvuxddp v%u,v%u\n", XT, XB);
16258         putVSReg( XT,
16259                   binop( Iop_64HLtoV128,
16260                          unop( Iop_ReinterpF64asI64,
16261                                binop( Iop_I64UtoF64,
16262                                       get_IR_roundingmode(),
16263                                       mkexpr( xB ) ) ),
16264                          unop( Iop_ReinterpF64asI64,
16265                                binop( Iop_I64UtoF64,
16266                                       get_IR_roundingmode(),
16267                                       mkexpr( xB2 ) ) ) ) );
16268
16269         break;
16270      case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
16271                  //            to Single-Precision format)
16272         DIP("xvcvsxddp v%u,v%u\n",  XT, XB);
16273         putVSReg( XT,
16274                   binop( Iop_64HLtoV128,
16275                          binop( Iop_32HLto64,
16276                                 unop( Iop_ReinterpF32asI32,
16277                                       unop( Iop_TruncF64asF32,
16278                                             binop( Iop_RoundF64toF32,
16279                                                    get_IR_roundingmode(),
16280                                                    binop( Iop_I64StoF64,
16281                                                           get_IR_roundingmode(),
16282                                                           mkexpr( xB ) ) ) ) ),
16283                                 mkU32( 0 ) ),
16284                          binop( Iop_32HLto64,
16285                                 unop( Iop_ReinterpF32asI32,
16286                                       unop( Iop_TruncF64asF32,
16287                                             binop( Iop_RoundF64toF32,
16288                                                    get_IR_roundingmode(),
16289                                                    binop( Iop_I64StoF64,
16290                                                           get_IR_roundingmode(),
16291                                                           mkexpr( xB2 ) ) ) ) ),
16292                                 mkU32( 0 ) ) ) );
16293         break;
16294      case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
16295                  //            to Single-Precision format)
16296         DIP("xvcvuxddp v%u,v%u\n", XT, XB);
16297         putVSReg( XT,
16298                   binop( Iop_64HLtoV128,
16299                          binop( Iop_32HLto64,
16300                                 unop( Iop_ReinterpF32asI32,
16301                                       unop( Iop_TruncF64asF32,
16302                                             binop( Iop_RoundF64toF32,
16303                                                    get_IR_roundingmode(),
16304                                                    binop( Iop_I64UtoF64,
16305                                                           get_IR_roundingmode(),
16306                                                           mkexpr( xB ) ) ) ) ),
16307                                 mkU32( 0 ) ),
16308                          binop( Iop_32HLto64,
16309                                 unop( Iop_ReinterpF32asI32,
16310                                       unop( Iop_TruncF64asF32,
16311                                             binop( Iop_RoundF64toF32,
16312                                                    get_IR_roundingmode(),
16313                                                    binop( Iop_I64UtoF64,
16314                                                           get_IR_roundingmode(),
16315                                                           mkexpr( xB2 ) ) ) ) ),
16316                                 mkU32( 0 ) ) ) );
16317         break;
16318
16319      case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
16320         DIP("xvcvsxwdp v%u,v%u\n",  XT, XB);
16321         putVSReg( XT,
16322                   binop( Iop_64HLtoV128,
16323                          unop( Iop_ReinterpF64asI64,
16324                                binop( Iop_I64StoF64, get_IR_roundingmode(),
16325                                       unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
16326                          unop( Iop_ReinterpF64asI64,
16327                                binop( Iop_I64StoF64, get_IR_roundingmode(),
16328                                       unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
16329         break;
16330      case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
16331         DIP("xvcvuxwdp v%u,v%u\n",  XT, XB);
16332         putVSReg( XT,
16333                   binop( Iop_64HLtoV128,
16334                          unop( Iop_ReinterpF64asI64,
16335                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
16336                                       unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
16337                          unop( Iop_ReinterpF64asI64,
16338                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
16339                                       unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
16340         break;
16341      case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
16342         DIP("xvcvsxwsp v%u,v%u\n",  XT, XB);
16343         putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
16344         break;
16345      case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
16346         DIP("xvcvuxwsp v%u,v%u\n",  XT, XB);
16347         putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
16348         break;
16349
16350      default:
16351         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
16352         return False;
16353   }
16354   return True;
16355}
16356
16357/*
16358 * VSX vector Double Precision Floating Point Arithmetic Instructions
16359 */
16360static Bool
16361dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
16362{
16363   /* XX3-Form */
16364   UChar opc1 = ifieldOPC( theInstr );
16365   UChar XT = ifieldRegXT( theInstr );
16366   UChar XA = ifieldRegXA( theInstr );
16367   UChar XB = ifieldRegXB( theInstr );
16368   IRExpr* rm = get_IR_roundingmode();
16369   IRTemp frA = newTemp(Ity_F64);
16370   IRTemp frB = newTemp(Ity_F64);
16371   IRTemp frA2 = newTemp(Ity_F64);
16372   IRTemp frB2 = newTemp(Ity_F64);
16373
16374   if (opc1 != 0x3C) {
16375      vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
16376      return False;
16377   }
16378
16379   assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
16380   assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
16381   assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
16382   assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
16383
16384   switch (opc2) {
16385      case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
16386      case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
16387      case 0x180: // xvadddp (VSX Vector Add Double-Precision)
16388      case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
16389      {
16390         IROp mOp;
16391         const HChar * oper_name;
16392         switch (opc2) {
16393            case 0x1E0:
16394               mOp = Iop_DivF64;
16395               oper_name = "div";
16396               break;
16397            case 0x1C0:
16398               mOp = Iop_MulF64;
16399               oper_name = "mul";
16400               break;
16401            case 0x180:
16402               mOp = Iop_AddF64;
16403               oper_name = "add";
16404               break;
16405            case 0x1A0:
16406               mOp = Iop_SubF64;
16407               oper_name = "sub";
16408               break;
16409
16410            default:
16411               vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
16412         }
16413         IRTemp hiResult = newTemp(Ity_I64);
16414         IRTemp loResult = newTemp(Ity_I64);
16415         DIP("xv%sdp v%d,v%d,v%d\n", oper_name, XT, XA, XB);
16416
16417         assign( hiResult,
16418                 unop( Iop_ReinterpF64asI64,
16419                       triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
16420         assign( loResult,
16421                 unop( Iop_ReinterpF64asI64,
16422                       triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
16423         putVSReg( XT,
16424                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
16425         break;
16426      }
16427      case 0x196: // xvsqrtdp
16428      {
16429         IRTemp hiResult = newTemp(Ity_I64);
16430         IRTemp loResult = newTemp(Ity_I64);
16431         DIP("xvsqrtdp v%d,v%d\n", XT, XB);
16432
16433         assign( hiResult,
16434                 unop( Iop_ReinterpF64asI64,
16435                       binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
16436         assign( loResult,
16437                 unop( Iop_ReinterpF64asI64,
16438                       binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
16439         putVSReg( XT,
16440                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
16441         break;
16442      }
16443      case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
16444      case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
16445      case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
16446      case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
16447      {
16448         /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
16449          *    XT == FRC
16450          *    XA == FRA
16451          *    XB == FRB
16452          *
16453          * and for xvm{add|sub}adp . . .
16454          *    XT == FRB
16455          *    XA == FRA
16456          *    XB == FRC
16457          */
16458         Bool negate;
16459         IROp mOp = Iop_INVALID;
16460         const HChar * oper_name = NULL;
16461         Bool mdp = False;
16462
16463         switch (opc2) {
16464            case 0x184: case 0x1A4:
16465            case 0x384: case 0x3A4:
16466               mOp = Iop_MAddF64;
16467               oper_name = "add";
16468               mdp = (opc2 & 0x0FF) == 0x0A4;
16469               break;
16470
16471            case 0x1C4: case 0x1E4:
16472            case 0x3C4: case 0x3E4:
16473               mOp = Iop_MSubF64;
16474               oper_name = "sub";
16475               mdp = (opc2 & 0x0FF) == 0x0E4;
16476               break;
16477
16478            default:
16479               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
16480         }
16481
16482         switch (opc2) {
16483            case 0x384: case 0x3A4:
16484            case 0x3C4: case 0x3E4:
16485               negate = True;
16486               break;
16487            default:
16488               negate = False;
16489         }
16490         IRTemp hiResult = newTemp(Ity_I64);
16491         IRTemp loResult = newTemp(Ity_I64);
16492         IRTemp frT = newTemp(Ity_F64);
16493         IRTemp frT2 = newTemp(Ity_F64);
16494         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
16495             XT, XA, XB);
16496         assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
16497         assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
16498
16499         assign( hiResult,
16500                 unop( Iop_ReinterpF64asI64,
16501                       qop( mOp,
16502                            rm,
16503                            mkexpr( frA ),
16504                            mkexpr( mdp ? frT : frB ),
16505                            mkexpr( mdp ? frB : frT ) ) ) );
16506         assign( loResult,
16507                 unop( Iop_ReinterpF64asI64,
16508                       qop( mOp,
16509                            rm,
16510                            mkexpr( frA2 ),
16511                            mkexpr( mdp ? frT2 : frB2 ),
16512                            mkexpr( mdp ? frB2 : frT2 ) ) ) );
16513         putVSReg( XT,
16514                   binop( Iop_64HLtoV128,
16515                          mkexpr( negate ? getNegatedResult( hiResult )
16516                                         : hiResult ),
16517                          mkexpr( negate ? getNegatedResult( loResult )
16518                                         : loResult ) ) );
16519         break;
16520      }
16521      case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
16522      {
16523         IRTemp frBHi_I64 = newTemp(Ity_I64);
16524         IRTemp frBLo_I64 = newTemp(Ity_I64);
16525         IRTemp flagsHi = newTemp(Ity_I32);
16526         IRTemp flagsLo = newTemp(Ity_I32);
16527         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
16528         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
16529         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
16530
16531         DIP("xvtsqrtdp cr%d,v%d\n", crfD, XB);
16532         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
16533         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
16534         do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
16535         do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
16536         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
16537          * where fl_flag == 1 on ppc64.
16538          */
16539         assign( flagsHi,
16540                 binop( Iop_Or32,
16541                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16542                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
16543                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
16544         assign( flagsLo,
16545                 binop( Iop_Or32,
16546                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16547                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
16548                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
16549         putGST_field( PPC_GST_CR,
16550                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
16551                       crfD );
16552         break;
16553      }
16554      case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
16555      {
16556         IRTemp frBHi_I64 = newTemp(Ity_I64);
16557         IRTemp frBLo_I64 = newTemp(Ity_I64);
16558         IRTemp frAHi_I64 = newTemp(Ity_I64);
16559         IRTemp frALo_I64 = newTemp(Ity_I64);
16560         IRTemp flagsHi = newTemp(Ity_I32);
16561         IRTemp flagsLo = newTemp(Ity_I32);
16562         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
16563         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
16564         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
16565
16566         DIP("xvtdivdp cr%d,v%d,v%d\n", crfD, XA, XB);
16567         assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
16568         assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
16569         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
16570         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
16571
16572         _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
16573         _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
16574         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
16575          * where fl_flag == 1 on ppc64.
16576          */
16577         assign( flagsHi,
16578                 binop( Iop_Or32,
16579                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16580                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
16581                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
16582         assign( flagsLo,
16583                 binop( Iop_Or32,
16584                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16585                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
16586                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
16587         putGST_field( PPC_GST_CR,
16588                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
16589                       crfD );
16590         break;
16591      }
16592
16593      default:
16594         vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
16595         return False;
16596   }
16597   return True;
16598}
16599
16600/*
16601 * VSX vector Single Precision Floating Point Arithmetic Instructions
16602 */
16603static Bool
16604dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
16605{
16606   /* XX3-Form */
16607   UChar opc1 = ifieldOPC( theInstr );
16608   UChar XT = ifieldRegXT( theInstr );
16609   UChar XA = ifieldRegXA( theInstr );
16610   UChar XB = ifieldRegXB( theInstr );
16611   IRExpr* rm = get_IR_roundingmode();
16612   IRTemp a3, a2, a1, a0;
16613   IRTemp b3, b2, b1, b0;
16614   IRTemp res0 = newTemp(Ity_I32);
16615   IRTemp res1 = newTemp(Ity_I32);
16616   IRTemp res2 = newTemp(Ity_I32);
16617   IRTemp res3 = newTemp(Ity_I32);
16618
16619   a3 = a2 = a1 = a0 = IRTemp_INVALID;
16620   b3 = b2 = b1 = b0 = IRTemp_INVALID;
16621
16622   if (opc1 != 0x3C) {
16623      vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
16624      return False;
16625   }
16626
16627   switch (opc2) {
16628      case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
16629         DIP("xvaddsp v%d,v%d,v%d\n", XT, XA, XB);
16630         // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
16631         putVSReg( XT, triop(Iop_Add32Fx4, rm,
16632                             getVSReg( XA ), getVSReg( XB )) );
16633         break;
16634
16635      case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
16636         DIP("xvmulsp v%d,v%d,v%d\n", XT, XA, XB);
16637         // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
16638         putVSReg( XT, triop(Iop_Mul32Fx4, rm,
16639                             getVSReg( XA ), getVSReg( XB )) );
16640         break;
16641
16642      case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
16643         DIP("xvsubsp v%d,v%d,v%d\n", XT, XA, XB);
16644         // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
16645         putVSReg( XT, triop(Iop_Sub32Fx4, rm,
16646                             getVSReg( XA ), getVSReg( XB )) );
16647         break;
16648
16649      case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
16650      {
16651         /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
16652          * So there are two choices:
16653          *   1. Implement the xvdivsp with a native insn; or
16654          *   2. Extract the 4 single precision floats from each vector
16655          *      register inputs and perform fdivs on each pair
16656          * I will do the latter, due to the general philosophy of
16657          * reusing existing implementations when practical.
16658          */
16659         DIP("xvdivsp v%d,v%d,v%d\n", XT, XA, XB);
16660         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
16661         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
16662
16663         assign( res0,
16664              unop( Iop_ReinterpF32asI32,
16665                    unop( Iop_TruncF64asF32,
16666                          triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
16667         assign( res1,
16668                 unop( Iop_ReinterpF32asI32,
16669                       unop( Iop_TruncF64asF32,
16670                             triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
16671         assign( res2,
16672                 unop( Iop_ReinterpF32asI32,
16673                       unop( Iop_TruncF64asF32,
16674                             triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
16675         assign( res3,
16676                 unop( Iop_ReinterpF32asI32,
16677                       unop( Iop_TruncF64asF32,
16678                             triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
16679
16680         putVSReg( XT,
16681                   binop( Iop_64HLtoV128,
16682                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
16683                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
16684         break;
16685      }
16686      case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
16687      {
16688         DIP("xvsqrtsp v%d,v%d\n", XT, XB);
16689         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
16690         /* Note: The native xvsqrtsp insruction does not always give the same precision
16691          * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
16692          * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
16693          * to the actual instruction.
16694          */
16695
16696         assign( res0,
16697                 unop( Iop_ReinterpF32asI32,
16698                       unop( Iop_TruncF64asF32,
16699                             binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
16700         assign( res1,
16701                 unop( Iop_ReinterpF32asI32,
16702                       unop( Iop_TruncF64asF32,
16703                             binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
16704         assign( res2,
16705                 unop( Iop_ReinterpF32asI32,
16706                       unop( Iop_TruncF64asF32,
16707                             binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
16708         assign( res3,
16709                 unop( Iop_ReinterpF32asI32,
16710                       unop( Iop_TruncF64asF32,
16711                             binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
16712
16713         putVSReg( XT,
16714                   binop( Iop_64HLtoV128,
16715                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
16716                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
16717         break;
16718      }
16719
16720      case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
16721      case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
16722      case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
16723      case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
16724      {
16725         IRTemp t3, t2, t1, t0;
16726         Bool msp = False;
16727         Bool negate;
16728         const HChar * oper_name = NULL;
16729         IROp mOp = Iop_INVALID;
16730         switch (opc2) {
16731            case 0x104: case 0x124:
16732            case 0x304: case 0x324:
16733               msp = (opc2 & 0x0FF) == 0x024;
16734               mOp = Iop_MAddF64r32;
16735               oper_name = "madd";
16736               break;
16737
16738            case 0x144: case 0x164:
16739            case 0x344: case 0x364:
16740               msp = (opc2 & 0x0FF) == 0x064;
16741               mOp = Iop_MSubF64r32;
16742               oper_name = "sub";
16743               break;
16744
16745            default:
16746               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
16747         }
16748
16749         switch (opc2) {
16750            case 0x304: case 0x324:
16751            case 0x344: case 0x364:
16752               negate = True;
16753               break;
16754
16755            default:
16756               negate = False;
16757         }
16758
16759         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name,
16760             msp ? "msp" : "asp", XT, XA, XB);
16761
16762         t3 = t2 = t1 = t0 = IRTemp_INVALID;
16763         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
16764         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
16765         breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
16766
16767         assign( res0,
16768                 unop( Iop_ReinterpF32asI32,
16769                       unop( Iop_TruncF64asF32,
16770                             qop( mOp,
16771                                  rm,
16772                                  mkexpr( a0 ),
16773                                  mkexpr( msp ? t0 : b0 ),
16774                                  mkexpr( msp ? b0 : t0 ) ) ) ) );
16775         assign( res1,
16776                 unop( Iop_ReinterpF32asI32,
16777                       unop( Iop_TruncF64asF32,
16778                             qop( mOp,
16779                                  rm,
16780                                  mkexpr( a1 ),
16781                                  mkexpr( msp ? t1 : b1 ),
16782                                  mkexpr( msp ? b1 : t1 ) ) ) ) );
16783         assign( res2,
16784                 unop( Iop_ReinterpF32asI32,
16785                       unop( Iop_TruncF64asF32,
16786                             qop( mOp,
16787                                  rm,
16788                                  mkexpr( a2 ),
16789                                  mkexpr( msp ? t2 : b2 ),
16790                                  mkexpr( msp ? b2 : t2 ) ) ) ) );
16791         assign( res3,
16792                 unop( Iop_ReinterpF32asI32,
16793                       unop( Iop_TruncF64asF32,
16794                             qop( mOp,
16795                                  rm,
16796                                  mkexpr( a3 ),
16797                                  mkexpr( msp ? t3 : b3 ),
16798                                  mkexpr( msp ? b3 : t3 ) ) ) ) );
16799
16800         putVSReg( XT,
16801                   binop( Iop_64HLtoV128,
16802                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
16803                                 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
16804                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
16805                                 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
16806
16807         break;
16808      }
16809      case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
16810      {
16811         IRTemp flags0 = newTemp(Ity_I32);
16812         IRTemp flags1 = newTemp(Ity_I32);
16813         IRTemp flags2 = newTemp(Ity_I32);
16814         IRTemp flags3 = newTemp(Ity_I32);
16815         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
16816         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
16817         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
16818         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
16819         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
16820         DIP("xvtsqrtsp cr%d,v%d\n", crfD, XB);
16821
16822         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
16823         do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
16824         do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
16825         do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
16826         do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
16827
16828         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
16829          * where fl_flag == 1 on ppc64.
16830          */
16831         assign( flags0,
16832                 binop( Iop_Or32,
16833                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16834                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
16835                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
16836         assign( flags1,
16837                 binop( Iop_Or32,
16838                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16839                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
16840                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
16841         assign( flags2,
16842                 binop( Iop_Or32,
16843                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16844                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
16845                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
16846         assign( flags3,
16847                 binop( Iop_Or32,
16848                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16849                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
16850                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
16851         putGST_field( PPC_GST_CR,
16852                       binop( Iop_Or32,
16853                              mkexpr( flags0 ),
16854                              binop( Iop_Or32,
16855                                     mkexpr( flags1 ),
16856                                     binop( Iop_Or32,
16857                                            mkexpr( flags2 ),
16858                                            mkexpr( flags3 ) ) ) ),
16859                       crfD );
16860
16861         break;
16862      }
16863      case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
16864      {
16865         IRTemp flags0 = newTemp(Ity_I32);
16866         IRTemp flags1 = newTemp(Ity_I32);
16867         IRTemp flags2 = newTemp(Ity_I32);
16868         IRTemp flags3 = newTemp(Ity_I32);
16869         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
16870         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
16871         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
16872         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
16873         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
16874         DIP("xvtdivsp cr%d,v%d,v%d\n", crfD, XA, XB);
16875
16876         breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
16877         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
16878         _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
16879         _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
16880         _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
16881         _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
16882
16883         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
16884          * where fl_flag == 1 on ppc64.
16885          */
16886         assign( flags0,
16887                 binop( Iop_Or32,
16888                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16889                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
16890                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
16891         assign( flags1,
16892                 binop( Iop_Or32,
16893                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16894                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
16895                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
16896         assign( flags2,
16897                 binop( Iop_Or32,
16898                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16899                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
16900                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
16901         assign( flags3,
16902                 binop( Iop_Or32,
16903                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
16904                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
16905                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
16906         putGST_field( PPC_GST_CR,
16907                       binop( Iop_Or32,
16908                              mkexpr( flags0 ),
16909                              binop( Iop_Or32,
16910                                     mkexpr( flags1 ),
16911                                     binop( Iop_Or32,
16912                                            mkexpr( flags2 ),
16913                                            mkexpr( flags3 ) ) ) ),
16914                       crfD );
16915
16916         break;
16917      }
16918
16919      default:
16920         vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
16921         return False;
16922   }
16923   return True;
16924}
16925
16926/*
16927 * Vector Population Count/bit matrix transpose
16928 */
16929static Bool
16930dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
16931{
16932   UChar vRB_addr = ifieldRegB(theInstr);
16933   UChar vRT_addr = ifieldRegDS(theInstr);
16934   UChar opc1 = ifieldOPC( theInstr );
16935   IRTemp vB = newTemp(Ity_V128);
16936   assign( vB, getVReg(vRB_addr));
16937
16938   if (opc1 != 0x4) {
16939      vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
16940      return False;
16941   }
16942
16943   switch (opc2) {
16944      case 0x702:    // vclzb
16945         DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
16946         putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) );
16947         break;
16948
16949      case 0x742:    // vclzh
16950         DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
16951         putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) );
16952         break;
16953
16954      case 0x782:    // vclzw
16955         DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
16956         putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) );
16957         break;
16958
16959      case 0x7C2:    // vclzd
16960         DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
16961         putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
16962         break;
16963
16964      case 0x703:    // vpopcntb
16965      {
16966         /* Break vector into 32-bit words and do the population count
16967          * on byte in the words
16968          */
16969         IRType ty = Ity_I32;
16970         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
16971         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
16972         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
16973         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
16974
16975         DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
16976         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
16977         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   BYTE);
16978         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  BYTE);
16979         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  BYTE);
16980         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
16981
16982         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
16983                                         cnt_bits32_63, cnt_bits0_31) );
16984         break;
16985      }
16986
16987      case 0x743:    // vpopcnth
16988      {
16989         /* Break vector into 32-bit words and do the population count
16990          * for each half word
16991          */
16992         IRType ty = Ity_I32;
16993         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
16994         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
16995         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
16996         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
16997
16998         DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
16999         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
17000
17001         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   HWORD);
17002         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  HWORD);
17003         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  HWORD);
17004         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
17005
17006         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
17007                                         cnt_bits32_63, cnt_bits0_31) );
17008         break;
17009      }
17010
17011      case 0x783:    // vpopcntw
17012      {
17013         /* Break vector into 32-bit words and do the population count
17014          * on each word.
17015          */
17016         IRType ty = Ity_I32;
17017         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
17018         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
17019         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
17020         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
17021
17022         DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
17023         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
17024
17025         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   WORD);
17026         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  WORD);
17027         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  WORD);
17028         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
17029
17030         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
17031                                         cnt_bits32_63, cnt_bits0_31) );
17032         break;
17033      }
17034
17035      case 0x7C3:    // vpopcntd
17036      {
17037         if (mode64) {
17038            /* Break vector into 64-bit double words and do the population count
17039             * on each double word.
17040             */
17041            IRType ty = Ity_I64;
17042            IRTemp bits0_63   = newTemp(Ity_I64);
17043            IRTemp bits64_127 = newTemp(Ity_I64);
17044            IRTemp cnt_bits0_63   = newTemp(Ity_I64);
17045            IRTemp cnt_bits64_127 = newTemp(Ity_I64);
17046
17047            DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
17048
17049            assign(bits0_63,   unop( Iop_V128to64,   mkexpr( vB ) ) );
17050            assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
17051            cnt_bits0_63   = gen_POPCOUNT(ty, bits0_63,   DWORD);
17052            cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
17053
17054            putVReg( vRT_addr, binop( Iop_64HLtoV128,
17055                                      mkexpr( cnt_bits64_127 ),
17056                                      mkexpr( cnt_bits0_63 ) ) );
17057         } else {
17058            /* Break vector into 32-bit words and do the population count
17059             * on each doubleword.
17060             */
17061            IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
17062            bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
17063            IRTemp cnt_bits0_63   = newTemp(Ity_I64);
17064            IRTemp cnt_bits64_127  = newTemp(Ity_I64);
17065
17066            DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
17067            breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
17068
17069            cnt_bits0_63   = gen_vpopcntd_mode32(bits0_31, bits32_63);
17070            cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
17071
17072            putVReg( vRT_addr, binop( Iop_64HLtoV128,
17073                                      mkexpr( cnt_bits64_127 ),
17074                                      mkexpr( cnt_bits0_63 ) ) );
17075         }
17076         break;
17077      }
17078
17079      case 0x50C:  // vgbbd Vector Gather Bits by Bytes by Doubleword
17080         DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
17081         putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
17082         break;
17083
17084      case 0x5CC:  // vbpermd Vector Bit Permute Doubleword
17085      {
17086         UChar vRA_addr = ifieldRegA( theInstr );
17087         IRTemp vA = newTemp( Ity_V128 );
17088         UInt j;
17089         IRTemp index_dword_hi[8]; // index in double word
17090         IRTemp index_dword_lo[8];
17091         IRTemp index_dword_hi_valid[8];
17092         IRTemp index_dword_lo_valid[8];
17093         IRTemp pb_dword_hi[8];  // permute bit
17094         IRTemp pb_dword_lo[8];
17095         IRTemp tmp_hi[9];
17096         IRTemp tmp_lo[9];
17097
17098         DIP("vbpermd v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
17099
17100         tmp_hi[0] = newTemp( Ity_I64 );
17101         tmp_lo[0] = newTemp( Ity_I64 );
17102
17103         assign( vA, getVReg(vRA_addr) );
17104         assign( tmp_hi[0], mkU64( 0 ) );
17105         assign( tmp_lo[0], mkU64( 0 ) );
17106
17107         for (j=0; j<8; j++) {
17108            index_dword_hi[j] = newTemp( Ity_I64 );
17109            index_dword_lo[j] = newTemp( Ity_I64 );
17110            index_dword_hi_valid[j] = newTemp( Ity_I64 );
17111            index_dword_lo_valid[j] = newTemp( Ity_I64 );
17112            pb_dword_hi[j] = newTemp( Ity_I64 );
17113            pb_dword_lo[j] = newTemp( Ity_I64 );
17114            tmp_hi[j+1] = newTemp( Ity_I64 );
17115            tmp_lo[j+1] = newTemp( Ity_I64 );
17116
17117            assign( index_dword_hi[j],
17118                    binop( Iop_And64,
17119                           binop( Iop_Shr64,
17120                                  unop( Iop_V128HIto64,
17121                                        mkexpr( vB ) ),
17122                                  mkU8( ( 7 - j ) * 8 ) ),
17123                           mkU64( 0xFF ) ) );
17124
17125            assign( index_dword_lo[j],
17126                    binop( Iop_And64,
17127                           binop( Iop_Shr64,
17128                                  unop( Iop_V128to64,
17129                                        mkexpr( vB ) ),
17130                                  mkU8( ( 7 - j ) * 8 ) ),
17131                           mkU64( 0xFF ) ) );
17132
17133            assign( index_dword_hi_valid[j],
17134                    unop( Iop_1Sto64,
17135                          binop( Iop_CmpLT64U,
17136                                 mkexpr( index_dword_hi[j] ),
17137                                 mkU64( 64 ) ) ) );
17138
17139            assign( index_dword_lo_valid[j],
17140                    unop( Iop_1Sto64,
17141                          binop( Iop_CmpLT64U,
17142                                 mkexpr( index_dword_lo[j] ),
17143                                 mkU64( 64 ) ) ) );
17144            assign( pb_dword_hi[j],
17145                    binop( Iop_And64,
17146                           binop( Iop_Shr64,
17147                                  unop( Iop_V128HIto64,
17148                                        mkexpr( vA ) ),
17149                                  unop( Iop_64to8,
17150                                        binop( Iop_Sub64,
17151                                               mkU64( 63 ),
17152                                               mkexpr( index_dword_hi[j] )
17153                                               ) ) ),
17154                           mkU64( 0x1 ) ) );
17155
17156            assign( pb_dword_lo[j],
17157                    binop( Iop_And64,
17158                           binop( Iop_Shr64,
17159                                  unop( Iop_V128to64,
17160                                        mkexpr( vA ) ),
17161                                  unop( Iop_64to8,
17162                                        binop( Iop_Sub64,
17163                                               mkU64( 63 ),
17164                                               mkexpr( index_dword_lo[j] )
17165                                               ) ) ),
17166                           mkU64( 0x1 ) ) );
17167
17168            assign( tmp_hi[j+1],
17169                    binop( Iop_Or64,
17170                           binop( Iop_And64,
17171                                  mkexpr( index_dword_hi_valid[j] ),
17172                                  binop( Iop_Shl64,
17173                                         mkexpr( pb_dword_hi[j] ),
17174                                         mkU8( 7 - j ) ) ),
17175                           mkexpr( tmp_hi[j] ) ) );
17176
17177            assign( tmp_lo[j+1],
17178                    binop( Iop_Or64,
17179                           binop( Iop_And64,
17180                                  mkexpr( index_dword_lo_valid[j] ),
17181                                  binop( Iop_Shl64,
17182                                         mkexpr( pb_dword_lo[j] ),
17183                                         mkU8( 7 - j ) ) ),
17184                           mkexpr( tmp_lo[j] ) ) );
17185         }
17186
17187         putVReg( vRT_addr,
17188                  binop( Iop_64HLtoV128,
17189                         mkexpr( tmp_hi[8] ),
17190                         mkexpr( tmp_lo[8] ) ) );
17191      }
17192      break;
17193
17194      default:
17195         vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
17196         return False;
17197      break;
17198   }
17199   return True;
17200}
17201
17202typedef enum {
17203   PPC_CMP_EQ = 2,
17204   PPC_CMP_GT = 4,
17205   PPC_CMP_GE = 6,
17206   PPC_CMP_LT = 8
17207} ppc_cmp_t;
17208
17209
17210/*
17211  This helper function takes as input the IRExpr returned
17212  from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
17213  in IR form.  This helper function converts it to PPC form.
17214
17215  Map compare result from IR to PPC
17216
17217  FP cmp result | PPC | IR
17218  --------------------------
17219  UN            | 0x1 | 0x45
17220  EQ            | 0x2 | 0x40
17221  GT            | 0x4 | 0x00
17222  LT            | 0x8 | 0x01
17223
17224 condcode = Shl(1, (~(ccIR>>5) & 2)
17225                    | ((ccIR ^ (ccIR>>6)) & 1)
17226*/
17227static IRTemp
17228get_fp_cmp_CR_val (IRExpr * ccIR_expr)
17229{
17230   IRTemp condcode = newTemp( Ity_I32 );
17231   IRTemp ccIR = newTemp( Ity_I32 );
17232
17233   assign(ccIR, ccIR_expr);
17234   assign( condcode,
17235           binop( Iop_Shl32,
17236                  mkU32( 1 ),
17237                  unop( Iop_32to8,
17238                        binop( Iop_Or32,
17239                               binop( Iop_And32,
17240                                      unop( Iop_Not32,
17241                                            binop( Iop_Shr32,
17242                                                   mkexpr( ccIR ),
17243                                                   mkU8( 5 ) ) ),
17244                                      mkU32( 2 ) ),
17245                               binop( Iop_And32,
17246                                      binop( Iop_Xor32,
17247                                             mkexpr( ccIR ),
17248                                             binop( Iop_Shr32,
17249                                                    mkexpr( ccIR ),
17250                                                    mkU8( 6 ) ) ),
17251                                      mkU32( 1 ) ) ) ) ) );
17252   return condcode;
17253}
17254
17255/*
17256 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
17257 * following these special rules:
17258 *   - The max/min of a QNaN and any value is that value
17259 *     (When two QNaNs are being compared, the frA QNaN is the return value.)
17260 *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
17261 *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
17262 */
17263static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
17264{
17265   IRTemp frA_isNaN = newTemp(Ity_I1);
17266   IRTemp frB_isNaN = newTemp(Ity_I1);
17267   IRTemp frA_isSNaN = newTemp(Ity_I1);
17268   IRTemp frB_isSNaN = newTemp(Ity_I1);
17269   IRTemp frA_isQNaN = newTemp(Ity_I1);
17270   IRTemp frB_isQNaN = newTemp(Ity_I1);
17271
17272   assign( frA_isNaN, is_NaN( Ity_I64, frA_I64 ) );
17273   assign( frB_isNaN, is_NaN( Ity_I64, frB_I64 ) );
17274   // If operand is a NAN and bit 12 is '0', then it's an SNaN
17275   assign( frA_isSNaN,
17276           mkAND1( mkexpr(frA_isNaN),
17277                   binop( Iop_CmpEQ32,
17278                          binop( Iop_And32,
17279                                 unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
17280                                 mkU32( 0x00080000 ) ),
17281                          mkU32( 0 ) ) ) );
17282   assign( frB_isSNaN,
17283           mkAND1( mkexpr(frB_isNaN),
17284                   binop( Iop_CmpEQ32,
17285                          binop( Iop_And32,
17286                                 unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
17287                                 mkU32( 0x00080000 ) ),
17288                          mkU32( 0 ) ) ) );
17289   assign( frA_isQNaN,
17290           mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
17291   assign( frB_isQNaN,
17292           mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
17293
17294   /* Based on the rules specified in the function prologue, the algorithm is as follows:
17295    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
17296    *   if frA is a SNaN
17297    *     result = frA converted to QNaN
17298    *   else if frB is a SNaN
17299    *     result = frB converted to QNaN
17300    *   else if frB is a QNaN
17301    *     result = frA
17302    *   // One of frA or frB was a NaN in order for this function to be called, so
17303    *   // if we get to this point, we KNOW that frA must be a QNaN.
17304    *   else // frA is a QNaN
17305    *     result = frB
17306    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
17307    */
17308
17309#define SNAN_MASK 0x0008000000000000ULL
17310   return
17311   IRExpr_ITE(mkexpr(frA_isSNaN),
17312              /* then: result = frA converted to QNaN */
17313              binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
17314              /* else:  if frB is a SNaN */
17315              IRExpr_ITE(mkexpr(frB_isSNaN),
17316                         /* then: result = frB converted to QNaN */
17317                         binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
17318                         /* else:  if frB is a QNaN */
17319                         IRExpr_ITE(mkexpr(frB_isQNaN),
17320                                    /* then: result = frA */
17321                                    mkexpr(frA_I64),
17322                                    /* else:  frA is a QNaN, so result = frB */
17323                                    mkexpr(frB_I64))));
17324}
17325
17326/*
17327 * Helper function for get_max_min_fp.
17328 */
17329static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
17330{
17331   IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
17332                                                  unop( Iop_ReinterpI64asF64,
17333                                                        mkexpr( src1 ) ),
17334                                                  unop( Iop_ReinterpI64asF64,
17335                                                        mkexpr( src2 ) ) ) );
17336
17337   return IRExpr_ITE( binop( Iop_CmpEQ32,
17338                               mkexpr( src1cmpsrc2 ),
17339                               mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
17340                      /* then: use src1 */
17341                      mkexpr( src1 ),
17342                      /* else: use src2 */
17343                      mkexpr( src2 ) );
17344}
17345
17346/*
17347 * Helper function for "Maximum/Minimum Double Precision" operations.
17348 * Arguments: frA and frb are Ity_I64
17349 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
17350 */
17351static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
17352{
17353   /* There are three special cases where get_fp_cmp_CR_val is not helpful
17354    * for ascertaining the maximum between two doubles:
17355    *   1. The max/min of +0 and -0 is +0.
17356    *   2. The max/min of a QNaN and any value is that value.
17357    *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
17358    * We perform the check for [+/-]0 here in this function and use the
17359    * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
17360    * to do the standard comparison function.
17361    */
17362   IRTemp anyNaN = newTemp(Ity_I1);
17363   IRTemp frA_isZero = newTemp(Ity_I1);
17364   IRTemp frB_isZero = newTemp(Ity_I1);
17365   assign( frA_isZero, is_Zero( Ity_I64, frA_I64 ) );
17366   assign( frB_isZero, is_Zero( Ity_I64, frB_I64 ) );
17367   assign( anyNaN, mkOR1( is_NaN( Ity_I64, frA_I64 ),
17368                          is_NaN(Ity_I64, frB_I64 ) ) );
17369#define MINUS_ZERO 0x8000000000000000ULL
17370
17371   return IRExpr_ITE( /* If both arguments are zero . . . */
17372                     mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
17373                     /* then: if frA is -0 and isMin==True, return -0;
17374                      *     else if frA is +0 and isMin==False; return +0;
17375                      *     otherwise, simply return frB. */
17376                     IRExpr_ITE( binop( Iop_CmpEQ32,
17377                                        unop( Iop_64HIto32,
17378                                              mkexpr( frA_I64 ) ),
17379                                        mkU32( isMin ? 0x80000000 : 0 ) ),
17380                                 mkU64( isMin ? MINUS_ZERO : 0ULL ),
17381                                 mkexpr( frB_I64 ) ),
17382                     /* else: check if either input is a NaN*/
17383                     IRExpr_ITE( mkexpr( anyNaN ),
17384                                 /* then: use "NaN helper" */
17385                                 _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
17386                                 /* else: use "comparison helper" */
17387                                 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
17388}
17389
17390static const HChar * _get_vsx_rdpi_suffix(UInt opc2)
17391{
17392   switch (opc2 & 0x7F) {
17393      case 0x72:
17394         return "m";
17395      case 0x52:
17396         return "p";
17397      case 0x56:
17398         return "c";
17399      case 0x32:
17400         return "z";
17401      case 0x12:
17402         return "";
17403
17404      default: // Impossible to get here
17405         vex_printf("Unrecognized opcode %x\n", opc2);
17406         vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
17407   }
17408}
17409
17410/*
17411 * Helper function for vector/scalar double precision fp round to integer instructions.
17412 */
17413static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
17414{
17415
17416   /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
17417   IRTemp frB = newTemp(Ity_F64);
17418   IRTemp frD = newTemp(Ity_F64);
17419   IRTemp intermediateResult = newTemp(Ity_I64);
17420   IRTemp is_SNAN = newTemp(Ity_I1);
17421   IRExpr * hi32;
17422   IRExpr * rxpi_rm;
17423   switch (opc2 & 0x7F) {
17424      case 0x72:
17425         rxpi_rm = mkU32(Irrm_NegINF);
17426         break;
17427      case 0x52:
17428         rxpi_rm = mkU32(Irrm_PosINF);
17429         break;
17430      case 0x56:
17431         rxpi_rm = get_IR_roundingmode();
17432         break;
17433      case 0x32:
17434         rxpi_rm = mkU32(Irrm_ZERO);
17435         break;
17436      case 0x12:
17437         rxpi_rm = mkU32(Irrm_NEAREST);
17438         break;
17439
17440      default: // Impossible to get here
17441         vex_printf("Unrecognized opcode %x\n", opc2);
17442         vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
17443   }
17444   assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
17445   assign( intermediateResult,
17446           binop( Iop_F64toI64S, rxpi_rm,
17447                  mkexpr( frB ) ) );
17448
17449   /* don't use the rounded integer if frB is outside -9e18..9e18 */
17450   /* F64 has only log10(2**52) significant digits anyway */
17451   /* need to preserve sign of zero */
17452   /*   frD = (fabs(frB) > 9e18) ? frB :
17453            (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
17454   assign( frD,
17455           IRExpr_ITE(
17456              binop( Iop_CmpNE8,
17457                     unop( Iop_32to8,
17458                           binop( Iop_CmpF64,
17459                                  IRExpr_Const( IRConst_F64( 9e18 ) ),
17460                                  unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
17461                     mkU8(0) ),
17462              mkexpr( frB ),
17463              IRExpr_ITE(
17464                 binop( Iop_CmpNE32,
17465                        binop( Iop_Shr32,
17466                               unop( Iop_64HIto32,
17467                                     mkexpr( frB_I64 ) ),
17468                               mkU8( 31 ) ),
17469                        mkU32(0) ),
17470                 unop( Iop_NegF64,
17471                       unop( Iop_AbsF64,
17472                             binop( Iop_I64StoF64,
17473                                    mkU32( 0 ),
17474                                    mkexpr( intermediateResult ) ) ) ),
17475                 binop( Iop_I64StoF64,
17476                        mkU32( 0 ),
17477                        mkexpr( intermediateResult ) )
17478              )
17479           )
17480   );
17481
17482   /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
17483    * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
17484    */
17485#define SNAN_MASK 0x0008000000000000ULL
17486   hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
17487   assign( is_SNAN,
17488           mkAND1( is_NaN( Ity_I64, frB_I64 ),
17489                   binop( Iop_CmpEQ32,
17490                          binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
17491                          mkU32( 0 ) ) ) );
17492
17493   return IRExpr_ITE( mkexpr( is_SNAN ),
17494                        unop( Iop_ReinterpI64asF64,
17495                              binop( Iop_Xor64,
17496                                     mkU64( SNAN_MASK ),
17497                                     mkexpr( frB_I64 ) ) ),
17498                      mkexpr( frD ));
17499}
17500
17501/*
17502 * Miscellaneous VSX vector instructions
17503 */
17504static Bool
17505dis_vxv_misc ( UInt theInstr, UInt opc2 )
17506{
17507   /* XX3-Form */
17508   UChar opc1 = ifieldOPC( theInstr );
17509   UChar XT = ifieldRegXT( theInstr );
17510   UChar XB = ifieldRegXB( theInstr );
17511
17512   if (opc1 != 0x3C) {
17513      vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
17514      return False;
17515   }
17516
17517   switch (opc2) {
17518      case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
17519      case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
17520                   //             Double-Precision)
17521      {
17522         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
17523         IRExpr* rm  = get_IR_roundingmode();
17524         IRTemp frB = newTemp(Ity_I64);
17525         IRTemp frB2 = newTemp(Ity_I64);
17526         Bool redp = opc2 == 0x1B4;
17527         IRTemp sqrtHi = newTemp(Ity_F64);
17528         IRTemp sqrtLo = newTemp(Ity_F64);
17529         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
17530         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
17531
17532         DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", XT, XB);
17533
17534         if (!redp) {
17535            assign( sqrtHi,
17536                    binop( Iop_SqrtF64,
17537                           rm,
17538                           unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
17539            assign( sqrtLo,
17540                    binop( Iop_SqrtF64,
17541                           rm,
17542                           unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
17543         }
17544         putVSReg( XT,
17545                   binop( Iop_64HLtoV128,
17546                          unop( Iop_ReinterpF64asI64,
17547                                triop( Iop_DivF64,
17548                                       rm,
17549                                       ieee_one,
17550                                       redp ? unop( Iop_ReinterpI64asF64,
17551                                                    mkexpr( frB ) )
17552                                            : mkexpr( sqrtHi ) ) ),
17553                          unop( Iop_ReinterpF64asI64,
17554                                triop( Iop_DivF64,
17555                                       rm,
17556                                       ieee_one,
17557                                       redp ? unop( Iop_ReinterpI64asF64,
17558                                                    mkexpr( frB2 ) )
17559                                            : mkexpr( sqrtLo ) ) ) ) );
17560         break;
17561
17562      }
17563      case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
17564      case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
17565      {
17566         IRTemp b3, b2, b1, b0;
17567         IRTemp res0 = newTemp(Ity_I32);
17568         IRTemp res1 = newTemp(Ity_I32);
17569         IRTemp res2 = newTemp(Ity_I32);
17570         IRTemp res3 = newTemp(Ity_I32);
17571         IRTemp sqrt3 = newTemp(Ity_F64);
17572         IRTemp sqrt2 = newTemp(Ity_F64);
17573         IRTemp sqrt1 = newTemp(Ity_F64);
17574         IRTemp sqrt0 = newTemp(Ity_F64);
17575         IRExpr* rm  = get_IR_roundingmode();
17576         Bool resp = opc2 == 0x134;
17577
17578         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
17579
17580         b3 = b2 = b1 = b0 = IRTemp_INVALID;
17581         DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", XT, XB);
17582         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
17583
17584         if (!resp) {
17585            assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
17586            assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
17587            assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
17588            assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
17589         }
17590
17591         assign( res0,
17592                 unop( Iop_ReinterpF32asI32,
17593                       unop( Iop_TruncF64asF32,
17594                             triop( Iop_DivF64r32,
17595                                    rm,
17596                                    ieee_one,
17597                                    resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
17598         assign( res1,
17599                 unop( Iop_ReinterpF32asI32,
17600                       unop( Iop_TruncF64asF32,
17601                             triop( Iop_DivF64r32,
17602                                    rm,
17603                                    ieee_one,
17604                                    resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
17605         assign( res2,
17606                 unop( Iop_ReinterpF32asI32,
17607                       unop( Iop_TruncF64asF32,
17608                             triop( Iop_DivF64r32,
17609                                    rm,
17610                                    ieee_one,
17611                                    resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
17612         assign( res3,
17613                 unop( Iop_ReinterpF32asI32,
17614                       unop( Iop_TruncF64asF32,
17615                             triop( Iop_DivF64r32,
17616                                    rm,
17617                                    ieee_one,
17618                                    resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
17619         putVSReg( XT,
17620                   binop( Iop_64HLtoV128,
17621                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
17622                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
17623         break;
17624      }
17625      case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
17626      case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
17627      {
17628         UChar XA = ifieldRegXA( theInstr );
17629         IRTemp a3, a2, a1, a0;
17630         IRTemp b3, b2, b1, b0;
17631         IRTemp res0 = newTemp( Ity_I32 );
17632         IRTemp res1 = newTemp( Ity_I32 );
17633         IRTemp res2 = newTemp( Ity_I32 );
17634         IRTemp res3 = newTemp( Ity_I32 );
17635         IRTemp a0_I64 = newTemp( Ity_I64 );
17636         IRTemp a1_I64 = newTemp( Ity_I64 );
17637         IRTemp a2_I64 = newTemp( Ity_I64 );
17638         IRTemp a3_I64 = newTemp( Ity_I64 );
17639         IRTemp b0_I64 = newTemp( Ity_I64 );
17640         IRTemp b1_I64 = newTemp( Ity_I64 );
17641         IRTemp b2_I64 = newTemp( Ity_I64 );
17642         IRTemp b3_I64 = newTemp( Ity_I64 );
17643
17644         Bool isMin = opc2 == 0x320 ? True : False;
17645
17646         a3 = a2 = a1 = a0 = IRTemp_INVALID;
17647         b3 = b2 = b1 = b0 = IRTemp_INVALID;
17648         DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", XT, XA, XB);
17649         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
17650         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
17651         assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
17652         assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
17653         assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
17654         assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
17655         assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
17656         assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
17657         assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
17658         assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
17659         assign( res0,
17660                 unop( Iop_ReinterpF32asI32,
17661                       unop( Iop_TruncF64asF32,
17662                             unop( Iop_ReinterpI64asF64,
17663                                   get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
17664         assign( res1,
17665                 unop( Iop_ReinterpF32asI32,
17666                       unop( Iop_TruncF64asF32,
17667                             unop( Iop_ReinterpI64asF64,
17668                                   get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
17669         assign( res2,
17670                 unop( Iop_ReinterpF32asI32,
17671                       unop( Iop_TruncF64asF32,
17672                             unop( Iop_ReinterpI64asF64,
17673                                   get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
17674         assign( res3,
17675                 unop( Iop_ReinterpF32asI32,
17676                       unop( Iop_TruncF64asF32,
17677                             unop( Iop_ReinterpI64asF64,
17678                                   get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
17679         putVSReg( XT,
17680                   binop( Iop_64HLtoV128,
17681                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
17682                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
17683         break;
17684      }
17685      case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
17686      case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
17687      {
17688         UChar XA = ifieldRegXA( theInstr );
17689         IRTemp frA = newTemp(Ity_I64);
17690         IRTemp frB = newTemp(Ity_I64);
17691         IRTemp frA2 = newTemp(Ity_I64);
17692         IRTemp frB2 = newTemp(Ity_I64);
17693         Bool isMin = opc2 == 0x3A0 ? True : False;
17694
17695         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
17696         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
17697         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
17698         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
17699         DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", XT, XA, XB);
17700         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
17701
17702         break;
17703      }
17704      case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
17705      {
17706         UChar XA = ifieldRegXA( theInstr );
17707         IRTemp frA = newTemp(Ity_I64);
17708         IRTemp frB = newTemp(Ity_I64);
17709         IRTemp frA2 = newTemp(Ity_I64);
17710         IRTemp frB2 = newTemp(Ity_I64);
17711         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
17712         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
17713         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
17714         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
17715
17716         DIP("xvcpsgndp v%d,v%d,v%d\n", XT, XA, XB);
17717         putVSReg( XT,
17718                   binop( Iop_64HLtoV128,
17719                          binop( Iop_Or64,
17720                                 binop( Iop_And64,
17721                                        mkexpr( frA ),
17722                                        mkU64( SIGN_BIT ) ),
17723                                 binop( Iop_And64,
17724                                        mkexpr( frB ),
17725                                        mkU64( SIGN_MASK ) ) ),
17726                          binop( Iop_Or64,
17727                                 binop( Iop_And64,
17728                                        mkexpr( frA2 ),
17729                                        mkU64( SIGN_BIT ) ),
17730                                 binop( Iop_And64,
17731                                        mkexpr( frB2 ),
17732                                        mkU64( SIGN_MASK ) ) ) ) );
17733         break;
17734      }
17735      case 0x340: // xvcpsgnsp
17736      {
17737         UChar XA = ifieldRegXA( theInstr );
17738         IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
17739         IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
17740         IRTemp resHi = newTemp(Ity_I64);
17741         IRTemp resLo = newTemp(Ity_I64);
17742
17743         a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
17744         b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
17745         DIP("xvcpsgnsp v%d,v%d v%d\n",XT, XA, XB);
17746         breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
17747         breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
17748
17749         assign( resHi,
17750                 binop( Iop_32HLto64,
17751                        binop( Iop_Or32,
17752                               binop( Iop_And32,
17753                                      unop(Iop_64to32, mkexpr( a3_I64 ) ),
17754                                      mkU32( SIGN_BIT32 ) ),
17755                               binop( Iop_And32,
17756                                      unop(Iop_64to32, mkexpr( b3_I64 ) ),
17757                                      mkU32( SIGN_MASK32) ) ),
17758
17759                        binop( Iop_Or32,
17760                               binop( Iop_And32,
17761                                      unop(Iop_64to32, mkexpr( a2_I64 ) ),
17762                                      mkU32( SIGN_BIT32 ) ),
17763                               binop( Iop_And32,
17764                                      unop(Iop_64to32, mkexpr( b2_I64 ) ),
17765                                      mkU32( SIGN_MASK32 ) ) ) ) );
17766         assign( resLo,
17767                 binop( Iop_32HLto64,
17768                        binop( Iop_Or32,
17769                               binop( Iop_And32,
17770                                      unop(Iop_64to32, mkexpr( a1_I64 ) ),
17771                                      mkU32( SIGN_BIT32 ) ),
17772                               binop( Iop_And32,
17773                                      unop(Iop_64to32, mkexpr( b1_I64 ) ),
17774                                      mkU32( SIGN_MASK32 ) ) ),
17775
17776                        binop( Iop_Or32,
17777                               binop( Iop_And32,
17778                                      unop(Iop_64to32, mkexpr( a0_I64 ) ),
17779                                      mkU32( SIGN_BIT32 ) ),
17780                               binop( Iop_And32,
17781                                      unop(Iop_64to32, mkexpr( b0_I64 ) ),
17782                                      mkU32( SIGN_MASK32 ) ) ) ) );
17783         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
17784         break;
17785      }
17786      case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
17787      case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
17788      {
17789         IRTemp frB = newTemp(Ity_F64);
17790         IRTemp frB2 = newTemp(Ity_F64);
17791         IRTemp abs_resultHi = newTemp(Ity_F64);
17792         IRTemp abs_resultLo = newTemp(Ity_F64);
17793         Bool make_negative = (opc2 == 0x3D2) ? True : False;
17794         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
17795         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
17796
17797         DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", XT, XB);
17798         if (make_negative) {
17799            assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
17800            assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
17801
17802         } else {
17803            assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
17804            assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
17805         }
17806         putVSReg( XT, binop( Iop_64HLtoV128,
17807                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
17808                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
17809         break;
17810      }
17811      case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
17812      case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
17813      {
17814         /*
17815          * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
17816          * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
17817          * of this function is so easy using shifts, I choose to emulate this instruction that
17818          * way versus a native instruction method of implementation.
17819          */
17820         Bool make_negative = (opc2 == 0x352) ? True : False;
17821         IRTemp shiftVector = newTemp(Ity_V128);
17822         IRTemp absVal_vector = newTemp(Ity_V128);
17823         assign( shiftVector,
17824                 binop( Iop_64HLtoV128,
17825                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
17826                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
17827         assign( absVal_vector,
17828                   binop( Iop_Shr32x4,
17829                          binop( Iop_Shl32x4,
17830                                 getVSReg( XB ),
17831                                 mkexpr( shiftVector ) ),
17832                          mkexpr( shiftVector ) ) );
17833         if (make_negative) {
17834            IRTemp signBit_vector = newTemp(Ity_V128);
17835            assign( signBit_vector,
17836                    binop( Iop_64HLtoV128,
17837                           binop( Iop_32HLto64,
17838                                  mkU32( 0x80000000 ),
17839                                  mkU32( 0x80000000 ) ),
17840                           binop( Iop_32HLto64,
17841                                  mkU32( 0x80000000 ),
17842                                  mkU32( 0x80000000 ) ) ) );
17843            putVSReg( XT,
17844                      binop( Iop_OrV128,
17845                             mkexpr( absVal_vector ),
17846                             mkexpr( signBit_vector ) ) );
17847         } else {
17848            putVSReg( XT, mkexpr( absVal_vector ) );
17849         }
17850         break;
17851      }
17852      case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
17853      {
17854         IRTemp frB = newTemp(Ity_F64);
17855         IRTemp frB2 = newTemp(Ity_F64);
17856         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
17857         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
17858         DIP("xvnegdp v%d,v%d\n",  XT, XB);
17859         putVSReg( XT,
17860                   binop( Iop_64HLtoV128,
17861                          unop( Iop_ReinterpF64asI64,
17862                                unop( Iop_NegF64, mkexpr( frB ) ) ),
17863                          unop( Iop_ReinterpF64asI64,
17864                                unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
17865         break;
17866      }
17867      case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
17868      case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
17869      case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
17870      case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
17871      case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
17872      {
17873         IRTemp frBHi_I64 = newTemp(Ity_I64);
17874         IRTemp frBLo_I64 = newTemp(Ity_I64);
17875         IRExpr * frD_fp_roundHi = NULL;
17876         IRExpr * frD_fp_roundLo = NULL;
17877
17878         assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
17879         frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
17880         assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
17881         frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
17882
17883         DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
17884         putVSReg( XT,
17885                   binop( Iop_64HLtoV128,
17886                          unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
17887                          unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
17888         break;
17889      }
17890      case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
17891      case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
17892      case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
17893      case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
17894      case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
17895      {
17896         const HChar * insn_suffix = NULL;
17897         IROp op;
17898         if (opc2 != 0x156) {
17899            // Use pre-defined IRop's for vrfi{m|n|p|z}
17900            switch (opc2) {
17901               case 0x112:
17902                  insn_suffix = "";
17903                  op = Iop_RoundF32x4_RN;
17904                  break;
17905               case 0x172:
17906                  insn_suffix = "m";
17907                  op = Iop_RoundF32x4_RM;
17908                  break;
17909               case 0x152:
17910                  insn_suffix = "p";
17911                  op = Iop_RoundF32x4_RP;
17912                  break;
17913               case 0x132:
17914                  insn_suffix = "z";
17915                  op = Iop_RoundF32x4_RZ;
17916                  break;
17917
17918               default:
17919                  vex_printf("Unrecognized opcode %x\n", opc2);
17920                  vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
17921            }
17922            DIP("xvrspi%s v%d,v%d\n", insn_suffix, XT, XB);
17923            putVSReg( XT, unop( op, getVSReg(XB) ) );
17924         } else {
17925            // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
17926            IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
17927            IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
17928            IRTemp b3_I64 = newTemp(Ity_I64);
17929            IRTemp b2_I64 = newTemp(Ity_I64);
17930            IRTemp b1_I64 = newTemp(Ity_I64);
17931            IRTemp b0_I64 = newTemp(Ity_I64);
17932
17933            b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
17934            frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
17935            breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
17936            assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
17937            assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
17938            assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
17939            assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
17940            frD_fp_roundb3 = unop(Iop_TruncF64asF32,
17941                                  _do_vsx_fp_roundToInt(b3_I64, opc2));
17942            frD_fp_roundb2 = unop(Iop_TruncF64asF32,
17943                                  _do_vsx_fp_roundToInt(b2_I64, opc2));
17944            frD_fp_roundb1 = unop(Iop_TruncF64asF32,
17945                                  _do_vsx_fp_roundToInt(b1_I64, opc2));
17946            frD_fp_roundb0 = unop(Iop_TruncF64asF32,
17947                                  _do_vsx_fp_roundToInt(b0_I64, opc2));
17948            DIP("xvrspic v%d,v%d\n", XT, XB);
17949            putVSReg( XT,
17950                      binop( Iop_64HLtoV128,
17951                             binop( Iop_32HLto64,
17952                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
17953                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
17954                             binop( Iop_32HLto64,
17955                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
17956                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
17957         }
17958         break;
17959      }
17960
17961      default:
17962         vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
17963         return False;
17964   }
17965   return True;
17966}
17967
17968
17969/*
17970 * VSX Scalar Floating Point Arithmetic Instructions
17971 */
17972static Bool
17973dis_vxs_arith ( UInt theInstr, UInt opc2 )
17974{
17975   /* XX3-Form */
17976   UChar opc1 = ifieldOPC( theInstr );
17977   UChar XT = ifieldRegXT( theInstr );
17978   UChar XA = ifieldRegXA( theInstr );
17979   UChar XB = ifieldRegXB( theInstr );
17980   IRExpr* rm = get_IR_roundingmode();
17981   IRTemp frA = newTemp(Ity_F64);
17982   IRTemp frB = newTemp(Ity_F64);
17983
17984   if (opc1 != 0x3C) {
17985      vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
17986      return False;
17987   }
17988
17989   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
17990   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
17991
17992   /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
17993    * of VSX[XT] are undefined after the operation; therefore, we can simply set
17994    * element to zero where it makes sense to do so.
17995    */
17996   switch (opc2) {
17997      case 0x000: // xsaddsp  (VSX Scalar Add Single-Precision)
17998         DIP("xsaddsp v%d,v%d,v%d\n", XT, XA, XB);
17999         putVSReg( XT, binop( Iop_64HLtoV128,
18000                              unop( Iop_ReinterpF64asI64,
18001                                    binop( Iop_RoundF64toF32, rm,
18002                                           triop( Iop_AddF64, rm,
18003                                                  mkexpr( frA ),
18004                                                  mkexpr( frB ) ) ) ),
18005                              mkU64( 0 ) ) );
18006         break;
18007      case 0x020: // xssubsp  (VSX Scalar Subtract Single-Precision)
18008         DIP("xssubsp v%d,v%d,v%d\n", XT, XA, XB);
18009         putVSReg( XT, binop( Iop_64HLtoV128,
18010                              unop( Iop_ReinterpF64asI64,
18011                                    binop( Iop_RoundF64toF32, rm,
18012                                           triop( Iop_SubF64, rm,
18013                                                  mkexpr( frA ),
18014                                                  mkexpr( frB ) ) ) ),
18015                              mkU64( 0 ) ) );
18016         break;
18017      case 0x080: // xsadddp (VSX scalar add double-precision)
18018         DIP("xsadddp v%d,v%d,v%d\n", XT, XA, XB);
18019         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18020                                                    triop( Iop_AddF64, rm,
18021                                                           mkexpr( frA ),
18022                                                           mkexpr( frB ) ) ),
18023                              mkU64( 0 ) ) );
18024         break;
18025      case 0x060: // xsdivsp (VSX scalar divide single-precision)
18026         DIP("xsdivsp v%d,v%d,v%d\n", XT, XA, XB);
18027         putVSReg( XT, binop( Iop_64HLtoV128,
18028                              unop( Iop_ReinterpF64asI64,
18029                                    binop( Iop_RoundF64toF32, rm,
18030                                           triop( Iop_DivF64, rm,
18031                                                  mkexpr( frA ),
18032                                                  mkexpr( frB ) ) ) ),
18033                               mkU64( 0 ) ) );
18034         break;
18035      case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
18036         DIP("xsdivdp v%d,v%d,v%d\n", XT, XA, XB);
18037         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18038                                                    triop( Iop_DivF64, rm,
18039                                                           mkexpr( frA ),
18040                                                           mkexpr( frB ) ) ),
18041                              mkU64( 0 ) ) );
18042         break;
18043      case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
18044                               * single-precision)
18045                               */
18046      {
18047         IRTemp frT = newTemp(Ity_F64);
18048         Bool mdp = opc2 == 0x024;
18049         DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18050         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18051                                                        getVSReg( XT ) ) ) );
18052         putVSReg( XT,
18053                   binop( Iop_64HLtoV128,
18054                          unop( Iop_ReinterpF64asI64,
18055                                binop( Iop_RoundF64toF32, rm,
18056                                       qop( Iop_MAddF64, rm,
18057                                            mkexpr( frA ),
18058                                            mkexpr( mdp ? frT : frB ),
18059                                            mkexpr( mdp ? frB : frT ) ) ) ),
18060                          mkU64( 0 ) ) );
18061         break;
18062      }
18063      case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
18064      {
18065         IRTemp frT = newTemp(Ity_F64);
18066         Bool mdp = opc2 == 0x0A4;
18067         DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18068         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18069                                                        getVSReg( XT ) ) ) );
18070         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18071                                                    qop( Iop_MAddF64, rm,
18072                                                         mkexpr( frA ),
18073                                                         mkexpr( mdp ? frT : frB ),
18074                                                         mkexpr( mdp ? frB : frT ) ) ),
18075                              mkU64( 0 ) ) );
18076         break;
18077      }
18078      case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
18079                               * multiply-subtract single-precision)
18080			       */
18081      {
18082         IRTemp frT = newTemp(Ity_F64);
18083         Bool mdp = opc2 == 0x064;
18084         DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18085         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18086                                                        getVSReg( XT ) ) ) );
18087         putVSReg( XT,
18088                   binop( Iop_64HLtoV128,
18089                          unop( Iop_ReinterpF64asI64,
18090                                binop( Iop_RoundF64toF32, rm,
18091                                       qop( Iop_MSubF64, rm,
18092                                            mkexpr( frA ),
18093                                            mkexpr( mdp ? frT : frB ),
18094                                            mkexpr( mdp ? frB : frT ) ) ) ),
18095                          mkU64( 0 ) ) );
18096         break;
18097      }
18098      case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
18099      {
18100         IRTemp frT = newTemp(Ity_F64);
18101         Bool mdp = opc2 == 0x0E4;
18102         DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18103         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18104                                                        getVSReg( XT ) ) ) );
18105         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18106                                                    qop( Iop_MSubF64, rm,
18107                                                         mkexpr( frA ),
18108                                                         mkexpr( mdp ? frT : frB ),
18109                                                         mkexpr( mdp ? frB : frT ) ) ),
18110                              mkU64( 0 ) ) );
18111         break;
18112      }
18113      case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
18114      {
18115         /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
18116          * of fnmadd and use pretty much the same code. However, that code has a bug in the
18117          * way it blindly negates the signbit, even if the floating point result is a NaN.
18118          * So, the TODO is to fix fnmadd (which I'll do in a different patch).
18119          * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
18120          * bit for NaN result.
18121          */
18122         Bool mdp = opc2 == 0x2A4;
18123         IRTemp frT = newTemp(Ity_F64);
18124         IRTemp maddResult = newTemp(Ity_I64);
18125
18126         DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18127         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18128                                                        getVSReg( XT ) ) ) );
18129         assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
18130                                                              mkexpr( frA ),
18131                                                              mkexpr( mdp ? frT : frB ),
18132                                                              mkexpr( mdp ? frB : frT ) ) ) );
18133
18134         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
18135                              mkU64( 0 ) ) );
18136         break;
18137      }
18138      case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
18139                               * multiply-add single-precision)
18140                               */
18141      {
18142         Bool mdp = opc2 == 0x224;
18143         IRTemp frT = newTemp(Ity_F64);
18144         IRTemp maddResult = newTemp(Ity_I64);
18145
18146         DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18147         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18148                                                        getVSReg( XT ) ) ) );
18149         assign( maddResult,
18150                 unop( Iop_ReinterpF64asI64,
18151                       binop( Iop_RoundF64toF32, rm,
18152                              qop( Iop_MAddF64, rm,
18153                                   mkexpr( frA ),
18154                                   mkexpr( mdp ? frT : frB ),
18155                                   mkexpr( mdp ? frB : frT ) ) ) ) );
18156
18157         putVSReg( XT, binop( Iop_64HLtoV128,
18158                              mkexpr( getNegatedResult(maddResult) ),
18159                              mkU64( 0 ) ) );
18160         break;
18161      }
18162      case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
18163                               * Multiply-Subtract Single-Precision)
18164                               */
18165      {
18166         IRTemp frT = newTemp(Ity_F64);
18167         Bool mdp = opc2 == 0x264;
18168         IRTemp msubResult = newTemp(Ity_I64);
18169
18170         DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18171         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18172                                                        getVSReg( XT ) ) ) );
18173         assign( msubResult,
18174                 unop( Iop_ReinterpF64asI64,
18175                       binop( Iop_RoundF64toF32, rm,
18176                              qop( Iop_MSubF64, rm,
18177                                   mkexpr( frA ),
18178                                   mkexpr( mdp ? frT : frB ),
18179                                   mkexpr( mdp ? frB : frT ) ) ) ) );
18180
18181         putVSReg( XT, binop( Iop_64HLtoV128,
18182                              mkexpr( getNegatedResult(msubResult) ),
18183                              mkU64( 0 ) ) );
18184
18185         break;
18186      }
18187
18188      case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
18189      {
18190         IRTemp frT = newTemp(Ity_F64);
18191         Bool mdp = opc2 == 0x2E4;
18192         IRTemp msubResult = newTemp(Ity_I64);
18193
18194         DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18195         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18196                                                        getVSReg( XT ) ) ) );
18197         assign(msubResult, unop( Iop_ReinterpF64asI64,
18198                                      qop( Iop_MSubF64,
18199                                           rm,
18200                                           mkexpr( frA ),
18201                                           mkexpr( mdp ? frT : frB ),
18202                                           mkexpr( mdp ? frB : frT ) ) ));
18203
18204         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
18205
18206         break;
18207      }
18208
18209      case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
18210         DIP("xsmulsp v%d,v%d,v%d\n", XT, XA, XB);
18211         putVSReg( XT, binop( Iop_64HLtoV128,
18212                              unop( Iop_ReinterpF64asI64,
18213                                    binop( Iop_RoundF64toF32, rm,
18214                                           triop( Iop_MulF64, rm,
18215                                                   mkexpr( frA ),
18216                                                   mkexpr( frB ) ) ) ),
18217                              mkU64( 0 ) ) );
18218         break;
18219
18220      case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
18221         DIP("xsmuldp v%d,v%d,v%d\n", XT, XA, XB);
18222         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18223                                                    triop( Iop_MulF64, rm,
18224                                                           mkexpr( frA ),
18225                                                           mkexpr( frB ) ) ),
18226                              mkU64( 0 ) ) );
18227         break;
18228      case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
18229         DIP("xssubdp v%d,v%d,v%d\n", XT, XA, XB);
18230         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18231                                                    triop( Iop_SubF64, rm,
18232                                                           mkexpr( frA ),
18233                                                           mkexpr( frB ) ) ),
18234                              mkU64( 0 ) ) );
18235         break;
18236
18237      case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
18238         DIP("xssqrtsp v%d,v%d\n", XT, XB);
18239         putVSReg( XT,
18240                   binop( Iop_64HLtoV128,
18241                          unop( Iop_ReinterpF64asI64,
18242                                binop( Iop_RoundF64toF32, rm,
18243                                       binop( Iop_SqrtF64, rm,
18244                                              mkexpr( frB ) ) ) ),
18245                          mkU64( 0 ) ) );
18246         break;
18247
18248      case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
18249         DIP("xssqrtdp v%d,v%d\n", XT, XB);
18250         putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18251                                                     binop( Iop_SqrtF64, rm,
18252                                                            mkexpr( frB ) ) ),
18253                               mkU64( 0 ) ) );
18254         break;
18255
18256      case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
18257      {
18258         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
18259         IRTemp frA_I64 = newTemp(Ity_I64);
18260         IRTemp frB_I64 = newTemp(Ity_I64);
18261         DIP("xstdivdp crf%d,v%d,v%d\n", crfD, XA, XB);
18262         assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
18263         assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
18264         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
18265         break;
18266      }
18267      case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
18268      {
18269         IRTemp frB_I64 = newTemp(Ity_I64);
18270         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
18271         IRTemp flags = newTemp(Ity_I32);
18272         IRTemp  fe_flag, fg_flag;
18273         fe_flag = fg_flag = IRTemp_INVALID;
18274         DIP("xstsqrtdp v%d,v%d\n", XT, XB);
18275         assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
18276         do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
18277         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
18278          * where fl_flag == 1 on ppc64.
18279          */
18280         assign( flags,
18281                 binop( Iop_Or32,
18282                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
18283                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
18284                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
18285         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
18286         break;
18287      }
18288
18289      default:
18290         vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
18291         return False;
18292   }
18293
18294   return True;
18295}
18296
18297
18298/*
18299 * VSX Floating Point Compare Instructions
18300 */
18301static Bool
18302dis_vx_cmp( UInt theInstr, UInt opc2 )
18303{
18304   /* XX3-Form and XX2-Form */
18305   UChar opc1 = ifieldOPC( theInstr );
18306   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
18307   IRTemp ccPPC32;
18308   UChar XA       = ifieldRegXA ( theInstr );
18309   UChar XB       = ifieldRegXB ( theInstr );
18310   IRTemp frA     = newTemp(Ity_F64);
18311   IRTemp frB     = newTemp(Ity_F64);
18312
18313   if (opc1 != 0x3C) {
18314      vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
18315      return False;
18316   }
18317
18318   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
18319   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
18320   switch (opc2) {
18321      case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
18322         /* Note: Differences between xscmpudp and xscmpodp are only in
18323          * exception flag settings, which aren't supported anyway. */
18324         DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
18325                                           crfD, XA, XB);
18326         ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
18327         putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
18328         putFPCC( mkexpr( ccPPC32 ) );
18329         break;
18330
18331      default:
18332         vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
18333         return False;
18334   }
18335   return True;
18336}
18337
18338static void
18339do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
18340                 ppc_cmp_t cmp_type )
18341{
18342   IRTemp frA_hi     = newTemp(Ity_F64);
18343   IRTemp frB_hi     = newTemp(Ity_F64);
18344   IRTemp frA_lo     = newTemp(Ity_F64);
18345   IRTemp frB_lo     = newTemp(Ity_F64);
18346   IRTemp ccPPC32    = newTemp(Ity_I32);
18347   IRTemp ccIR_hi;
18348   IRTemp ccIR_lo;
18349
18350   IRTemp hiResult = newTemp(Ity_I64);
18351   IRTemp loResult = newTemp(Ity_I64);
18352   IRTemp hiEQlo = newTemp(Ity_I1);
18353   IRTemp all_elem_true = newTemp(Ity_I32);
18354   IRTemp all_elem_false = newTemp(Ity_I32);
18355
18356   assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
18357   assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
18358   assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
18359   assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
18360
18361   ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
18362                                       mkexpr( frA_hi ),
18363                                       mkexpr( frB_hi ) ) );
18364   ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
18365                                       mkexpr( frA_lo ),
18366                                       mkexpr( frB_lo ) ) );
18367
18368   if (cmp_type != PPC_CMP_GE) {
18369      assign( hiResult,
18370              unop( Iop_1Sto64,
18371                    binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
18372      assign( loResult,
18373              unop( Iop_1Sto64,
18374                    binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
18375   } else {
18376      // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
18377      // the other element compare may return "2" (for "equal to").
18378      IRTemp lo_GE = newTemp(Ity_I1);
18379      IRTemp hi_GE = newTemp(Ity_I1);
18380
18381      assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
18382                           binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
18383      assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
18384
18385      assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
18386                           binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
18387      assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
18388   }
18389
18390   // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
18391   assign( hiEQlo,
18392           binop( Iop_CmpEQ32,
18393                  unop( Iop_64to32, mkexpr( hiResult ) ),
18394                  unop( Iop_64to32, mkexpr( loResult ) ) ) );
18395   putVSReg( XT,
18396             binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
18397
18398   assign( all_elem_true,
18399           unop( Iop_1Uto32,
18400                 mkAND1( mkexpr( hiEQlo ),
18401                         binop( Iop_CmpEQ32,
18402                                mkU32( 0xffffffff ),
18403                                unop( Iop_64to32,
18404                                mkexpr( hiResult ) ) ) ) ) );
18405
18406   assign( all_elem_false,
18407           unop( Iop_1Uto32,
18408                 mkAND1( mkexpr( hiEQlo ),
18409                         binop( Iop_CmpEQ32,
18410                                mkU32( 0 ),
18411                                unop( Iop_64to32,
18412                                mkexpr( hiResult ) ) ) ) ) );
18413   assign( ccPPC32,
18414           binop( Iop_Or32,
18415                  binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
18416                  binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
18417
18418   if (flag_rC) {
18419      putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
18420   }
18421}
18422
18423/*
18424 * VSX Vector Compare Instructions
18425 */
18426static Bool
18427dis_vvec_cmp( UInt theInstr, UInt opc2 )
18428{
18429   /* XX3-Form */
18430   UChar opc1 = ifieldOPC( theInstr );
18431   UChar XT = ifieldRegXT ( theInstr );
18432   UChar XA = ifieldRegXA ( theInstr );
18433   UChar XB = ifieldRegXB ( theInstr );
18434   UChar flag_rC  = ifieldBIT10(theInstr);
18435   IRTemp vA = newTemp( Ity_V128 );
18436   IRTemp vB = newTemp( Ity_V128 );
18437
18438   if (opc1 != 0x3C) {
18439      vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
18440      return False;
18441   }
18442
18443   assign( vA, getVSReg( XA ) );
18444   assign( vB, getVSReg( XB ) );
18445
18446   switch (opc2) {
18447      case 0x18C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
18448      {
18449         DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18450             XT, XA, XB);
18451         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
18452         break;
18453      }
18454
18455      case 0x1CC:  // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
18456      {
18457         DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18458             XT, XA, XB);
18459         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
18460         break;
18461      }
18462
18463      case 0x1AC:  // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
18464      {
18465         DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18466             XT, XA, XB);
18467         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
18468         break;
18469      }
18470
18471      case 0x10C:  // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
18472      {
18473         IRTemp vD = newTemp(Ity_V128);
18474
18475         DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18476             XT, XA, XB);
18477         assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
18478         putVSReg( XT, mkexpr(vD) );
18479         if (flag_rC) {
18480            set_AV_CR6( mkexpr(vD), True );
18481         }
18482         break;
18483      }
18484
18485      case 0x14C:  // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
18486      {
18487         IRTemp vD = newTemp(Ity_V128);
18488
18489         DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18490             XT, XA, XB);
18491         assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
18492         putVSReg( XT, mkexpr(vD) );
18493         if (flag_rC) {
18494            set_AV_CR6( mkexpr(vD), True );
18495         }
18496         break;
18497      }
18498
18499      case 0x12C:  //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
18500      {
18501         IRTemp vD = newTemp(Ity_V128);
18502
18503         DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18504             XT, XA, XB);
18505         assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
18506         putVSReg( XT, mkexpr(vD) );
18507         if (flag_rC) {
18508            set_AV_CR6( mkexpr(vD), True );
18509         }
18510         break;
18511      }
18512
18513      default:
18514         vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
18515         return False;
18516   }
18517   return True;
18518}
18519/*
18520 * Miscellaneous VSX Scalar Instructions
18521 */
18522static Bool
18523dis_vxs_misc( UInt theInstr, UInt opc2, int allow_isa_3_0 )
18524{
18525#define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
18526   /* XX3-Form and XX2-Form */
18527   UChar opc1 = ifieldOPC( theInstr );
18528   UChar XT = ifieldRegXT ( theInstr );
18529   UChar XA = ifieldRegXA ( theInstr );
18530   UChar XB = ifieldRegXB ( theInstr );
18531   IRTemp vA = newTemp( Ity_V128 );
18532   IRTemp vB = newTemp( Ity_V128 );
18533
18534   if (opc1 != 0x3C) {
18535      vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
18536      return False;
18537   }
18538
18539   assign( vA, getVSReg( XA ) );
18540   assign( vB, getVSReg( XB ) );
18541
18542   /* For all the VSX move instructions, the contents of doubleword element 1
18543    * of VSX[XT] are undefined after the operation; therefore, we can simply
18544    * move the entire array element where it makes sense to do so.
18545    */
18546   if (( opc2 == 0x168 ) && ( IFIELD( theInstr, 19, 2 ) == 0 ) )
18547      {
18548         /* Special case of XX1-Form with immediate value
18549          *  xxspltib (VSX Vector Splat Immediate Byte)
18550          */
18551         UInt uim = IFIELD( theInstr, 11, 8 );
18552         UInt word_value = ( uim << 24 ) | ( uim << 16 ) | ( uim << 8 ) | uim;
18553
18554         DIP("xxspltib v%d,%d\n", (UInt)XT, uim);
18555         putVSReg(XT, binop( Iop_64HLtoV128,
18556                             binop( Iop_32HLto64,
18557                                    mkU32( word_value ),
18558                                    mkU32( word_value ) ),
18559                             binop( Iop_32HLto64,
18560                                    mkU32( word_value ),
18561                                    mkU32( word_value ) ) ) );
18562         return True;
18563      }
18564
18565   switch ( opc2 ) {
18566      case 0x0ec: // xscmpexpdp (VSX Scalar Compare Exponents Double-Precision)
18567      {
18568         /* Compare 64-bit data, 128-bit layout:
18569            src1[0:63] is double word, src1[64:127] is unused
18570            src2[0:63] is double word, src2[64:127] is unused
18571         */
18572         IRExpr *bit4, *bit5, *bit6, *bit7;
18573         UInt BF = IFIELD( theInstr, 23, 3 );
18574         IRTemp eq_lt_gt = newTemp( Ity_I32 );
18575         IRTemp CC = newTemp( Ity_I32 );
18576         IRTemp vA_hi = newTemp( Ity_I64 );
18577         IRTemp vB_hi = newTemp( Ity_I64 );
18578         IRExpr *mask = mkU64( 0x7FF0000000000000 );
18579
18580         DIP("xscmpexpdp %d,v%d,v%d\n", BF, XA, XB);
18581
18582         assign( vA_hi, unop( Iop_V128HIto64, mkexpr( vA ) ) );
18583         assign( vB_hi, unop( Iop_V128HIto64, mkexpr( vB ) ) );
18584
18585         /* A exp < B exp */
18586         bit4 = binop( Iop_CmpLT64U,
18587                      binop( Iop_And64,
18588                             mkexpr( vA_hi ),
18589                             mask ),
18590                      binop( Iop_And64,
18591                             mkexpr( vB_hi ),
18592                             mask ) );
18593         /*  A exp > B exp */
18594         bit5 = binop( Iop_CmpLT64U,
18595                      binop( Iop_And64,
18596                             mkexpr( vB_hi ),
18597                             mask ),
18598                      binop( Iop_And64,
18599                             mkexpr( vA_hi ),
18600                             mask ) );
18601         /* test equal */
18602         bit6 = binop( Iop_CmpEQ64,
18603                      binop( Iop_And64,
18604                             mkexpr( vA_hi ),
18605                             mask ),
18606                      binop( Iop_And64,
18607                             mkexpr( vB_hi ),
18608                             mask ) );
18609
18610         /* exp A or exp B is NaN */
18611         bit7 = mkOR1( is_NaN( Ity_I64, vA_hi ),
18612                       is_NaN( Ity_I64, vB_hi ) );
18613
18614         assign( eq_lt_gt, binop( Iop_Or32,
18615                                  binop( Iop_Shl32,
18616                                         unop( Iop_1Uto32, bit4 ),
18617                                         mkU8( 3) ),
18618                                  binop( Iop_Or32,
18619                                         binop( Iop_Shl32,
18620                                                unop( Iop_1Uto32, bit5 ),
18621                                                mkU8( 2) ),
18622                                         binop( Iop_Shl32,
18623                                                unop( Iop_1Uto32, bit6 ),
18624                                                mkU8( 1 ) ) ) ) );
18625         assign(CC, binop( Iop_Or32,
18626                           binop( Iop_And32,
18627                                  mkexpr( eq_lt_gt ) ,
18628                                  unop( Iop_Not32, unop( Iop_1Sto32, bit7 ) ) ),
18629                           unop( Iop_1Uto32, bit7 ) ) );
18630
18631         putGST_field( PPC_GST_CR, mkexpr( CC ), BF );
18632         putFPCC( mkexpr( CC ) );
18633         return True;
18634      }
18635      break;
18636
18637      case 0x14A: // xxextractuw (VSX Vector Extract Unsigned Word)
18638      {
18639         UInt uim = IFIELD( theInstr, 16, 4 );
18640
18641         DIP("xxextractuw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, uim);
18642
18643         putVSReg( XT,
18644                   binop( Iop_ShlV128,
18645                          binop( Iop_AndV128,
18646                                 binop( Iop_ShrV128,
18647                                        mkexpr( vB ),
18648                                        mkU8( ( 12 - uim ) * 8 ) ),
18649                                 binop(Iop_64HLtoV128,
18650                                       mkU64( 0 ),
18651                                       mkU64( 0xFFFFFFFF ) ) ),
18652                          mkU8( ( 32*2 ) ) ) );
18653         break;
18654      }
18655      case 0x16A: // xxinsertw (VSX Vector insert Word)
18656      {
18657         UInt uim = IFIELD( theInstr, 16, 4 );
18658         IRTemp vT = newTemp( Ity_V128 );
18659         IRTemp tmp = newTemp( Ity_V128 );
18660
18661         DIP("xxinsertw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, uim);
18662
18663         assign( vT, getVSReg( XT ) );
18664         assign( tmp, binop( Iop_AndV128,
18665                             mkexpr( vT ),
18666                             unop( Iop_NotV128,
18667                                   binop( Iop_ShlV128,
18668                                          binop( Iop_64HLtoV128,
18669                                                 mkU64( 0x0 ),
18670                                                 mkU64( 0xFFFFFFFF) ),
18671                                          mkU8( ( 12 - uim ) * 8 ) ) ) ) );
18672
18673         putVSReg( XT,
18674                   binop( Iop_OrV128,
18675                          binop( Iop_ShlV128,
18676                                 binop( Iop_AndV128,
18677                                        binop( Iop_ShrV128,
18678                                               mkexpr( vB ),
18679                                               mkU8( 32 * 2 ) ),
18680                                        binop( Iop_64HLtoV128,
18681                                               mkU64( 0 ),
18682                                               mkU64( 0xFFFFFFFF ) ) ),
18683                                 mkU8( ( 12 - uim ) * 8 ) ),
18684                          mkexpr( tmp ) ) );
18685         break;
18686      }
18687
18688      case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
18689      {
18690         /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
18691         IRTemp absVal = newTemp(Ity_V128);
18692         if (host_endness == VexEndnessLE) {
18693            IRTemp hi64 = newTemp(Ity_I64);
18694            IRTemp lo64 = newTemp(Ity_I64);
18695            assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) );
18696            assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) );
18697            assign( absVal, binop( Iop_64HLtoV128,
18698                                   binop( Iop_And64, mkexpr(hi64),
18699                                          mkU64(VG_PPC_SIGN_MASK) ),
18700                                   mkexpr(lo64) ) );
18701         } else {
18702            assign(absVal, binop(Iop_ShrV128,
18703                                 binop(Iop_ShlV128, mkexpr(vB),
18704                                       mkU8(1)), mkU8(1)));
18705         }
18706         DIP("xsabsdp v%d,v%d\n", XT, XB);
18707         putVSReg(XT, mkexpr(absVal));
18708         break;
18709      }
18710
18711      case 0x2b6: // xsxexpdp (VSX Scalar Extract Exponent Double-Precision)
18712                  // xsxsigdp (VSX Scalar Extract Significand Doulbe-Precision)
18713                  // xsvhpdp  (VSX Scalar Convert Half-Precision format
18714                  //           to Double-Precision format)
18715                  // xscvdphp (VSX Scalar round & convert Double-precision
18716                  //           format to Half-precision format)
18717      {
18718         IRTemp rT = newTemp( Ity_I64 );
18719         UInt inst_select = IFIELD( theInstr, 16, 5);
18720
18721         if (inst_select == 0) {
18722            DIP("xsxexpd %d,v%d\n", (UInt)XT, (UInt)XB);
18723
18724            assign( rT, binop( Iop_Shr64,
18725                               binop( Iop_And64,
18726                                      unop( Iop_V128HIto64, mkexpr( vB ) ),
18727                                      mkU64( 0x7FF0000000000000 ) ),
18728                               mkU8 ( 52 ) ) );
18729         } else if (inst_select == 1) {
18730            IRExpr *normal;
18731            IRTemp tmp = newTemp(Ity_I64);
18732
18733            DIP("xsxsigdp v%d,v%d\n",  (UInt)XT, (UInt)XB);
18734
18735            assign( tmp, unop( Iop_V128HIto64, mkexpr( vB ) ) );
18736
18737            /* Value is normal if it isn't infinite, zero or denormalized */
18738            normal = mkNOT1( mkOR1(
18739                                   mkOR1( is_NaN( Ity_I64, tmp ),
18740                                          is_Inf( Ity_I64, tmp ) ),
18741                                   mkOR1( is_Zero( Ity_I64, tmp ),
18742                                          is_Denorm( Ity_I64, tmp ) ) ) );
18743
18744            assign( rT, binop( Iop_Or64,
18745                               binop( Iop_And64,
18746                                      mkexpr( tmp ),
18747                                      mkU64( 0xFFFFFFFFFFFFF ) ),
18748                               binop( Iop_Shl64,
18749                                      unop( Iop_1Uto64, normal),
18750                                      mkU8( 52 ) ) ) );
18751            putIReg( XT, mkexpr( rT ) );
18752
18753        } else if (inst_select == 16) {
18754            IRTemp result = newTemp( Ity_V128 );
18755            IRTemp value = newTemp( Ity_I64 );
18756            /* Note: PPC only coverts the 16-bit value in the upper 64-bits
18757             * of the source V128 to a 64-bit value stored in the upper
18758             * 64-bits of the V128 result.  The contents of the lower 64-bits
18759             * is undefined.
18760             */
18761
18762            DIP("xscvhpdp v%d, v%d\n", (UInt)XT, (UInt)XB);
18763            assign( result, unop( Iop_F16toF64x2, mkexpr( vB ) ) );
18764
18765            putVSReg( XT, mkexpr( result ) );
18766
18767            assign( value, unop( Iop_V128HIto64, mkexpr( result ) ) );
18768            generate_store_FPRF( Ity_I64, value );
18769            return True;
18770
18771         } else if (inst_select == 17) {   // xscvdphp
18772            IRTemp value = newTemp( Ity_I32 );
18773            IRTemp result = newTemp( Ity_V128 );
18774            /* Note: PPC only coverts the 64-bit value in the upper 64-bits of
18775             * the V128 and stores the 16-bit result in the upper word of the
18776             * V128 result.  The contents of the lower 64-bits is undefined.
18777             */
18778            DIP("xscvdphp v%d, v%d\n", (UInt)XT, (UInt)XB);
18779            assign( result,  unop( Iop_F64toF16x2, mkexpr( vB ) ) );
18780            assign( value, unop( Iop_64to32, unop( Iop_V128HIto64,
18781                                                   mkexpr( result ) ) ) );
18782            putVSReg( XT, mkexpr( result ) );
18783            generate_store_FPRF( Ity_I16, value );
18784            return True;
18785
18786         } else {
18787            vex_printf( "dis_vxv_scalar_extract_exp_sig invalid inst_select (ppc)(opc2)\n" );
18788            vex_printf("inst_select = %d\n", inst_select);
18789            return False;
18790         }
18791      }
18792      break;
18793
18794      case 0x254:  // xststdcsp (VSX Scalar Test Data Class Single-Precision)
18795      case 0x2D4:  // xststdcdp (VSX Scalar Test Data Class Double-Precision)
18796      {
18797         /* These instructions only differ in that the single precision
18798            instruction, xststdcsp, has the additional constraint on the
18799            denormal test that the exponent be greater then zero and
18800            less then 0x381. */
18801         IRTemp vB_hi = newTemp( Ity_I64 );
18802         UInt BF = IFIELD( theInstr, 23, 3 );
18803         UInt DCMX_mask = IFIELD( theInstr, 16, 7 );
18804         IRTemp NaN = newTemp( Ity_I64 );
18805         IRTemp inf = newTemp( Ity_I64 );
18806         IRTemp zero = newTemp( Ity_I64 );
18807         IRTemp dnorm = newTemp( Ity_I64 );
18808         IRTemp pos = newTemp( Ity_I64 );
18809         IRTemp not_sp = newTemp( Ity_I64 );
18810         IRTemp DCM = newTemp( Ity_I64 );
18811         IRTemp CC = newTemp( Ity_I64 );
18812         IRTemp exponent = newTemp( Ity_I64 );
18813         IRTemp tmp = newTemp( Ity_I64 );
18814
18815         assign( vB_hi, unop( Iop_V128HIto64, mkexpr( vB ) ) );
18816
18817         assign( pos, unop( Iop_1Uto64,
18818                            binop( Iop_CmpEQ64,
18819                                   binop( Iop_Shr64,
18820                                          mkexpr( vB_hi ),
18821                                          mkU8( 63 ) ),
18822                                   mkU64( 0 ) ) ) );
18823
18824         assign( NaN, unop( Iop_1Uto64, is_NaN( Ity_I64, vB_hi ) ) );
18825         assign( inf, unop( Iop_1Uto64, is_Inf( Ity_I64, vB_hi ) ) );
18826         assign( zero, unop( Iop_1Uto64, is_Zero( Ity_I64, vB_hi ) ) );
18827
18828         if (opc2 == 0x254) {
18829            DIP("xststdcsp %d,v%d,%d\n", BF, (UInt)XB, DCMX_mask);
18830
18831            /* The least significant bit of the CC is set to 1 if the double
18832               precision value is not representable as a single precision
18833               value. The spec says the bit is set if:
18834                  src != convert_SPtoDP(convert_DPtoSP(src))
18835            */
18836            assign( tmp,
18837                    unop( Iop_ReinterpF64asI64,
18838                                unop( Iop_F32toF64,
18839                                      unop( Iop_TruncF64asF32,
18840                                            unop( Iop_ReinterpI64asF64,
18841                                                  mkexpr( vB_hi ) ) ) ) ) );
18842            assign( not_sp, unop( Iop_1Uto64,
18843                                  mkNOT1( binop( Iop_CmpEQ64,
18844                                                 mkexpr( vB_hi ),
18845                                                 mkexpr( tmp ) ) ) ) );
18846            assign( exponent,
18847                    binop( Iop_Shr64,
18848                           binop( Iop_And64,
18849                                  mkexpr( vB_hi ),
18850                                  mkU64( 0x7ff0000000000000 ) ),
18851                           mkU8( 52 ) ) );
18852            assign( dnorm, unop( Iop_1Uto64,
18853                                 mkOR1( is_Denorm( Ity_I64, vB_hi ),
18854                                        mkAND1( binop( Iop_CmpLT64U,
18855                                                       mkexpr( exponent ),
18856                                                       mkU64( 0x381 ) ),
18857                                                binop( Iop_CmpNE64,
18858                                                       mkexpr( exponent ),
18859                                                       mkU64( 0x0 ) ) ) ) ) );
18860
18861         } else {
18862            DIP("xststdcdp %d,v%d,%d\n", BF, (UInt)XB, DCMX_mask);
18863            assign( not_sp,  mkU64( 0 ) );
18864            assign( dnorm, unop( Iop_1Uto64, is_Denorm( Ity_I64, vB_hi ) ) );
18865         }
18866
18867         assign( DCM, create_DCM( Ity_I64, NaN, inf, zero, dnorm, pos ) );
18868         assign( CC,
18869                 binop( Iop_Or64,
18870                        binop( Iop_And64,    /* vB sign bit */
18871                               binop( Iop_Shr64,
18872                                      mkexpr( vB_hi ),
18873                                      mkU8( 60 ) ),
18874                               mkU64( 0x8 ) ),
18875                        binop( Iop_Or64,
18876                               binop( Iop_Shl64,
18877                                      unop( Iop_1Uto64,
18878                                            binop( Iop_CmpNE64,
18879                                                   binop( Iop_And64,
18880                                                          mkexpr( DCM ),
18881                                                          mkU64( DCMX_mask ) ),
18882                                                   mkU64( 0 ) ) ),
18883                                      mkU8( 1 ) ),
18884                               mkexpr( not_sp ) ) ) );
18885         putGST_field( PPC_GST_CR, unop( Iop_64to32, mkexpr( CC ) ), BF );
18886         putFPCC( unop( Iop_64to32, mkexpr( CC ) ) );
18887      }
18888      return True;
18889
18890      case 0x2C0: // xscpsgndp
18891      {
18892         /* Scalar copy sign double-precision */
18893         IRTemp vecA_signed = newTemp(Ity_I64);
18894         IRTemp vecB_unsigned = newTemp(Ity_I64);
18895         IRTemp vec_result = newTemp(Ity_V128);
18896         DIP("xscpsgndp v%d,v%d v%d\n", XT, XA, XB);
18897         assign( vecA_signed, binop( Iop_And64,
18898                                     unop( Iop_V128HIto64,
18899                                           mkexpr(vA)),
18900                                           mkU64(~VG_PPC_SIGN_MASK) ) );
18901         assign( vecB_unsigned, binop( Iop_And64,
18902                                       unop( Iop_V128HIto64,
18903                                             mkexpr(vB) ),
18904                                             mkU64(VG_PPC_SIGN_MASK) ) );
18905         assign( vec_result, binop( Iop_64HLtoV128,
18906                                    binop( Iop_Or64,
18907                                           mkexpr(vecA_signed),
18908                                           mkexpr(vecB_unsigned) ),
18909                                    mkU64(0x0ULL)));
18910         putVSReg(XT, mkexpr(vec_result));
18911         break;
18912      }
18913      case 0x2D2: // xsnabsdp
18914      {
18915         /* Scalar negative absolute value double-precision */
18916         IRTemp BHi_signed = newTemp(Ity_I64);
18917         DIP("xsnabsdp v%d,v%d\n", XT, XB);
18918         assign( BHi_signed, binop( Iop_Or64,
18919                                    unop( Iop_V128HIto64,
18920                                          mkexpr(vB) ),
18921                                          mkU64(~VG_PPC_SIGN_MASK) ) );
18922         putVSReg(XT, binop( Iop_64HLtoV128,
18923                             mkexpr(BHi_signed), mkU64(0x0ULL) ) );
18924         break;
18925      }
18926      case 0x2F2: // xsnegdp
18927      {
18928         /* Scalar negate double-precision */
18929         IRTemp BHi_signed = newTemp(Ity_I64);
18930         IRTemp BHi_unsigned = newTemp(Ity_I64);
18931         IRTemp BHi_negated = newTemp(Ity_I64);
18932         IRTemp BHi_negated_signbit = newTemp(Ity_I1);
18933         IRTemp vec_result = newTemp(Ity_V128);
18934         DIP("xsnabsdp v%d,v%d\n", XT, XB);
18935         assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) );
18936         assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed),
18937                                      mkU64(VG_PPC_SIGN_MASK) ) );
18938         assign( BHi_negated_signbit,
18939                 unop( Iop_Not1,
18940                       unop( Iop_32to1,
18941                             binop( Iop_Shr32,
18942                                    unop( Iop_64HIto32,
18943                                          binop( Iop_And64,
18944                                                 mkexpr(BHi_signed),
18945                                                 mkU64(~VG_PPC_SIGN_MASK) )
18946                                          ),
18947                                    mkU8(31) ) ) ) );
18948         assign( BHi_negated,
18949                 binop( Iop_Or64,
18950                        binop( Iop_32HLto64,
18951                               binop( Iop_Shl32,
18952                                      unop( Iop_1Uto32,
18953                                            mkexpr(BHi_negated_signbit) ),
18954                                      mkU8(31) ),
18955                               mkU32(0) ),
18956                        mkexpr(BHi_unsigned) ) );
18957         assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
18958                                    mkU64(0x0ULL)));
18959         putVSReg( XT, mkexpr(vec_result));
18960         break;
18961      }
18962      case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
18963      case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
18964      {
18965         IRTemp frA     = newTemp(Ity_I64);
18966         IRTemp frB     = newTemp(Ity_I64);
18967         Bool isMin = opc2 == 0x2A0 ? True : False;
18968         DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", XT, XA, XB);
18969
18970         assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
18971         assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
18972         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
18973
18974         break;
18975      }
18976      case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
18977      case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
18978      case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
18979      case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
18980      case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
18981      {
18982         IRTemp frB_I64 = newTemp(Ity_I64);
18983         IRExpr * frD_fp_round = NULL;
18984
18985         assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
18986         frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
18987
18988         DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
18989         putVSReg( XT,
18990                   binop( Iop_64HLtoV128,
18991                          unop( Iop_ReinterpF64asI64, frD_fp_round),
18992                          mkU64( 0 ) ) );
18993         break;
18994      }
18995      case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
18996      case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
18997                   * single-Precision)
18998                   */
18999      {
19000         IRTemp frB = newTemp(Ity_F64);
19001         IRTemp sqrt = newTemp(Ity_F64);
19002         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
19003         IRExpr* rm  = get_IR_roundingmode();
19004         Bool redp = opc2 == 0x034;
19005         DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", XT,
19006             XB);
19007
19008         assign( frB,
19009                 unop( Iop_ReinterpI64asF64,
19010                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
19011
19012         if (!redp)
19013            assign( sqrt,
19014                    binop( Iop_SqrtF64,
19015                           rm,
19016                           mkexpr(frB) ) );
19017         putVSReg( XT,
19018                      binop( Iop_64HLtoV128,
19019                             unop( Iop_ReinterpF64asI64,
19020                                   binop( Iop_RoundF64toF32, rm,
19021                                          triop( Iop_DivF64,
19022                                                 rm,
19023                                                 ieee_one,
19024                                                 redp ? mkexpr( frB ) :
19025                                                        mkexpr( sqrt ) ) ) ),
19026                             mkU64( 0 ) ) );
19027         break;
19028      }
19029
19030      case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
19031      case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
19032
19033      {
19034         IRTemp frB = newTemp(Ity_F64);
19035         IRTemp sqrt = newTemp(Ity_F64);
19036         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
19037         IRExpr* rm  = get_IR_roundingmode();
19038         Bool redp = opc2 == 0x0B4;
19039         DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", XT, XB);
19040         assign( frB,
19041                 unop( Iop_ReinterpI64asF64,
19042                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
19043
19044         if (!redp)
19045            assign( sqrt,
19046                    binop( Iop_SqrtF64,
19047                           rm,
19048                           mkexpr(frB) ) );
19049         putVSReg( XT,
19050                      binop( Iop_64HLtoV128,
19051                             unop( Iop_ReinterpF64asI64,
19052                                   triop( Iop_DivF64,
19053                                          rm,
19054                                          ieee_one,
19055                                          redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
19056                             mkU64( 0 ) ) );
19057         break;
19058      }
19059
19060      case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
19061      {
19062         IRTemp frB = newTemp(Ity_F64);
19063         IRExpr* rm  = get_IR_roundingmode();
19064         DIP("xsrsp v%d, v%d\n", XT, XB);
19065         assign( frB,
19066                 unop( Iop_ReinterpI64asF64,
19067                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
19068
19069         putVSReg( XT, binop( Iop_64HLtoV128,
19070                              unop( Iop_ReinterpF64asI64,
19071                                    binop( Iop_RoundF64toF32,
19072                                           rm,
19073                                           mkexpr( frB ) ) ),
19074                              mkU64( 0 ) ) );
19075         break;
19076      }
19077
19078      case 0x354: // xvtstdcsp (VSX Test Data Class Single-Precision)
19079      {
19080         UInt DX_mask = IFIELD( theInstr, 16, 5 );
19081         UInt DC_mask = IFIELD( theInstr, 6, 1 );
19082         UInt DM_mask = IFIELD( theInstr, 2, 1 );
19083         UInt DCMX_mask = (DC_mask << 6) | (DM_mask << 5) | DX_mask;
19084
19085         IRTemp match_value[4];
19086         IRTemp value[4];
19087         IRTemp NaN[4];
19088         IRTemp inf[4];
19089         IRTemp pos[4];
19090         IRTemp DCM[4];
19091         IRTemp zero[4];
19092         IRTemp dnorm[4];
19093         Int i;
19094
19095         DIP("xvtstdcsp v%d,v%d,%d\n", (UInt)XT, (UInt)XB, DCMX_mask);
19096
19097         for (i = 0; i < 4; i++) {
19098            NaN[i]   = newTemp(Ity_I32);
19099            inf[i]   = newTemp(Ity_I32);
19100            pos[i]   = newTemp(Ity_I32);
19101            DCM[i]   = newTemp(Ity_I32);
19102            zero[i]  = newTemp(Ity_I32);
19103            dnorm[i] = newTemp(Ity_I32);
19104
19105            value[i] = newTemp(Ity_I32);
19106            match_value[i] = newTemp(Ity_I32);
19107
19108            assign( value[i],
19109                    unop( Iop_64to32,
19110                          unop( Iop_V128to64,
19111                                binop( Iop_AndV128,
19112                                       binop( Iop_ShrV128,
19113                                              mkexpr( vB ),
19114                                              mkU8( (3-i)*32 ) ),
19115                                       binop( Iop_64HLtoV128,
19116                                              mkU64( 0x0 ),
19117                                              mkU64( 0xFFFFFFFF ) ) ) ) ) );
19118
19119            assign( pos[i], unop( Iop_1Uto32,
19120                                  binop( Iop_CmpEQ32,
19121                                         binop( Iop_Shr32,
19122                                                mkexpr( value[i] ),
19123                                                mkU8( 31 ) ),
19124                                         mkU32( 0 ) ) ) );
19125
19126            assign( NaN[i], unop( Iop_1Uto32, is_NaN( Ity_I32, value[i] ) ));
19127            assign( inf[i], unop( Iop_1Uto32, is_Inf( Ity_I32, value[i] ) ) );
19128            assign( zero[i], unop( Iop_1Uto32, is_Zero( Ity_I32, value[i] ) ) );
19129
19130            assign( dnorm[i], unop( Iop_1Uto32, is_Denorm( Ity_I32,
19131                                                           value[i] ) ) );
19132            assign( DCM[i], create_DCM( Ity_I32, NaN[i], inf[i], zero[i],
19133                                        dnorm[i], pos[i] ) );
19134
19135            assign( match_value[i],
19136                    unop( Iop_1Sto32,
19137                          binop( Iop_CmpNE32,
19138                                 binop( Iop_And32,
19139                                        mkU32( DCMX_mask ),
19140                                        mkexpr( DCM[i] ) ),
19141                                 mkU32( 0 ) ) ) );
19142         }
19143
19144         putVSReg( XT, binop( Iop_64HLtoV128,
19145                              binop( Iop_32HLto64,
19146                                     mkexpr( match_value[0] ),
19147                                     mkexpr( match_value[1] ) ),
19148                              binop( Iop_32HLto64,
19149                                     mkexpr( match_value[2] ),
19150                                     mkexpr( match_value[3] ) ) ) );
19151      }
19152      break;
19153
19154      case 0x360:  // xviexpsp  (VSX Vector Insert Exponent Single-Precision)
19155      {
19156            Int i;
19157            IRTemp new_XT[5];
19158            IRTemp A_value[4];
19159            IRTemp B_value[4];
19160            IRExpr *sign[4], *expr[4], *fract[4];
19161
19162            DIP("xviexpsp v%d,v%d\n", XT, XB);
19163            new_XT[0] = newTemp(Ity_V128);
19164            assign( new_XT[0], binop( Iop_64HLtoV128,
19165                                      mkU64( 0x0 ),
19166                                      mkU64( 0x0 ) ) );
19167
19168            for (i = 0; i < 4; i++) {
19169               A_value[i] = newTemp(Ity_I32);
19170               B_value[i] = newTemp(Ity_I32);
19171
19172               assign( A_value[i],
19173                       unop( Iop_64to32,
19174                             unop( Iop_V128to64,
19175                                   binop( Iop_AndV128,
19176                                          binop( Iop_ShrV128,
19177                                                 mkexpr( vA ),
19178                                                 mkU8( (3-i)*32 ) ),
19179                                          binop( Iop_64HLtoV128,
19180                                                 mkU64( 0x0 ),
19181                                                 mkU64( 0xFFFFFFFF ) ) ) ) ) );
19182               assign( B_value[i],
19183                       unop( Iop_64to32,
19184                             unop( Iop_V128to64,
19185                                   binop( Iop_AndV128,
19186                                          binop( Iop_ShrV128,
19187                                                 mkexpr( vB ),
19188                                                 mkU8( (3-i)*32 ) ),
19189                                          binop( Iop_64HLtoV128,
19190                                                 mkU64( 0x0 ),
19191                                                 mkU64( 0xFFFFFFFF ) ) ) ) ) );
19192
19193               sign[i] = binop( Iop_And32, mkexpr( A_value[i] ),
19194                                mkU32( 0x80000000 ) );
19195               expr[i] = binop( Iop_Shl32,
19196                                binop( Iop_And32, mkexpr( B_value[i] ),
19197                                       mkU32( 0xFF ) ),
19198                                mkU8( 23 ) );
19199               fract[i] = binop( Iop_And32, mkexpr( A_value[i] ),
19200                                 mkU32( 0x007FFFFF ) );
19201
19202               new_XT[i+1] = newTemp(Ity_V128);
19203               assign( new_XT[i+1],
19204                       binop( Iop_OrV128,
19205                              binop( Iop_ShlV128,
19206                                     binop( Iop_64HLtoV128,
19207                                            mkU64( 0 ),
19208                                            binop( Iop_32HLto64,
19209                                                   mkU32( 0 ),
19210                                                   binop( Iop_Or32,
19211                                                         binop( Iop_Or32,
19212                                                                 sign[i],
19213                                                                 expr[i] ),
19214                                                          fract[i] ) ) ),
19215                                     mkU8( (3-i)*32 ) ),
19216                              mkexpr( new_XT[i] ) ) );
19217            }
19218            putVSReg( XT, mkexpr( new_XT[4] ) );
19219      }
19220      break;
19221
19222      case 0x396:  // xsiexpdp (VSX Scalar Insert Exponent Double-Precision)
19223      {
19224         IRExpr *sign, *expr, *fract;
19225         UChar rA_addr = ifieldRegA(theInstr);
19226         UChar rB_addr = ifieldRegB(theInstr);
19227         IRTemp rA = newTemp( Ity_I64 );
19228         IRTemp rB = newTemp( Ity_I64 );
19229
19230         DIP("xsiexpdp v%d,%d,%d\n", (UInt)XT, (UInt)rA_addr, (UInt)rB_addr);
19231         assign( rA, getIReg(rA_addr));
19232         assign( rB, getIReg(rB_addr));
19233
19234         sign = binop( Iop_And64, mkexpr( rA ), mkU64( 0x8000000000000000 ) );
19235         expr = binop( Iop_Shl64,
19236                       binop( Iop_And64, mkexpr( rB ), mkU64( 0x7FF ) ),
19237                       mkU8( 52 ) );
19238         fract = binop( Iop_And64, mkexpr( rA ), mkU64( 0x000FFFFFFFFFFFFF ) );
19239
19240         putVSReg( XT, binop( Iop_64HLtoV128,
19241                              binop( Iop_Or64,
19242                                     binop( Iop_Or64, sign, expr ),
19243                                     fract ),
19244                              mkU64( 0 ) ) );
19245      }
19246      break;
19247
19248      case 0x3B6: // xvxexpdp (VSX Vector Extract Exponent Double-Precision)
19249                  // xvxsigdp (VSX Vector Extract Significand Double-Precision)
19250                  // xxbrh
19251                  // xvxexpsp (VSX Vector Extract Exponent Single-Precision)
19252                  // xvxsigsp (VSX Vector Extract Significand Single-Precision)
19253                  // xxbrw
19254                  // xxbrd
19255                  // xxbrq
19256                  // xvcvhpsp (VSX Vector Convert Half-Precision format to Single-Precision format)
19257                  // xvcvsphp (VSX Vector round and convert Single-Precision format to Half-Precision format)
19258      {
19259         UInt inst_select = IFIELD( theInstr, 16, 5);
19260
19261         if (inst_select == 0) {
19262            DIP("xvxexpdp v%d,v%d\n", XT, XB);
19263
19264            putVSReg( XT, binop( Iop_ShrV128,
19265                                 binop( Iop_AndV128,
19266                                        mkexpr( vB ),
19267                                        binop( Iop_64HLtoV128,
19268                                               mkU64( 0x7FF0000000000000 ),
19269                                               mkU64( 0x7FF0000000000000 ) ) ),
19270                                 mkU8( 52 ) ) );
19271
19272         } else if (inst_select == 1) {
19273            Int i;
19274            IRExpr *normal[2];
19275            IRTemp value[2];
19276            IRTemp new_XT[3];
19277
19278            DIP("xvxsigdp v%d,v%d\n", XT, XB);
19279            new_XT[0] = newTemp(Ity_V128);
19280            assign( new_XT[0], binop( Iop_64HLtoV128,
19281                                      mkU64( 0x0 ),
19282                                      mkU64( 0x0 ) ) );
19283
19284            for (i = 0; i < 2; i++) {
19285               value[i] = newTemp(Ity_I64);
19286               assign( value[i],
19287                       unop( Iop_V128to64,
19288                            binop( Iop_AndV128,
19289                                    binop( Iop_ShrV128,
19290                                           mkexpr( vB ),
19291                                           mkU8( (1-i)*64 ) ),
19292                                    binop( Iop_64HLtoV128,
19293                                           mkU64( 0x0 ),
19294                                           mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
19295
19296               /* Value is normal if it isn't infinite, zero or denormalized */
19297               normal[i] = mkNOT1( mkOR1(
19298                                         mkOR1( is_NaN( Ity_I64, value[i] ),
19299                                                is_Inf( Ity_I64, value[i] ) ),
19300                                         mkOR1( is_Zero( Ity_I64, value[i] ),
19301                                                is_Denorm( Ity_I64,
19302                                                           value[i] ) ) ) );
19303               new_XT[i+1] = newTemp(Ity_V128);
19304
19305               assign( new_XT[i+1],
19306                       binop( Iop_OrV128,
19307                              binop( Iop_ShlV128,
19308                                     binop( Iop_64HLtoV128,
19309                                            mkU64( 0x0 ),
19310                                            binop( Iop_Or64,
19311                                                   binop( Iop_And64,
19312                                                          mkexpr( value[i] ),
19313                                                          mkU64( 0xFFFFFFFFFFFFF ) ),
19314                                                   binop( Iop_Shl64,
19315                                                          unop( Iop_1Uto64,
19316                                                                normal[i]),
19317                                                          mkU8( 52 ) ) ) ),
19318                                     mkU8( (1-i)*64 ) ),
19319                              mkexpr( new_XT[i] ) ) );
19320            }
19321            putVSReg( XT, mkexpr( new_XT[2] ) );
19322
19323         } else if (inst_select == 7) {
19324            IRTemp sub_element0 = newTemp( Ity_V128 );
19325            IRTemp sub_element1 = newTemp( Ity_V128 );
19326
19327            DIP("xxbrh v%d, v%d\n", (UInt)XT, (UInt)XB);
19328
19329            assign( sub_element0,
19330                    binop( Iop_ShrV128,
19331                           binop( Iop_AndV128,
19332                                  binop(Iop_64HLtoV128,
19333                                        mkU64( 0xFF00FF00FF00FF00 ),
19334                                        mkU64( 0xFF00FF00FF00FF00 ) ),
19335                                  mkexpr( vB ) ),
19336                           mkU8( 8 ) ) );
19337            assign( sub_element1,
19338                    binop( Iop_ShlV128,
19339                           binop( Iop_AndV128,
19340                                  binop(Iop_64HLtoV128,
19341                                        mkU64( 0x00FF00FF00FF00FF ),
19342                                        mkU64( 0x00FF00FF00FF00FF ) ),
19343                                  mkexpr( vB ) ),
19344                           mkU8( 8 ) ) );
19345
19346            putVSReg(XT, binop( Iop_OrV128,
19347                                mkexpr( sub_element1 ),
19348                                mkexpr( sub_element0 ) ) );
19349
19350         } else if (inst_select == 8) {
19351            DIP("xvxexpsp v%d,v%d\n", XT, XB);
19352
19353            putVSReg( XT, binop( Iop_ShrV128,
19354                                 binop( Iop_AndV128,
19355                                        mkexpr( vB ),
19356                                        binop( Iop_64HLtoV128,
19357                                               mkU64( 0x7F8000007F800000 ),
19358                                               mkU64( 0x7F8000007F800000 ) ) ),
19359                                 mkU8( 23 ) ) );
19360         } else if (inst_select == 9) {
19361            Int i;
19362            IRExpr *normal[4];
19363            IRTemp value[4];
19364            IRTemp new_value[4];
19365            IRTemp new_XT[5];
19366
19367            DIP("xvxsigsp v%d,v%d\n", XT, XB);
19368            new_XT[0] = newTemp(Ity_V128);
19369            assign( new_XT[0], binop( Iop_64HLtoV128,
19370                                      mkU64( 0x0 ),
19371                                      mkU64( 0x0 ) ) );
19372
19373            for (i = 0; i < 4; i++) {
19374               value[i] = newTemp(Ity_I32);
19375               assign( value[i],
19376                       unop( Iop_64to32,
19377                             unop( Iop_V128to64,
19378                                   binop( Iop_AndV128,
19379                                          binop( Iop_ShrV128,
19380                                                 mkexpr( vB ),
19381                                                 mkU8( (3-i)*32 ) ),
19382                                          binop( Iop_64HLtoV128,
19383                                                 mkU64( 0x0 ),
19384                                                 mkU64( 0xFFFFFFFF ) ) ) ) ) );
19385
19386               new_XT[i+1] = newTemp(Ity_V128);
19387
19388               /* Value is normal if it isn't infinite, zero or denormalized */
19389               normal[i] = mkNOT1( mkOR1(
19390                                         mkOR1( is_NaN( Ity_I32, value[i] ),
19391                                                is_Inf( Ity_I32, value[i] ) ),
19392                                         mkOR1( is_Zero( Ity_I32, value[i] ),
19393                                                is_Denorm( Ity_I32,
19394                                                           value[i] ) ) ) );
19395               new_value[i] = newTemp(Ity_I32);
19396               assign( new_value[i],
19397                       binop( Iop_Or32,
19398                              binop( Iop_And32,
19399                                     mkexpr( value[i] ),
19400                                     mkU32( 0x7FFFFF ) ),
19401                              binop( Iop_Shl32,
19402                                     unop( Iop_1Uto32,
19403                                           normal[i]),
19404                                     mkU8( 23 ) ) ) );
19405
19406               assign( new_XT[i+1],
19407                       binop( Iop_OrV128,
19408                              binop( Iop_ShlV128,
19409                                     binop( Iop_64HLtoV128,
19410                                            mkU64( 0x0 ),
19411                                            binop( Iop_32HLto64,
19412                                                   mkU32( 0x0 ),
19413                                                   mkexpr( new_value[i] ) ) ),
19414                                     mkU8( (3-i)*32 ) ),
19415                              mkexpr( new_XT[i] ) ) );
19416            }
19417            putVSReg( XT, mkexpr( new_XT[4] ) );
19418
19419         } else if (inst_select == 15) {
19420            IRTemp sub_element0 = newTemp( Ity_V128 );
19421            IRTemp sub_element1 = newTemp( Ity_V128 );
19422            IRTemp sub_element2 = newTemp( Ity_V128 );
19423            IRTemp sub_element3 = newTemp( Ity_V128 );
19424
19425            DIP("xxbrw v%d, v%d\n", (UInt)XT, (UInt)XB);
19426
19427            assign( sub_element0,
19428                    binop( Iop_ShrV128,
19429                           binop( Iop_AndV128,
19430                                  binop(Iop_64HLtoV128,
19431                                        mkU64( 0xFF000000FF000000 ),
19432                                        mkU64( 0xFF000000FF000000 ) ),
19433                                  mkexpr( vB ) ),
19434                           mkU8( 24 ) ) );
19435            assign( sub_element1,
19436                    binop( Iop_ShrV128,
19437                           binop( Iop_AndV128,
19438                                  binop(Iop_64HLtoV128,
19439                                        mkU64( 0x00FF000000FF0000 ),
19440                                        mkU64( 0x00FF000000FF0000 ) ),
19441                                  mkexpr( vB ) ),
19442                           mkU8( 8 ) ) );
19443            assign( sub_element2,
19444                    binop( Iop_ShlV128,
19445                           binop( Iop_AndV128,
19446                                  binop(Iop_64HLtoV128,
19447                                        mkU64( 0x0000FF000000FF00 ),
19448                                        mkU64( 0x0000FF000000FF00 ) ),
19449                                  mkexpr( vB ) ),
19450                           mkU8( 8 ) ) );
19451            assign( sub_element3,
19452                    binop( Iop_ShlV128,
19453                           binop( Iop_AndV128,
19454                                  binop(Iop_64HLtoV128,
19455                                        mkU64( 0x00000000FF000000FF ),
19456                                        mkU64( 0x00000000FF000000FF ) ),
19457                                  mkexpr( vB ) ),
19458                           mkU8( 24 ) ) );
19459
19460            putVSReg( XT,
19461                      binop( Iop_OrV128,
19462                             binop( Iop_OrV128,
19463                                    mkexpr( sub_element3 ),
19464                                    mkexpr( sub_element2 ) ),
19465                             binop( Iop_OrV128,
19466                                    mkexpr( sub_element1 ),
19467                                    mkexpr( sub_element0 ) ) ) );
19468
19469         } else if (inst_select == 23) {
19470            DIP("xxbrd v%d, v%d\n", (UInt)XT, (UInt)XB);
19471
19472            int i;
19473            int shift = 56;
19474            IRTemp sub_element[16];
19475            IRTemp new_xT[17];
19476
19477            new_xT[0] = newTemp( Ity_V128 );
19478            assign( new_xT[0], binop( Iop_64HLtoV128,
19479                                      mkU64( 0 ),
19480                                      mkU64( 0 ) ) );
19481
19482            for ( i = 0; i < 4; i++ ) {
19483               new_xT[i+1] = newTemp( Ity_V128 );
19484               sub_element[i]   = newTemp( Ity_V128 );
19485               sub_element[i+4] = newTemp( Ity_V128 );
19486
19487               assign( sub_element[i],
19488                       binop( Iop_ShrV128,
19489                              binop( Iop_AndV128,
19490                                     binop( Iop_64HLtoV128,
19491                                            mkU64( (0xFFULL << (7 - i) * 8) ),
19492                                            mkU64( (0xFFULL << (7 - i) * 8) ) ),
19493                                     mkexpr( vB ) ),
19494                              mkU8( shift ) ) );
19495
19496               assign( sub_element[i+4],
19497                       binop( Iop_ShlV128,
19498                              binop( Iop_AndV128,
19499                                     binop( Iop_64HLtoV128,
19500                                            mkU64( (0xFFULL << i*8) ),
19501                                            mkU64( (0xFFULL << i*8) ) ),
19502                                     mkexpr( vB ) ),
19503                              mkU8( shift ) ) );
19504               shift = shift - 16;
19505
19506               assign( new_xT[i+1],
19507                       binop( Iop_OrV128,
19508                              mkexpr( new_xT[i] ),
19509                              binop( Iop_OrV128,
19510                                     mkexpr ( sub_element[i] ),
19511                                     mkexpr ( sub_element[i+4] ) ) ) );
19512               }
19513
19514            putVSReg( XT, mkexpr( new_xT[4] ) );
19515
19516         } else if (inst_select == 24) {
19517            // xvcvhpsp, (VSX Vector Convert half-precision format to
19518            //           Single-precision format)
19519            /* only supported on ISA 3.0 and newer */
19520            IRTemp result = newTemp( Ity_V128 );
19521            IRTemp src  = newTemp( Ity_I64 );
19522
19523            if (!allow_isa_3_0) return False;
19524
19525            DIP("xvcvhpsp v%d,v%d\n", XT,XB);
19526            /* The instruction does not set the C or FPCC fields.  The
19527             * instruction takes four 16-bit values stored in a 128-bit value
19528             * as follows:   x V | x V | x V | x V  where V is a 16-bit
19529             * value and x is an unused 16-bit value. To use Iop_F16toF32x4
19530             * the four 16-bit values will be gathered into a single 64 bit
19531             * value.  The backend will scatter the four 16-bit values back
19532             * into a 128-bit operand before issuing the instruction.
19533             */
19534            /* Gather 16-bit float values from V128 source into new 64-bit
19535             * source value for the Iop.
19536             */
19537            assign( src,
19538                    unop( Iop_V128to64,
19539                          binop( Iop_Perm8x16,
19540                                 mkexpr( vB ),
19541                                 binop ( Iop_64HLtoV128,
19542                                         mkU64( 0 ),
19543                                         mkU64( 0x020306070A0B0E0F) ) ) ) );
19544
19545            assign( result, unop( Iop_F16toF32x4, mkexpr( src ) ) );
19546
19547            putVSReg( XT, mkexpr( result ) );
19548
19549         } else if (inst_select == 25) {
19550            // xvcvsphp, (VSX Vector round and Convert single-precision
19551            // format to half-precision format)
19552            /* only supported on ISA 3.0 and newer */
19553            IRTemp result = newTemp( Ity_V128 );
19554            IRTemp tmp64  = newTemp( Ity_I64 );
19555
19556            if (!allow_isa_3_0) return False;
19557            DIP("xvcvsphp v%d,v%d\n", XT,XB);
19558
19559            /* Iop_F32toF16x4 is V128 -> I64, scatter the 16-bit floats in the
19560             * I64 result to the V128 register to store.
19561             */
19562            assign( tmp64, unop( Iop_F32toF16x4, mkexpr( vB ) ) );
19563
19564            /* Scatter 16-bit float values from returned 64-bit value
19565             * of V128 result.
19566             */
19567            if (host_endness == VexEndnessLE)
19568               /* Note location 0 may have a valid number in it.  Location
19569                * 15 should always be zero.  Use 0xF to put zeros in the
19570                * desired bytes.
19571                */
19572               assign( result,
19573                       binop( Iop_Perm8x16,
19574                              binop( Iop_64HLtoV128,
19575                                     mkexpr( tmp64 ),
19576                                     mkU64( 0 ) ),
19577                              binop ( Iop_64HLtoV128,
19578                                      mkU64( 0x0F0F00010F0F0203 ),
19579                                      mkU64( 0x0F0F04050F0F0607 ) ) ) );
19580            else
19581               assign( result,
19582                       binop( Iop_Perm8x16,
19583                              binop( Iop_64HLtoV128,
19584                                     mkexpr( tmp64 ),
19585                                     mkU64( 0 ) ),
19586                              binop ( Iop_64HLtoV128,
19587                                      mkU64( 0x0F0F06070F0F0405 ),
19588                                      mkU64( 0x0F0F02030F0F0001 ) ) ) );
19589            putVSReg( XT, mkexpr( result ) );
19590
19591         } else if ( inst_select == 31 ) {
19592            int i;
19593            int shift_left = 8;
19594            int shift_right = 120;
19595            IRTemp sub_element[16];
19596            IRTemp new_xT[9];
19597
19598            DIP("xxbrq v%d, v%d\n", (UInt) XT, (UInt) XB);
19599
19600            new_xT[0] = newTemp( Ity_V128 );
19601            assign( new_xT[0], binop( Iop_64HLtoV128,
19602                                      mkU64( 0 ),
19603                                      mkU64( 0 ) ) );
19604
19605            for ( i = 0; i < 8; i++ ) {
19606               new_xT[i+1] = newTemp( Ity_V128 );
19607               sub_element[i]   = newTemp( Ity_V128 );
19608               sub_element[i+8] = newTemp( Ity_V128 );
19609
19610               assign( sub_element[i],
19611                       binop( Iop_ShrV128,
19612                              binop( Iop_AndV128,
19613                                     binop( Iop_64HLtoV128,
19614                                            mkU64( ( 0xFFULL << (7 - i) * 8 ) ),
19615                                            mkU64( 0x0ULL ) ),
19616                                     mkexpr( vB ) ),
19617                              mkU8( shift_right ) ) );
19618               shift_right = shift_right - 16;
19619
19620               assign( sub_element[i+8],
19621                       binop( Iop_ShlV128,
19622                              binop( Iop_AndV128,
19623                                     binop( Iop_64HLtoV128,
19624                                            mkU64( 0x0ULL ),
19625                                            mkU64( ( 0xFFULL << (7 - i) * 8 ) ) ),
19626                                     mkexpr( vB ) ),
19627                              mkU8( shift_left ) ) );
19628               shift_left = shift_left + 16;
19629
19630               assign( new_xT[i+1],
19631                       binop( Iop_OrV128,
19632                              mkexpr( new_xT[i] ),
19633                              binop( Iop_OrV128,
19634                                     mkexpr ( sub_element[i] ),
19635                                     mkexpr ( sub_element[i+8] ) ) ) );
19636               }
19637
19638            putVSReg( XT, mkexpr( new_xT[8] ) );
19639
19640         } else {
19641            vex_printf("dis_vxs_misc(ppc) Invalid instruction selection\n");
19642            return False;
19643         }
19644         break;
19645      }
19646
19647      case 0x3D4: // xvtstdcdp (VSX Test Data Class Double-Precision)
19648      {
19649         UInt DX_mask = IFIELD( theInstr, 16, 5 );
19650         UInt DC_mask = IFIELD( theInstr, 6, 1 );
19651         UInt DM_mask = IFIELD( theInstr, 2, 1 );
19652         UInt DCMX_mask = (DC_mask << 6) | (DM_mask << 5) | DX_mask;
19653
19654         IRTemp NaN[2], inf[2], zero[2], dnorm[2], pos[2], DCM[2];
19655         IRTemp match_value[2];
19656         IRTemp value[2];
19657         Int i;
19658
19659         DIP("xvtstdcdp v%d,v%d,%d\n", (UInt)XT, (UInt)XB, DCMX_mask);
19660
19661         for (i = 0; i < 2; i++) {
19662            NaN[i] = newTemp(Ity_I64);
19663            inf[i] = newTemp(Ity_I64);
19664            pos[i] = newTemp(Ity_I64);
19665            DCM[i] = newTemp(Ity_I64);
19666            zero[i] = newTemp(Ity_I64);
19667            dnorm[i] = newTemp(Ity_I64);
19668
19669            value[i] = newTemp(Ity_I64);
19670            match_value[i] = newTemp(Ity_I64);
19671
19672            assign( value[i],
19673                    unop( Iop_V128to64,
19674                          binop( Iop_AndV128,
19675                                 binop( Iop_ShrV128,
19676                                        mkexpr( vB ),
19677                                        mkU8( (1-i)*64 ) ),
19678                                 binop( Iop_64HLtoV128,
19679                                        mkU64( 0x0 ),
19680                                        mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
19681
19682            assign( pos[i], unop( Iop_1Uto64,
19683                                 binop( Iop_CmpEQ64,
19684                                        binop( Iop_Shr64,
19685                                               mkexpr( value[i] ),
19686                                               mkU8( 63 ) ),
19687                                        mkU64( 0 ) ) ) );
19688
19689            assign( NaN[i], unop( Iop_1Uto64, is_NaN( Ity_I64, value[i] ) ) );
19690            assign( inf[i], unop( Iop_1Uto64, is_Inf( Ity_I64, value[i] ) ) );
19691            assign( zero[i], unop( Iop_1Uto64, is_Zero( Ity_I64, value[i] ) ) );
19692            assign( dnorm[i], unop( Iop_1Uto64, is_Denorm( Ity_I64,
19693                                                           value[i] ) ) );
19694
19695            assign( DCM[i], create_DCM( Ity_I64, NaN[i], inf[i], zero[i],
19696                                        dnorm[i], pos[i] ) );
19697
19698            assign( match_value[i],
19699                    unop( Iop_1Sto64,
19700                          binop( Iop_CmpNE64,
19701                                 binop( Iop_And64,
19702                                        mkU64( DCMX_mask ),
19703                                        mkexpr( DCM[i] ) ),
19704                                 mkU64( 0 ) ) ) );
19705         }
19706         putVSReg( XT, binop( Iop_64HLtoV128,
19707                              mkexpr( match_value[0] ),
19708                              mkexpr( match_value[1] ) ) );
19709      }
19710      break;
19711
19712      case 0x3E0:  // xviexpdp (VSX Vector Insert Exponent Double-Precision)
19713      {
19714            Int i;
19715            IRTemp new_XT[3];
19716            IRTemp A_value[2];
19717            IRTemp B_value[2];
19718            IRExpr *sign[2], *expr[2], *fract[2];
19719
19720            DIP("xviexpdp v%d,v%d\n", XT, XB);
19721            new_XT[0] = newTemp(Ity_V128);
19722            assign( new_XT[0], binop( Iop_64HLtoV128,
19723                                      mkU64( 0x0 ),
19724                                      mkU64( 0x0 ) ) );
19725
19726            for (i = 0; i < 2; i++) {
19727               A_value[i] = newTemp(Ity_I64);
19728               B_value[i] = newTemp(Ity_I64);
19729
19730               assign( A_value[i],
19731                       unop( Iop_V128to64,
19732                             binop( Iop_AndV128,
19733                                    binop( Iop_ShrV128,
19734                                           mkexpr( vA ),
19735                                           mkU8( (1-i)*64 ) ),
19736                                    binop( Iop_64HLtoV128,
19737                                           mkU64( 0x0 ),
19738                                           mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
19739               assign( B_value[i],
19740                       unop( Iop_V128to64,
19741                             binop( Iop_AndV128,
19742                                    binop( Iop_ShrV128,
19743                                           mkexpr( vB ),
19744                                           mkU8( (1-i)*64 ) ),
19745                                    binop( Iop_64HLtoV128,
19746                                           mkU64( 0x0 ),
19747                                           mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
19748
19749               sign[i] = binop( Iop_And64, mkexpr( A_value[i] ),
19750                                mkU64( 0x8000000000000000 ) );
19751               expr[i] = binop( Iop_Shl64,
19752                                binop( Iop_And64, mkexpr( B_value[i] ),
19753                                       mkU64( 0x7FF ) ),
19754                                mkU8( 52 ) );
19755               fract[i] = binop( Iop_And64, mkexpr( A_value[i] ),
19756                                 mkU64( 0x000FFFFFFFFFFFFF ) );
19757
19758               new_XT[i+1] = newTemp(Ity_V128);
19759               assign( new_XT[i+1],
19760                       binop( Iop_OrV128,
19761                              binop( Iop_ShlV128,
19762                                     binop( Iop_64HLtoV128,
19763                                            mkU64( 0 ),
19764                                            binop( Iop_Or64,
19765                                                   binop( Iop_Or64,
19766                                                          sign[i],
19767                                                          expr[i] ),
19768                                                   fract[i] ) ),
19769                                     mkU8( (1-i)*64 ) ),
19770                              mkexpr( new_XT[i] ) ) );
19771            }
19772            putVSReg( XT, mkexpr( new_XT[2] ) );
19773      }
19774      break;
19775
19776      default:
19777         vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
19778         return False;
19779   }
19780   return True;
19781}
19782
19783/*
19784 * VSX Logical Instructions
19785 */
19786static Bool
19787dis_vx_logic ( UInt theInstr, UInt opc2 )
19788{
19789   /* XX3-Form */
19790   UChar opc1 = ifieldOPC( theInstr );
19791   UChar XT = ifieldRegXT ( theInstr );
19792   UChar XA = ifieldRegXA ( theInstr );
19793   UChar XB = ifieldRegXB ( theInstr );
19794   IRTemp vA = newTemp( Ity_V128 );
19795   IRTemp vB = newTemp( Ity_V128 );
19796
19797   if (opc1 != 0x3C) {
19798      vex_printf( "dis_vx_logic(ppc)(instr)\n" );
19799      return False;
19800   }
19801
19802   assign( vA, getVSReg( XA ) );
19803   assign( vB, getVSReg( XB ) );
19804
19805   switch (opc2) {
19806      case 0x268: // xxlxor
19807         DIP("xxlxor v%d,v%d,v%d\n", XT, XA, XB);
19808         putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
19809         break;
19810      case 0x248: // xxlor
19811         DIP("xxlor v%d,v%d,v%d\n", XT, XA, XB);
19812         putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
19813         break;
19814      case 0x288: // xxlnor
19815         DIP("xxlnor v%d,v%d,v%d\n", XT, XA, XB);
19816         putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
19817                                                 mkexpr( vB ) ) ) );
19818         break;
19819      case 0x208: // xxland
19820         DIP("xxland v%d,v%d,v%d\n", XT, XA, XB);
19821         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
19822         break;
19823      case 0x228: //xxlandc
19824         DIP("xxlandc v%d,v%d,v%d\n", XT, XA, XB);
19825         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
19826                                                               mkexpr( vB ) ) ) );
19827         break;
19828      case 0x2A8: // xxlorc (VSX Logical OR with complement)
19829         DIP("xxlorc v%d,v%d,v%d\n", XT, XA, XB);
19830         putVSReg( XT, binop( Iop_OrV128,
19831                              mkexpr( vA ),
19832                              unop( Iop_NotV128, mkexpr( vB ) ) ) );
19833         break;
19834      case 0x2C8: // xxlnand (VSX Logical NAND)
19835         DIP("xxlnand v%d,v%d,v%d\n", XT, XA, XB);
19836         putVSReg( XT, unop( Iop_NotV128,
19837                             binop( Iop_AndV128, mkexpr( vA ),
19838                                    mkexpr( vB ) ) ) );
19839         break;
19840      case 0x2E8: // xxleqv (VSX Logical Equivalence)
19841         DIP("xxleqv v%d,v%d,v%d\n", XT, XA, XB);
19842         putVSReg( XT, unop( Iop_NotV128,
19843                             binop( Iop_XorV128,
19844                             mkexpr( vA ), mkexpr( vB ) ) ) );
19845         break;
19846      default:
19847         vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
19848         return False;
19849   }
19850   return True;
19851}
19852
19853/*
19854 * VSX Load Instructions
19855 * NOTE: VSX supports word-aligned storage access.
19856 */
19857static Bool
19858dis_vx_load ( UInt theInstr )
19859{
19860   /* XX1-Form */
19861   UChar opc1 = ifieldOPC( theInstr );
19862   UChar XT = ifieldRegXT ( theInstr );
19863   UChar rA_addr = ifieldRegA( theInstr );
19864   UChar rB_addr = ifieldRegB( theInstr );
19865   UInt opc2 = ifieldOPClo10( theInstr );
19866
19867   IRType ty = mode64 ? Ity_I64 : Ity_I32;
19868   IRTemp EA = newTemp( ty );
19869
19870   if (opc1 != 0x1F) {
19871      vex_printf( "dis_vx_load(ppc)(instr)\n" );
19872      return False;
19873   }
19874
19875   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
19876
19877   switch (opc2) {
19878   case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
19879   {
19880      IRExpr * exp;
19881      DIP("lxsiwzx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
19882
19883      if (host_endness == VexEndnessLE)
19884         exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
19885      else
19886         exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
19887
19888      putVSReg( XT, binop( Iop_64HLtoV128,
19889                           unop( Iop_32Uto64, exp),
19890                           mkU64(0) ) );
19891      break;
19892   }
19893   case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
19894   {
19895      IRExpr * exp;
19896      DIP("lxsiwax %d,r%u,r%u\n", XT, rA_addr, rB_addr);
19897
19898      if (host_endness == VexEndnessLE)
19899         exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
19900      else
19901         exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
19902
19903      putVSReg( XT, binop( Iop_64HLtoV128,
19904                           unop( Iop_32Sto64, exp),
19905                           mkU64(0) ) );
19906      break;
19907   }
19908   case 0x10C: // lxvx
19909   {
19910      UInt ea_off = 0;
19911      IRExpr* irx_addr;
19912      IRTemp word[4];
19913      int i;
19914
19915      DIP("lxvx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
19916
19917      if ( host_endness == VexEndnessBE ) {
19918         for ( i = 3; i>= 0; i-- ) {
19919            word[i] = newTemp( Ity_I64 );
19920
19921            irx_addr =
19922               binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
19923                      ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
19924
19925            assign( word[i], unop( Iop_32Uto64,
19926                                   load( Ity_I32, irx_addr ) ) );
19927            ea_off += 4;
19928         }
19929
19930         putVSReg( XT, binop( Iop_64HLtoV128,
19931                              binop( Iop_Or64,
19932                                     mkexpr( word[2] ),
19933                                     binop( Iop_Shl64,
19934                                            mkexpr( word[3] ),
19935                                            mkU8( 32 ) ) ),
19936                              binop( Iop_Or64,
19937                                     mkexpr( word[0] ),
19938                                     binop( Iop_Shl64,
19939                                            mkexpr( word[1] ),
19940                                            mkU8( 32 ) ) ) ) );
19941      } else {
19942         for ( i = 0; i< 4; i++ ) {
19943            word[i] = newTemp( Ity_I64 );
19944
19945            irx_addr =
19946               binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
19947                      ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
19948
19949            assign( word[i], unop( Iop_32Uto64,
19950                                   load( Ity_I32, irx_addr ) ) );
19951            ea_off += 4;
19952         }
19953
19954         putVSReg( XT, binop( Iop_64HLtoV128,
19955                              binop( Iop_Or64,
19956                                     mkexpr( word[2] ),
19957                                     binop( Iop_Shl64,
19958                                            mkexpr( word[3] ),
19959                                            mkU8( 32 ) ) ),
19960                              binop( Iop_Or64,
19961                                     mkexpr( word[0] ),
19962                                     binop( Iop_Shl64,
19963                                            mkexpr( word[1] ),
19964                                            mkU8( 32 ) ) ) ) );
19965      }
19966      break;
19967   }
19968
19969   case 0x10D: // lxvl
19970   {
19971      DIP("lxvl %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
19972
19973      IRTemp byte[16];
19974      UInt i;
19975      UInt ea_off = 0;
19976      IRExpr* irx_addr;
19977      IRTemp tmp_low[9];
19978      IRTemp tmp_hi[9];
19979      IRTemp shift = newTemp( Ity_I8 );
19980      IRTemp nb_gt16 = newTemp( Ity_I8 );
19981      IRTemp ld_result = newTemp( Ity_V128 );
19982      IRTemp nb_not_zero = newTemp( Ity_I64 );
19983
19984      IRTemp base_addr = newTemp( ty );
19985
19986      tmp_low[0] = newTemp( Ity_I64 );
19987      tmp_hi[0] = newTemp( Ity_I64 );
19988
19989      assign( base_addr, ea_rAor0( rA_addr ) );
19990      assign( tmp_low[0], mkU64( 0 ) );
19991      assign( tmp_hi[0], mkU64( 0 ) );
19992
19993      /* shift is 15 - nb, where nb = rB[0:7], used to zero out upper bytes */
19994      assign( nb_not_zero, unop( Iop_1Sto64,
19995                                  binop( Iop_CmpNE64,
19996                                         mkU64( 0 ),
19997                                         binop( Iop_Shr64,
19998                                                getIReg( rB_addr ),
19999                                                mkU8( 56 ) ) ) ) );
20000
20001      assign( nb_gt16, unop( Iop_1Sto8,
20002                             binop( Iop_CmpLT64U,
20003                                    binop( Iop_Shr64,
20004                                           getIReg( rB_addr ),
20005                                           mkU8( 60 ) ),
20006                                    mkU64( 1 ) ) ) );
20007
20008      /* Set the shift to 0, by ANDing with nb_gt16.  nb_gt16 will be all
20009       * zeros if nb > 16.  This will result in quad word load being stored.
20010       */
20011      assign( shift,
20012              binop( Iop_And8,
20013                     unop( Iop_64to8,
20014                           binop( Iop_Mul64,
20015                                  binop( Iop_Sub64,
20016                                         mkU64 ( 16 ),
20017                                         binop( Iop_Shr64,
20018                                                getIReg( rB_addr ),
20019                                                mkU8( 56 ) ) ),
20020                                  mkU64( 8 ) ) ),
20021                     mkexpr( nb_gt16 ) ) );
20022
20023      /* fetch all 16 bytes, we will remove what we don't want later */
20024      if ( host_endness == VexEndnessBE ) {
20025         for ( i = 0; i < 8; i++ ) {
20026            byte[i] = newTemp( Ity_I64 );
20027            tmp_hi[i+1] = newTemp( Ity_I64 );
20028
20029            irx_addr =
20030               binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20031                      ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20032            ea_off += 1;
20033
20034            assign( byte[i], binop( Iop_Shl64,
20035                                      unop( Iop_8Uto64,
20036                                            load( Ity_I8, irx_addr ) ),
20037                                      mkU8( 8 * ( 7 - i ) ) ) );
20038
20039            assign( tmp_hi[i+1], binop( Iop_Or64,
20040                                        mkexpr( byte[i] ),
20041                                        mkexpr( tmp_hi[i] ) ) );
20042         }
20043
20044         for ( i = 0; i < 8; i++ ) {
20045            byte[i+8] = newTemp( Ity_I64 );
20046            tmp_low[i+1] = newTemp( Ity_I64 );
20047
20048            irx_addr =
20049               binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20050                      ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20051            ea_off += 1;
20052
20053            assign( byte[i+8], binop( Iop_Shl64,
20054                                    unop( Iop_8Uto64,
20055                                          load( Ity_I8, irx_addr ) ),
20056                                    mkU8( 8 * ( 7 - i ) ) ) );
20057
20058            assign( tmp_low[i+1], binop( Iop_Or64,
20059                                         mkexpr( byte[i+8] ),
20060                                         mkexpr( tmp_low[i] ) ) );
20061         }
20062         assign( ld_result, binop( Iop_ShlV128,
20063                                   binop( Iop_ShrV128,
20064                                          binop( Iop_64HLtoV128,
20065                                                 mkexpr( tmp_hi[8] ),
20066                                                 mkexpr( tmp_low[8] ) ),
20067                                          mkexpr( shift ) ),
20068                                   mkexpr( shift ) ) );
20069      } else {
20070         for ( i = 0; i < 8; i++ ) {
20071            byte[i] = newTemp( Ity_I64 );
20072            tmp_low[i+1] = newTemp( Ity_I64 );
20073
20074            irx_addr =
20075               binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20076                      ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20077            ea_off += 1;
20078
20079            assign( byte[i], binop( Iop_Shl64,
20080                                    unop( Iop_8Uto64,
20081                                          load( Ity_I8, irx_addr ) ),
20082                                    mkU8( 8 * i ) ) );
20083
20084            assign( tmp_low[i+1],
20085                    binop( Iop_Or64,
20086                           mkexpr( byte[i] ), mkexpr( tmp_low[i] ) ) );
20087         }
20088
20089         for ( i = 0; i < 8; i++ ) {
20090            byte[i + 8] = newTemp( Ity_I64 );
20091            tmp_hi[i+1] = newTemp( Ity_I64 );
20092
20093            irx_addr =
20094               binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20095                      ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20096            ea_off += 1;
20097
20098            assign( byte[i+8], binop( Iop_Shl64,
20099                                      unop( Iop_8Uto64,
20100                                            load( Ity_I8, irx_addr ) ),
20101                                      mkU8( 8 * i ) ) );
20102
20103            assign( tmp_hi[i+1], binop( Iop_Or64,
20104                                        mkexpr( byte[i+8] ),
20105                                        mkexpr( tmp_hi[i] ) ) );
20106         }
20107         assign( ld_result, binop( Iop_ShrV128,
20108                                   binop( Iop_ShlV128,
20109                                          binop( Iop_64HLtoV128,
20110                                                 mkexpr( tmp_hi[8] ),
20111                                                 mkexpr( tmp_low[8] ) ),
20112                                          mkexpr( shift ) ),
20113                                   mkexpr( shift ) ) );
20114      }
20115
20116
20117      /* If nb = 0, mask out the calculated load result so the stored
20118       * value is zero.
20119       */
20120
20121      putVSReg( XT, binop( Iop_AndV128,
20122                           mkexpr( ld_result ),
20123                           binop( Iop_64HLtoV128,
20124                                  mkexpr( nb_not_zero ),
20125                                  mkexpr( nb_not_zero ) ) ) );
20126      break;
20127   }
20128
20129   case 0x12D: // lxvll (Load VSX Vector Left-Justified with Length XX1 form)
20130   {
20131      IRTemp byte[16];
20132      IRTemp tmp_low[9];
20133      IRTemp tmp_hi[9];
20134      IRTemp mask = newTemp(Ity_V128);
20135      IRTemp rB = newTemp( Ity_I64 );
20136      IRTemp nb = newTemp( Ity_I64 );
20137      IRTemp nb_zero = newTemp(Ity_V128);
20138      IRTemp mask_shift = newTemp(Ity_I64);
20139      Int i;
20140      UInt ea_off = 0;
20141      IRExpr* irx_addr;
20142      IRTemp base_addr = newTemp( ty );
20143      IRTemp nb_compare_zero = newTemp( Ity_I64 );
20144
20145      DIP("lxvll %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20146
20147      tmp_low[0] = newTemp(Ity_I64);
20148      tmp_hi[0] = newTemp(Ity_I64);
20149
20150      assign( rB, getIReg(rB_addr));
20151      assign( base_addr, ea_rAor0( rA_addr ) );
20152      assign( tmp_low[0], mkU64( 0 ) );
20153      assign( tmp_hi[0], mkU64( 0 ) );
20154
20155      /* mask_shift is number of 16 bytes minus (nb times 8-bits per byte) */
20156      assign( nb, binop( Iop_Shr64, mkexpr( rB ), mkU8( 56 )  ) );
20157
20158      assign( nb_compare_zero, unop( Iop_1Sto64,
20159                                     binop( Iop_CmpEQ64,
20160                                            mkexpr( nb ),
20161                                            mkU64( 0 ) ) ) );
20162
20163      /* nb_zero is 0xFF..FF if the nb_field = 0 */
20164      assign( nb_zero, binop( Iop_64HLtoV128,
20165                              mkexpr( nb_compare_zero ),
20166                              mkexpr( nb_compare_zero ) ) );
20167
20168      assign( mask_shift, binop( Iop_Sub64,
20169                                 mkU64( 16*8 ),
20170                                 binop( Iop_Mul64,
20171                                        mkexpr( nb ),
20172                                        mkU64( 8 ) ) ) );
20173
20174      /* fetch all 16 bytes, we will remove what we don't want later */
20175      for (i = 0; i < 8; i++) {
20176         byte[i] = newTemp(Ity_I64);
20177         tmp_hi[i+1] = newTemp(Ity_I64);
20178
20179         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20180                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20181         ea_off += 1;
20182
20183         /* Instruction always loads in Big Endian format */
20184         assign( byte[i], binop( Iop_Shl64,
20185                                 unop( Iop_8Uto64,
20186                                       load( Ity_I8, irx_addr ) ),
20187                                 mkU8( 8 * (7 - i) ) ) );
20188         assign( tmp_hi[i+1],
20189                 binop( Iop_Or64,
20190                        mkexpr( byte[i] ), mkexpr( tmp_hi[i] ) ) );
20191      }
20192
20193      for (i = 0; i < 8; i++) {
20194         byte[i + 8]  = newTemp(Ity_I64);
20195         tmp_low[i+1] = newTemp(Ity_I64);
20196
20197         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20198                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20199         ea_off += 1;
20200
20201         /* Instruction always loads in Big Endian format */
20202        assign( byte[i+8], binop( Iop_Shl64,
20203                                   unop( Iop_8Uto64,
20204                                         load( Ity_I8, irx_addr ) ),
20205                                   mkU8( 8 * (7 - i) ) ) );
20206         assign( tmp_low[i+1], binop( Iop_Or64,
20207                                      mkexpr( byte[i+8] ),
20208                                      mkexpr( tmp_low[i] ) ) );
20209      }
20210
20211      /* Create mask to clear the right most 16 - nb bytes, set to zero
20212       * if nb= 0.
20213       */
20214      assign( mask, binop( Iop_AndV128,
20215                          binop( Iop_ShlV128,
20216                                  binop( Iop_ShrV128,
20217                                         mkV128( 0xFFFF ),
20218                                         unop( Iop_64to8, mkexpr( mask_shift ) ) ),
20219                                  unop( Iop_64to8, mkexpr( mask_shift ) ) ),
20220                           unop( Iop_NotV128, mkexpr( nb_zero ) ) ) );
20221
20222      putVSReg( XT, binop( Iop_AndV128,
20223                           mkexpr( mask ),
20224                           binop( Iop_64HLtoV128,
20225                                  mkexpr( tmp_hi[8] ),
20226                                  mkexpr( tmp_low[8] ) ) ) );
20227      break;
20228   }
20229
20230   case 0x16C: // lxvwsx
20231   {
20232      IRTemp data = newTemp( Ity_I64 );
20233
20234      DIP("lxvwsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20235
20236      /* The load is a 64-bit fetch that is Endian aware, just want
20237       * the lower 32 bits. */
20238      if ( host_endness == VexEndnessBE ) {
20239         UInt ea_off = 4;
20240         IRExpr* irx_addr;
20241
20242         irx_addr =
20243            binop( mkSzOp( ty, Iop_Sub8 ), mkexpr( EA ),
20244                   ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20245
20246         assign( data, binop( Iop_And64,
20247                              load( Ity_I64, irx_addr ),
20248                              mkU64( 0xFFFFFFFF ) ) );
20249
20250      } else {
20251         assign( data, binop( Iop_And64,
20252                              load( Ity_I64, mkexpr( EA ) ),
20253                              mkU64( 0xFFFFFFFF ) ) );
20254      }
20255
20256      /* Take lower 32-bits and spat across the four word positions */
20257      putVSReg( XT,
20258                binop( Iop_64HLtoV128,
20259                       binop( Iop_Or64,
20260                              mkexpr( data ),
20261                              binop( Iop_Shl64,
20262                                     mkexpr( data ),
20263                                     mkU8( 32 ) ) ),
20264                       binop( Iop_Or64,
20265                              mkexpr( data ),
20266                              binop( Iop_Shl64,
20267                                     mkexpr( data ),
20268                                     mkU8( 32 ) ) ) ) );
20269      break;
20270   }
20271
20272   case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
20273   {
20274      IRExpr * exp;
20275      DIP("lxsspx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20276      /* Take 32-bit floating point value in the upper half of the fetched
20277       * 64-bit value, convert to 64-bit floating point value and load into
20278       * top word of V128.
20279       */
20280      exp = unop( Iop_ReinterpF64asI64,
20281                  unop( Iop_F32toF64,
20282                        unop( Iop_ReinterpI32asF32,
20283                              load( Ity_I32, mkexpr( EA ) ) ) ) );
20284
20285      putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
20286      break;
20287   }
20288   case 0x24C: // lxsdx
20289   {
20290      IRExpr * exp;
20291      DIP("lxsdx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20292      exp = load( Ity_I64, mkexpr( EA ) );
20293      // We need to pass an expression of type Ity_V128 with putVSReg, but the load
20294      // we just performed is only a DW.  But since the contents of VSR[XT] element 1
20295      // are undefined after this operation, we can just do a splat op.
20296      putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
20297      break;
20298   }
20299
20300   case 0x30D: // lxsibzx
20301   {
20302      IRExpr *byte;
20303      IRExpr* irx_addr;
20304
20305      DIP("lxsibzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20306
20307      if ( host_endness == VexEndnessBE )
20308         irx_addr = binop( Iop_Sub64, mkexpr( EA ), mkU64( 7 ) );
20309
20310      else
20311         irx_addr = mkexpr( EA );
20312
20313      byte = load( Ity_I64, irx_addr );
20314      putVSReg( XT, binop( Iop_64HLtoV128,
20315                            binop( Iop_And64,
20316                                   byte,
20317                                   mkU64( 0xFF ) ),
20318                           mkU64( 0 ) ) );
20319      break;
20320   }
20321
20322   case 0x32D: // lxsihzx
20323   {
20324      IRExpr *byte;
20325      IRExpr* irx_addr;
20326
20327      DIP("lxsihzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20328
20329      if ( host_endness == VexEndnessBE )
20330         irx_addr = binop( Iop_Sub64, mkexpr( EA ), mkU64( 6 ) );
20331
20332      else
20333         irx_addr = mkexpr( EA );
20334
20335      byte = load( Ity_I64, irx_addr );
20336      putVSReg( XT, binop( Iop_64HLtoV128,
20337                            binop( Iop_And64,
20338                                   byte,
20339                                   mkU64( 0xFFFF ) ),
20340                           mkU64( 0 ) ) );
20341      break;
20342   }
20343   case 0x34C: // lxvd2x
20344   {
20345      IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
20346      IRExpr * high, *low;
20347      ULong ea_off = 8;
20348      IRExpr* high_addr;
20349      DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20350      high = load( Ity_I64, mkexpr( EA ) );
20351      high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
20352            : mkU32( ea_off ) );
20353      low = load( Ity_I64, high_addr );
20354      putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
20355      break;
20356   }
20357   case 0x14C: // lxvdsx
20358   {
20359      IRTemp data = newTemp(Ity_I64);
20360      DIP("lxvdsx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20361      assign( data, load( Ity_I64, mkexpr( EA ) ) );
20362      putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
20363      break;
20364   }
20365   case 0x30C:
20366   {
20367      IRExpr *t0;
20368
20369      DIP("lxvw4x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20370
20371      /* The load will result in the data being in BE order. */
20372      if (host_endness == VexEndnessLE) {
20373         IRExpr *t0_BE;
20374         IRTemp perm_LE = newTemp(Ity_V128);
20375
20376         t0_BE = load( Ity_V128, mkexpr( EA ) );
20377
20378         /*  Permute the data to LE format */
20379         assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL),
20380                                 mkU64(0x0405060700010203ULL)));
20381
20382         t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) );
20383      } else {
20384         t0 = load( Ity_V128, mkexpr( EA ) );
20385      }
20386
20387      putVSReg( XT, t0 );
20388      break;
20389   }
20390
20391   case 0x32C: // lxvh8x
20392   {
20393      DIP("lxvh8x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20394
20395      IRTemp h_word[8];
20396      int i;
20397      UInt ea_off = 0;
20398      IRExpr* irx_addr;
20399      IRTemp tmp_low[5];
20400      IRTemp tmp_hi[5];
20401
20402      tmp_low[0] = newTemp( Ity_I64 );
20403      tmp_hi[0] = newTemp( Ity_I64 );
20404      assign( tmp_low[0], mkU64( 0 ) );
20405      assign( tmp_hi[0], mkU64( 0 ) );
20406
20407      for ( i = 0; i < 4; i++ ) {
20408         h_word[i]    = newTemp(Ity_I64);
20409         tmp_low[i+1] = newTemp(Ity_I64);
20410
20411         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20412                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20413         ea_off += 2;
20414
20415         assign( h_word[i], binop( Iop_Shl64,
20416                                   unop( Iop_16Uto64,
20417                                         load( Ity_I16, irx_addr ) ),
20418                                   mkU8( 16 * ( 3 - i ) ) ) );
20419
20420         assign( tmp_low[i+1],
20421                 binop( Iop_Or64,
20422                        mkexpr( h_word[i] ), mkexpr( tmp_low[i] ) ) );
20423      }
20424
20425      for ( i = 0; i < 4; i++ ) {
20426         h_word[i+4]   = newTemp( Ity_I64 );
20427         tmp_hi[i+1] = newTemp( Ity_I64 );
20428
20429         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20430                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20431         ea_off += 2;
20432
20433         assign( h_word[i+4], binop( Iop_Shl64,
20434                                     unop( Iop_16Uto64,
20435                                           load( Ity_I16, irx_addr ) ),
20436                                     mkU8( 16 * ( 3 - i ) ) ) );
20437
20438         assign( tmp_hi[i+1], binop( Iop_Or64,
20439                                     mkexpr( h_word[i+4] ),
20440                                     mkexpr( tmp_hi[i] ) ) );
20441      }
20442      putVSReg( XT, binop( Iop_64HLtoV128,
20443                           mkexpr( tmp_low[4] ), mkexpr( tmp_hi[4] ) ) );
20444      break;
20445   }
20446
20447   case 0x36C: // lxvb16x
20448   {
20449      DIP("lxvb16x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20450
20451      IRTemp byte[16];
20452      int i;
20453      UInt ea_off = 0;
20454      IRExpr* irx_addr;
20455      IRTemp tmp_low[9];
20456      IRTemp tmp_hi[9];
20457
20458      tmp_low[0] = newTemp( Ity_I64 );
20459      tmp_hi[0] = newTemp( Ity_I64 );
20460      assign( tmp_low[0], mkU64( 0 ) );
20461      assign( tmp_hi[0], mkU64( 0 ) );
20462
20463      for ( i = 0; i < 8; i++ ) {
20464         byte[i] = newTemp( Ity_I64 );
20465         tmp_low[i+1] = newTemp( Ity_I64 );
20466
20467         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20468                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20469         ea_off += 1;
20470
20471         assign( byte[i], binop( Iop_Shl64,
20472                                 unop( Iop_8Uto64,
20473                                       load( Ity_I8, irx_addr ) ),
20474                                 mkU8( 8 * ( 7 - i ) ) ) );
20475
20476         assign( tmp_low[i+1],
20477                 binop( Iop_Or64,
20478                        mkexpr( byte[i] ), mkexpr( tmp_low[i] ) ) );
20479      }
20480
20481      for ( i = 0; i < 8; i++ ) {
20482         byte[i + 8] = newTemp( Ity_I64 );
20483         tmp_hi[i+1] = newTemp( Ity_I64 );
20484
20485         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20486                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20487         ea_off += 1;
20488
20489         assign( byte[i+8], binop( Iop_Shl64,
20490                                   unop( Iop_8Uto64,
20491                                         load( Ity_I8, irx_addr ) ),
20492                                   mkU8( 8 * ( 7 - i ) ) ) );
20493         assign( tmp_hi[i+1], binop( Iop_Or64,
20494                                     mkexpr( byte[i+8] ),
20495                                     mkexpr( tmp_hi[i] ) ) );
20496      }
20497      putVSReg( XT, binop( Iop_64HLtoV128,
20498                           mkexpr( tmp_low[8] ), mkexpr( tmp_hi[8] ) ) );
20499      break;
20500   }
20501
20502   default:
20503      vex_printf( "dis_vx_load(ppc)(opc2)\n" );
20504      return False;
20505   }
20506   return True;
20507}
20508
20509/*
20510 * VSX Move Instructions
20511 */
20512static Bool
20513dis_vx_move ( UInt theInstr )
20514{
20515   /* XX1-Form */
20516   UChar opc1 = ifieldOPC( theInstr );
20517   UChar XS = ifieldRegXS( theInstr );
20518   UChar rA_addr = ifieldRegA( theInstr );
20519   UChar rB_addr = ifieldRegB( theInstr );
20520   IRTemp vS = newTemp( Ity_V128 );
20521   UInt opc2 = ifieldOPClo10( theInstr );
20522   IRType ty = Ity_I64;
20523
20524   if ( opc1 != 0x1F ) {
20525      vex_printf( "dis_vx_move(ppc)(instr)\n" );
20526      return False;
20527   }
20528
20529   switch (opc2) {
20530   case 0x133: // mfvsrld RA,XS   Move From VSR Lower Doubleword
20531      DIP("mfvsrld %d,r%u\n", (UInt)XS, rA_addr);
20532
20533      assign( vS, getVSReg( XS ) );
20534      putIReg( rA_addr, unop(Iop_V128to64, mkexpr( vS) ) );
20535
20536      break;
20537
20538   case 0x193: // mfvsrdd  XT,RA,RB  Move to VSR Double Doubleword
20539   {
20540      IRTemp tmp = newTemp( Ity_I32 );
20541
20542      DIP("mfvsrdd %d,r%u\n", (UInt)XS, rA_addr);
20543
20544      assign( tmp, unop( Iop_64to32, getIReg(rA_addr) ) );
20545      assign( vS, binop( Iop_64HLtoV128,
20546                         binop( Iop_32HLto64,
20547                                mkexpr( tmp ),
20548                                mkexpr( tmp ) ),
20549                         binop( Iop_32HLto64,
20550                                mkexpr( tmp ),
20551                                mkexpr( tmp ) ) ) );
20552      putVSReg( XS, mkexpr( vS ) );
20553   }
20554   break;
20555
20556   case 0x1B3: // mtvsrws  XT,RA  Move to VSR word & Splat
20557   {
20558      IRTemp rA = newTemp( ty );
20559      IRTemp rB = newTemp( ty );
20560
20561      DIP("mfvsrws %d,r%u\n", (UInt)XS, rA_addr);
20562
20563      if ( rA_addr == 0 )
20564         assign( rA, mkU64 ( 0 ) );
20565      else
20566         assign( rA, getIReg(rA_addr) );
20567
20568      assign( rB, getIReg(rB_addr) );
20569      assign( vS, binop( Iop_64HLtoV128, mkexpr( rA ), mkexpr( rB ) ) );
20570      putVSReg( XS, mkexpr( vS ) );
20571   }
20572   break;
20573
20574   default:
20575      vex_printf( "dis_vx_move(ppc)(opc2)\n" );
20576      return False;
20577   }
20578   return True;
20579}
20580
20581/*
20582 * VSX Store Instructions
20583 * NOTE: VSX supports word-aligned storage access.
20584 */
20585static Bool
20586dis_vx_store ( UInt theInstr )
20587{
20588   /* XX1-Form */
20589   UChar opc1 = ifieldOPC( theInstr );
20590   UChar XS = ifieldRegXS( theInstr );
20591   UChar rA_addr = ifieldRegA( theInstr );
20592   UChar rB_addr = ifieldRegB( theInstr );
20593   IRTemp vS = newTemp( Ity_V128 );
20594   UInt opc2 = ifieldOPClo10( theInstr );
20595
20596   IRType ty = mode64 ? Ity_I64 : Ity_I32;
20597   IRTemp EA = newTemp( ty );
20598
20599   if (opc1 != 0x1F) {
20600      vex_printf( "dis_vx_store(ppc)(instr)\n" );
20601      return False;
20602   }
20603
20604   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
20605   assign( vS, getVSReg( XS ) );
20606
20607   switch (opc2) {
20608   case 0x08C:
20609   {
20610     /* Need the next to the most significant 32-bit word from
20611      * the 128-bit vector.
20612      */
20613      IRExpr * high64, * low32;
20614      DIP("stxsiwx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
20615      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
20616      low32  = unop( Iop_64to32, high64 );
20617      store( mkexpr( EA ), low32 );
20618      break;
20619   }
20620
20621   case 0x18C: // stxvx Store VSX Vector Indexed
20622   {
20623      UInt ea_off = 0;
20624      IRExpr* irx_addr;
20625      IRTemp word0 = newTemp( Ity_I64 );
20626      IRTemp word1 = newTemp( Ity_I64 );
20627      IRTemp word2 = newTemp( Ity_I64 );
20628      IRTemp word3 = newTemp( Ity_I64 );
20629      DIP("stxvx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
20630
20631      assign( word0,  binop( Iop_Shr64,
20632                             unop( Iop_V128HIto64, mkexpr( vS ) ),
20633                             mkU8( 32 ) ) );
20634
20635      assign( word1, binop( Iop_And64,
20636                            unop( Iop_V128HIto64, mkexpr( vS ) ),
20637                            mkU64( 0xFFFFFFFF ) ) );
20638
20639      assign( word2, binop( Iop_Shr64,
20640                            unop( Iop_V128to64, mkexpr( vS ) ),
20641                            mkU8( 32 ) ) );
20642
20643      assign( word3, binop( Iop_And64,
20644                            unop( Iop_V128to64, mkexpr( vS ) ),
20645                            mkU64( 0xFFFFFFFF ) ) );
20646
20647      if (host_endness == VexEndnessBE) {
20648         store( mkexpr( EA ), unop( Iop_64to32, mkexpr( word0 ) ) );
20649
20650         ea_off += 4;
20651         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20652                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20653
20654         store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) );
20655
20656         ea_off += 4;
20657         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20658                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20659
20660         store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) );
20661         ea_off += 4;
20662         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20663                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20664
20665         store( irx_addr, unop( Iop_64to32, mkexpr( word3 ) ) );
20666      } else {
20667         store( mkexpr( EA ), unop( Iop_64to32, mkexpr( word3 ) ) );
20668
20669         ea_off += 4;
20670         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20671                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20672
20673         store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) );
20674
20675         ea_off += 4;
20676         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20677                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20678
20679         store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) );
20680         ea_off += 4;
20681         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20682                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20683
20684         store( irx_addr, unop( Iop_64to32, mkexpr( word0 ) ) );
20685      }
20686      break;
20687   }
20688
20689   case 0x18D: // stxvl Store VSX Vector Indexed
20690   {
20691      UInt ea_off = 0;
20692      IRExpr* irx_addr;
20693      IRTemp word0 = newTemp( Ity_I64 );
20694      IRTemp word1 = newTemp( Ity_I64 );
20695      IRTemp word2 = newTemp( Ity_I64 );
20696      IRTemp word3 = newTemp( Ity_I64 );
20697      IRTemp shift = newTemp( Ity_I8 );
20698      IRTemp nb_gt16 = newTemp( Ity_I8 );
20699      IRTemp nb_zero = newTemp( Ity_V128 );
20700      IRTemp nb = newTemp( Ity_I8 );
20701      IRTemp nb_field = newTemp( Ity_I64 );
20702      IRTemp n_bytes = newTemp( Ity_I8 );
20703      IRTemp base_addr = newTemp( ty );
20704      IRTemp current_mem = newTemp( Ity_V128 );
20705      IRTemp store_val = newTemp( Ity_V128 );
20706      IRTemp nb_mask = newTemp( Ity_V128 );
20707
20708      DIP("stxvl %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
20709
20710      assign( nb_field, binop( Iop_Shr64,
20711                               getIReg(rB_addr),
20712                               mkU8( 56 ) ) );
20713
20714      assign( nb, unop( Iop_64to8, mkexpr( nb_field ) ) );
20715
20716      /* nb_gt16 will be all zeros if nb > 16 */
20717      assign( nb_gt16, unop( Iop_1Sto8,
20718                             binop( Iop_CmpLT64U,
20719                                    binop( Iop_Shr64,
20720                                           mkexpr( nb_field ),
20721                                           mkU8( 4 ) ),
20722                                    mkU64( 1 ) ) ) );
20723
20724      /* nb_zero is 0xFF..FF if the nb_field = 0 */
20725      assign( nb_zero, binop( Iop_64HLtoV128,
20726                              unop( Iop_1Sto64,
20727                                    binop( Iop_CmpEQ64,
20728                                           mkexpr( nb_field ),
20729                                           mkU64( 0 ) ) ),
20730                              unop( Iop_1Sto64,
20731                                    binop( Iop_CmpEQ64,
20732                                           mkexpr( nb_field ),
20733                                           mkU64( 0 ) ) ) ) );
20734
20735      /* set n_bytes to 0 if nb >= 16.  Otherwise, set to nb. */
20736      assign( n_bytes, binop( Iop_And8, mkexpr( nb ), mkexpr( nb_gt16 ) ) );
20737      assign( shift, unop( Iop_64to8,
20738                           binop( Iop_Mul64,
20739                                  binop( Iop_Sub64,
20740                                         mkU64( 16 ),
20741                                         unop( Iop_8Uto64,
20742                                               mkexpr( n_bytes ) ) ),
20743                                  mkU64( 8 ) ) ) );
20744
20745      /* We only have a 32-bit store function. So, need to fetch the
20746       * contents of memory merge with the store value and do two
20747       * 32-byte stores so we preserve the contents of memory not
20748       * addressed by nb.
20749       */
20750      assign( base_addr, ea_rAor0( rA_addr ) );
20751
20752      assign( current_mem,
20753              binop( Iop_64HLtoV128,
20754                     load( Ity_I64, mkexpr( base_addr ) ),
20755                     load( Ity_I64,
20756                           binop( mkSzOp( ty, Iop_Add8 ),
20757                                  mkexpr( base_addr ),
20758                                  ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 )
20759                                  ) ) ) );
20760
20761      /* Set the nb_mask to all zeros if nb = 0 so the current contents
20762       * of memory get written back without modifications.
20763       *
20764       * The store_val is a combination of the current memory value
20765       * and the bytes you want to store.  The nb_mask selects the
20766       * bytes you want stored from Vs.
20767       */
20768      if (host_endness == VexEndnessBE) {
20769         assign( nb_mask,
20770                 binop( Iop_OrV128,
20771                        binop( Iop_AndV128,
20772                               binop( Iop_ShlV128,
20773                                      mkV128( 0xFFFF ),
20774                                      mkexpr( shift ) ),
20775                               unop( Iop_NotV128, mkexpr( nb_zero ) ) ),
20776                        binop( Iop_AndV128,
20777                               mkexpr( nb_zero ),
20778                               mkV128( 0 ) ) ) );
20779
20780         assign( store_val,
20781                 binop( Iop_OrV128,
20782                        binop( Iop_AndV128,
20783                               binop( Iop_ShrV128,
20784                                      mkexpr( vS ),
20785                                      mkexpr( shift ) ),
20786                               mkexpr( nb_mask ) ),
20787                        binop( Iop_AndV128,
20788                               unop( Iop_NotV128, mkexpr( nb_mask ) ),
20789                               mkexpr( current_mem) ) ) );
20790
20791      } else {
20792            assign( nb_mask,
20793                 binop( Iop_OrV128,
20794                        binop( Iop_AndV128,
20795                               binop( Iop_ShrV128,
20796                                      binop( Iop_ShlV128,
20797                                             mkV128( 0xFFFF ),
20798                                             mkexpr( shift ) ),
20799                                      mkexpr( shift ) ),
20800                               unop( Iop_NotV128, mkexpr( nb_zero ) ) ),
20801                        binop( Iop_AndV128,
20802                               mkexpr( nb_zero ),
20803                               mkV128( 0 ) ) ) );
20804
20805         assign( store_val,
20806                 binop( Iop_OrV128,
20807                        binop( Iop_AndV128,
20808                               binop( Iop_ShrV128,
20809                                      binop( Iop_ShlV128,
20810                                             mkexpr( vS ),
20811                                             mkexpr( shift ) ),
20812                                      mkexpr( shift ) ),
20813                               mkexpr( nb_mask ) ),
20814                        binop( Iop_AndV128,
20815                               unop( Iop_NotV128, mkexpr( nb_mask ) ),
20816                               mkexpr( current_mem) ) ) );
20817      }
20818
20819      /* Store the value in 32-byte chunks */
20820      assign( word0,  binop( Iop_Shr64,
20821                             unop( Iop_V128HIto64, mkexpr( store_val ) ),
20822                             mkU8( 32 ) ) );
20823
20824      assign( word1, binop( Iop_And64,
20825                            unop( Iop_V128HIto64, mkexpr( store_val ) ),
20826                            mkU64( 0xFFFFFFFF ) ) );
20827
20828      assign( word2, binop( Iop_Shr64,
20829                            unop( Iop_V128to64, mkexpr( store_val ) ),
20830                            mkU8( 32 ) ) );
20831
20832      assign( word3, binop( Iop_And64,
20833                            unop( Iop_V128to64, mkexpr( store_val ) ),
20834                            mkU64( 0xFFFFFFFF ) ) );
20835
20836      ea_off = 0;
20837      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20838                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20839
20840      store( irx_addr, unop( Iop_64to32, mkexpr( word3 ) ) );
20841
20842      ea_off += 4;
20843      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20844                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20845
20846      store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) );
20847
20848      ea_off += 4;
20849      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20850                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20851
20852      store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) );
20853
20854      ea_off += 4;
20855      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20856                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20857
20858      store( irx_addr, unop( Iop_64to32, mkexpr( word0 ) ) );
20859      break;
20860   }
20861
20862   case 0x1AD: // stxvll (Store VSX Vector Left-justified with length XX1-form)
20863   {
20864      UInt ea_off = 0;
20865      IRExpr* irx_addr;
20866      IRTemp word0[5];
20867      IRTemp word1[5];
20868      IRTemp word2[5];
20869      IRTemp word3[5];
20870      IRTemp shift = newTemp(Ity_I8);
20871      IRTemp nb_gt16 = newTemp(Ity_I8);
20872      IRTemp nb_zero = newTemp(Ity_V128);
20873      IRTemp nb = newTemp(Ity_I8);
20874      IRTemp nb_field = newTemp(Ity_I64);
20875      IRTemp n_bytes = newTemp(Ity_I8);
20876      IRTemp base_addr = newTemp( ty );
20877      IRTemp current_mem = newTemp(Ity_V128);
20878      IRTemp store_val = newTemp(Ity_V128);
20879      IRTemp nb_mask = newTemp(Ity_V128);
20880      IRTemp mask = newTemp( Ity_I64 );
20881      IRTemp byte[16];
20882      IRTemp tmp_low[9];
20883      IRTemp tmp_hi[9];
20884      IRTemp nb_field_compare_zero = newTemp( Ity_I64 );
20885      Int i;
20886
20887      DIP("stxvll %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
20888
20889      assign( nb_field, binop( Iop_Shr64,
20890                               getIReg(rB_addr),
20891                               mkU8( 56 ) ) );
20892      assign( nb, unop( Iop_64to8, mkexpr( nb_field ) ) );
20893      assign( mask, mkU64( 0xFFFFFFFFFFFFFFFFULL ) );
20894
20895      /* nb_gt16 will be all zeros if nb > 16 */
20896      assign( nb_gt16, unop( Iop_1Sto8,
20897                             binop( Iop_CmpLT64U,
20898                                    binop( Iop_Shr64,
20899                                           mkexpr( nb_field ),
20900                                           mkU8( 4 ) ),
20901                                    mkU64( 1 ) ) ) );
20902
20903      assign( nb_field_compare_zero, unop( Iop_1Sto64,
20904                                           binop( Iop_CmpEQ64,
20905                                                  mkexpr( nb_field ),
20906                                                  mkU64( 0 ) ) ) );
20907
20908      /* nb_zero is 0xFF..FF if the nb_field = 0 */
20909      assign( nb_zero, binop( Iop_64HLtoV128,
20910                              mkexpr( nb_field_compare_zero ),
20911                              mkexpr( nb_field_compare_zero ) ) );
20912
20913
20914      /* set n_bytes to 0 if nb >= 16.  Otherwise, set to nb. */
20915      assign( n_bytes, binop( Iop_And8, mkexpr( nb ), mkexpr( nb_gt16 ) ) );
20916      assign( shift,
20917              unop( Iop_64to8,
20918                    binop( Iop_Mul64,
20919                           binop( Iop_Sub64,
20920                                  mkU64( 16 ),
20921                                  unop( Iop_8Uto64, mkexpr( n_bytes ) )),
20922                           mkU64( 8 ) ) ) );
20923
20924      /* We only have a 32-bit store function. So, need to fetch the
20925       * contents of memory merge with the store value and do two
20926       * 32-byte stores so we preserve the contents of memory not
20927       * addressed by nb.
20928       */
20929      assign( base_addr, ea_rAor0( rA_addr ) );
20930      /* fetch all 16 bytes and store in Big Endian format */
20931      word0[0] = newTemp(Ity_I64);
20932      assign( word0[0], mkU64( 0 ) );
20933
20934      word1[0] = newTemp(Ity_I64);
20935      assign( word1[0], mkU64( 0 ) );
20936
20937      word2[0] = newTemp(Ity_I64);
20938      assign( word2[0], mkU64( 0 ) );
20939
20940      word3[0] = newTemp(Ity_I64);
20941      assign( word3[0], mkU64( 0 ) );
20942
20943      for (i = 0; i < 4; i++) {
20944         word0[i+1] = newTemp(Ity_I64);
20945
20946         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20947                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20948         ea_off += 1;
20949
20950         /* Instruction always loads in Big Endian format */
20951         assign( word0[i+1],
20952                 binop( Iop_Or64,
20953                        binop( Iop_Shl64,
20954                               unop( Iop_8Uto64,
20955                                     load( Ity_I8,
20956                                           irx_addr ) ),
20957                               mkU8( (3-i)*8 ) ),
20958                        mkexpr( word0[i] ) ) );
20959      }
20960
20961      for (i = 0; i < 4; i++) {
20962         word1[i+1] = newTemp(Ity_I64);
20963
20964         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20965                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20966         ea_off += 1;
20967
20968         /* Instruction always loads in Big Endian format */
20969         assign( word1[i+1],
20970                 binop( Iop_Or64,
20971                        binop( Iop_Shl64,
20972                               unop( Iop_8Uto64,
20973                                     load( Ity_I8,
20974                                           irx_addr ) ),
20975                               mkU8( (3-i)*8 ) ),
20976                        mkexpr( word1[i] ) ) );
20977      }
20978      for (i = 0; i < 4; i++) {
20979         word2[i+1] = newTemp(Ity_I64);
20980
20981         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20982                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20983         ea_off += 1;
20984
20985         /* Instruction always loads in Big Endian format */
20986         assign( word2[i+1],
20987                 binop( Iop_Or64,
20988                        binop( Iop_Shl64,
20989                               unop( Iop_8Uto64,
20990                                     load( Ity_I8,
20991                                           irx_addr ) ),
20992                               mkU8( (3-i)*8 ) ),
20993                        mkexpr( word2[i] ) ) );
20994      }
20995      for (i = 0; i < 4; i++) {
20996         word3[i+1] = newTemp(Ity_I64);
20997
20998         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20999                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21000         ea_off += 1;
21001
21002         /* Instruction always loads in Big Endian format */
21003         assign( word3[i+1],
21004                 binop( Iop_Or64,
21005                        binop( Iop_Shl64,
21006                               unop( Iop_8Uto64,
21007                                     load( Ity_I8,
21008                                           irx_addr ) ),
21009                               mkU8( (3-i)*8 ) ),
21010                        mkexpr( word3[i] ) ) );
21011      }
21012
21013
21014      assign( current_mem,
21015              binop( Iop_64HLtoV128,
21016                     binop( Iop_Or64,
21017                            binop( Iop_Shl64,
21018                                   mkexpr( word0[4] ),
21019                                   mkU8( 32 ) ),
21020                            mkexpr( word1[4] ) ),
21021                     binop( Iop_Or64,
21022                            binop( Iop_Shl64,
21023                                   mkexpr( word2[4] ),
21024                                   mkU8( 32 ) ),
21025                            mkexpr( word3[4] ) ) ) );
21026
21027      /* Set the nb_mask to all zeros if nb = 0 so the current contents
21028       * of memory get written back without modifications.
21029       *
21030       * The store_val is a combination of the current memory value
21031       * and the bytes you want to store.  The nb_mask selects the
21032       * bytes you want stored from Vs.
21033       */
21034      /* The instruction always uses Big Endian order */
21035      assign( nb_mask,
21036              binop( Iop_OrV128,
21037                     binop( Iop_AndV128,
21038                            binop( Iop_ShlV128,
21039                                   binop( Iop_ShrV128,
21040                                          binop( Iop_64HLtoV128,
21041                                                 mkexpr( mask ),
21042                                                 mkexpr( mask ) ),
21043                                          mkexpr( shift ) ),
21044                                   mkexpr( shift ) ),
21045                            unop( Iop_NotV128, mkexpr( nb_zero ) ) ),
21046                     binop( Iop_AndV128,
21047                            mkexpr( nb_zero ),
21048                            binop( Iop_64HLtoV128,
21049                                   mkU64( 0x0 ),
21050                                   mkU64( 0x0 ) ) ) ) );
21051
21052      assign( store_val,
21053              binop( Iop_OrV128,
21054                     binop( Iop_AndV128,
21055                            mkexpr( vS ),
21056                            mkexpr( nb_mask ) ),
21057                     binop( Iop_AndV128,
21058                            unop( Iop_NotV128, mkexpr( nb_mask ) ),
21059                            mkexpr( current_mem) ) ) );
21060
21061      /* store the merged value in Big Endian format */
21062      tmp_low[0] = newTemp(Ity_I64);
21063      tmp_hi[0] = newTemp(Ity_I64);
21064      assign( tmp_low[0], mkU64( 0 ) );
21065      assign( tmp_hi[0], mkU64( 0 ) );
21066
21067      for (i = 0; i < 8; i++) {
21068         byte[i] = newTemp(Ity_I64);
21069         byte[i+8] = newTemp(Ity_I64);
21070         tmp_low[i+1] = newTemp(Ity_I64);
21071         tmp_hi[i+1]  = newTemp(Ity_I64);
21072
21073         assign( byte[i], binop( Iop_And64,
21074                                 binop( Iop_Shr64,
21075                                        unop( Iop_V128HIto64,
21076                                              mkexpr( store_val ) ),
21077                                        mkU8( (7-i)*8 ) ),
21078                                 mkU64( 0xFF ) ) );
21079         assign( byte[i+8], binop( Iop_And64,
21080                                   binop( Iop_Shr64,
21081                                          unop( Iop_V128to64,
21082                                                mkexpr( store_val ) ),
21083                                          mkU8( (7-i)*8 ) ),
21084                                   mkU64( 0xFF ) ) );
21085
21086         assign( tmp_low[i+1],
21087                 binop( Iop_Or64,
21088                        mkexpr( tmp_low[i] ),
21089                        binop( Iop_Shl64, mkexpr( byte[i] ), mkU8( i*8 ) ) ) );
21090         assign( tmp_hi[i+1],
21091                 binop( Iop_Or64,
21092                        mkexpr( tmp_hi[i] ),
21093                        binop( Iop_Shl64, mkexpr( byte[i+8] ),
21094                               mkU8( i*8 ) ) ) );
21095      }
21096
21097      /* Store the value in 32-byte chunks */
21098      ea_off = 0;
21099      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21100                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21101
21102      store( irx_addr, unop( Iop_64to32, mkexpr( tmp_low[8] ) ) );
21103
21104      ea_off += 4;
21105      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21106                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21107
21108      store( irx_addr, unop( Iop_64HIto32, mkexpr( tmp_low[8] ) ) );
21109
21110      ea_off += 4;
21111      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21112                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21113
21114      store( irx_addr, unop( Iop_64to32, mkexpr( tmp_hi[8] ) ) );
21115
21116      ea_off += 4;
21117      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21118                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21119
21120      store( irx_addr, unop( Iop_64HIto32, mkexpr( tmp_hi[8] ) ) );
21121
21122      break;
21123      }
21124
21125   case 0x28C:
21126   {
21127      IRTemp high64 = newTemp(Ity_F64);
21128      IRTemp val32  = newTemp(Ity_I32);
21129      DIP("stxsspx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21130      assign(high64, unop( Iop_ReinterpI64asF64,
21131                           unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
21132      assign(val32, unop( Iop_ReinterpF32asI32,
21133                          unop( Iop_TruncF64asF32,
21134                                mkexpr(high64) ) ) );
21135      store( mkexpr( EA ), mkexpr( val32 ) );
21136      break;
21137   }
21138   case 0x2CC:
21139   {
21140      IRExpr * high64;
21141      DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21142      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
21143      store( mkexpr( EA ), high64 );
21144      break;
21145   }
21146
21147   case 0x38D: // stxsibx
21148   {
21149      IRExpr *stored_word;
21150      IRTemp byte_to_store = newTemp( Ity_I64 );
21151
21152      DIP("stxsibx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21153
21154      /* Can't store just a byte, need to fetch the word at EA merge data
21155       * and store.
21156       */
21157      stored_word = load( Ity_I64, mkexpr( EA ) );
21158      assign( byte_to_store, binop( Iop_And64,
21159                                    unop( Iop_V128HIto64,
21160                                          mkexpr( vS ) ),
21161                                    mkU64( 0xFF ) ) );
21162
21163      store( mkexpr( EA ), binop( Iop_Or64,
21164                                  binop( Iop_And64,
21165                                         stored_word,
21166                                         mkU64( 0xFFFFFFFFFFFFFF00 ) ),
21167                                  mkexpr( byte_to_store ) ) );
21168      break;
21169   }
21170
21171   case 0x3AD: // stxsihx
21172   {
21173      IRExpr *stored_word;
21174      IRTemp byte_to_store = newTemp( Ity_I64 );
21175
21176      DIP("stxsihx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21177
21178      /* Can't store just a halfword, need to fetch the word at EA merge data
21179       * and store.
21180       */
21181      stored_word = load( Ity_I64, mkexpr( EA ) );
21182      assign( byte_to_store, binop( Iop_And64,
21183                                    unop( Iop_V128HIto64,
21184                                          mkexpr( vS ) ),
21185                                    mkU64( 0xFFFF ) ) );
21186
21187      store( mkexpr( EA ), binop( Iop_Or64,
21188                                  binop( Iop_And64,
21189                                         stored_word,
21190                                         mkU64( 0xFFFFFFFFFFFF0000 ) ),
21191                                  mkexpr( byte_to_store ) ) );
21192      break;
21193   }
21194
21195   case 0x3CC:
21196   {
21197      IRExpr * high64, *low64;
21198      DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21199      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
21200      low64 = unop( Iop_V128to64, mkexpr( vS ) );
21201      store( mkexpr( EA ), high64 );
21202      store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21203                    ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 );
21204      break;
21205   }
21206   case 0x38C:
21207   {
21208      UInt ea_off = 0;
21209      IRExpr* irx_addr;
21210      IRTemp hi64 = newTemp( Ity_I64 );
21211      IRTemp lo64 = newTemp( Ity_I64 );
21212
21213      DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21214
21215      // This instruction supports word-aligned stores, so EA may not be
21216      // quad-word aligned.  Therefore, do 4 individual word-size stores.
21217      assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
21218      assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
21219      store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
21220      ea_off += 4;
21221      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21222                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21223      store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
21224      ea_off += 4;
21225      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21226                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21227      store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
21228      ea_off += 4;
21229      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21230                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21231      store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
21232
21233      break;
21234   }
21235   case 0x3AC: // stxvh8x Store VSX Vector Halfword*8 Indexed
21236   {
21237      UInt ea_off = 0;
21238      IRExpr* irx_addr;
21239      IRTemp half_word0 = newTemp( Ity_I64 );
21240      IRTemp half_word1 = newTemp( Ity_I64 );
21241      IRTemp half_word2 = newTemp( Ity_I64 );
21242      IRTemp half_word3 = newTemp( Ity_I64 );
21243      IRTemp half_word4 = newTemp( Ity_I64 );
21244      IRTemp half_word5 = newTemp( Ity_I64 );
21245      IRTemp half_word6 = newTemp( Ity_I64 );
21246      IRTemp half_word7 = newTemp( Ity_I64 );
21247
21248      DIP("stxvb8x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21249
21250      assign( half_word0, binop( Iop_Shr64,
21251                                 unop( Iop_V128HIto64, mkexpr( vS ) ),
21252                                 mkU8( 48 ) ) );
21253
21254      assign( half_word1, binop( Iop_And64,
21255                                 binop( Iop_Shr64,
21256                                        unop( Iop_V128HIto64, mkexpr( vS ) ),
21257                                        mkU8( 32 ) ),
21258                                 mkU64( 0xFFFF ) ) );
21259
21260      assign( half_word2, binop( Iop_And64,
21261                                 binop( Iop_Shr64,
21262                                        unop( Iop_V128HIto64, mkexpr( vS ) ),
21263                                        mkU8( 16 ) ),
21264                                 mkU64( 0xFFFF ) ) );
21265
21266      assign( half_word3, binop( Iop_And64,
21267                                 unop( Iop_V128HIto64, mkexpr( vS ) ),
21268                                 mkU64( 0xFFFF ) ) );
21269
21270      assign( half_word4, binop( Iop_Shr64,
21271                                 unop( Iop_V128to64, mkexpr( vS ) ),
21272                                 mkU8( 48 ) ) );
21273
21274      assign( half_word5, binop( Iop_And64,
21275                                 binop( Iop_Shr64,
21276                                        unop( Iop_V128to64, mkexpr( vS ) ),
21277                                        mkU8( 32 ) ),
21278                                 mkU64( 0xFFFF ) ) );
21279
21280      assign( half_word6, binop( Iop_And64,
21281                                 binop( Iop_Shr64,
21282                                        unop( Iop_V128to64, mkexpr( vS ) ),
21283                                        mkU8( 16 ) ),
21284                                 mkU64( 0xFFFF ) ) );
21285
21286      assign( half_word7, binop( Iop_And64,
21287                                 unop( Iop_V128to64, mkexpr( vS ) ),
21288                                 mkU64( 0xFFFF ) ) );
21289
21290      /* Do the 32-bit stores.  The store() does an Endian aware store. */
21291      if ( host_endness == VexEndnessBE ) {
21292         store( mkexpr( EA ), unop( Iop_64to32,
21293                                    binop( Iop_Or64,
21294                                           mkexpr( half_word1 ),
21295                                           binop( Iop_Shl64,
21296                                                  mkexpr( half_word0 ),
21297                                                  mkU8( 16 ) ) ) ) );
21298
21299         ea_off += 4;
21300         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21301                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21302
21303
21304         store( irx_addr, unop( Iop_64to32,
21305                                binop( Iop_Or64,
21306                                       mkexpr( half_word3 ),
21307                                       binop( Iop_Shl64,
21308                                              mkexpr( half_word2 ),
21309                                              mkU8( 16 ) ) ) ) );
21310
21311         ea_off += 4;
21312         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21313                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21314
21315         store( irx_addr, unop( Iop_64to32,
21316                                binop( Iop_Or64,
21317                                       mkexpr( half_word5 ),
21318                                       binop( Iop_Shl64,
21319                                              mkexpr( half_word4 ),
21320                                              mkU8( 16 ) ) ) ) );
21321         ea_off += 4;
21322         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21323                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21324
21325         store( irx_addr, unop( Iop_64to32,
21326                                binop( Iop_Or64,
21327                                       mkexpr( half_word7 ),
21328                                       binop( Iop_Shl64,
21329                                              mkexpr( half_word6 ),
21330                                              mkU8( 16 ) ) ) ) );
21331
21332      } else {
21333         store( mkexpr( EA ), unop( Iop_64to32,
21334                                    binop( Iop_Or64,
21335                                           mkexpr( half_word0 ),
21336                                           binop( Iop_Shl64,
21337                                                  mkexpr( half_word1 ),
21338                                                  mkU8( 16 ) ) ) ) );
21339
21340         ea_off += 4;
21341         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21342                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21343
21344         store( irx_addr, unop( Iop_64to32,
21345                                binop( Iop_Or64,
21346                                       mkexpr( half_word2 ),
21347                                       binop( Iop_Shl64,
21348                                              mkexpr( half_word3 ),
21349                                              mkU8( 16 ) ) ) ) );
21350         ea_off += 4;
21351         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21352                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21353
21354         store( irx_addr, unop( Iop_64to32,
21355                                binop( Iop_Or64,
21356                                       mkexpr( half_word4 ),
21357                                       binop( Iop_Shl64,
21358                                              mkexpr( half_word5 ),
21359                                              mkU8( 16 ) ) ) ) );
21360         ea_off += 4;
21361         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21362                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21363
21364         store( irx_addr, unop( Iop_64to32,
21365                                binop( Iop_Or64,
21366                                       mkexpr( half_word6 ),
21367                                       binop( Iop_Shl64,
21368                                              mkexpr( half_word7 ),
21369                                              mkU8( 16 ) ) ) ) );
21370      }
21371      break;
21372   }
21373
21374   case 0x3EC: // stxvb16x Store VSX Vector Byte*16 Indexed
21375   {
21376      UInt ea_off = 0;
21377      int i;
21378      IRExpr* irx_addr;
21379      IRTemp byte[16];
21380
21381      DIP("stxvb16x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21382
21383      for ( i = 0; i < 8; i++ ) {
21384         byte[i] = newTemp( Ity_I64 );
21385         byte[i+8] = newTemp( Ity_I64 );
21386
21387         assign( byte[i], binop( Iop_And64,
21388                               binop( Iop_Shr64,
21389                                      unop( Iop_V128HIto64, mkexpr( vS ) ),
21390                                      mkU8( 56 - i*8 ) ),
21391                               mkU64( 0xFF ) ) );
21392
21393         assign( byte[i+8], binop( Iop_And64,
21394                               binop( Iop_Shr64,
21395                                      unop( Iop_V128to64, mkexpr( vS ) ),
21396                                      mkU8( 56 - i*8) ),
21397                               mkU64( 0xFF ) ) );
21398      }
21399
21400      if ( host_endness == VexEndnessBE ) {
21401         for ( i = 0; i < 16; i = i + 4)  {
21402            irx_addr =
21403               binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21404                      ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21405
21406            store( irx_addr,
21407                   unop( Iop_64to32,
21408                         binop( Iop_Or64,
21409                                binop( Iop_Or64,
21410                                       mkexpr( byte[i+3] ),
21411                                       binop( Iop_Shl64,
21412                                              mkexpr( byte[i+2] ),
21413                                              mkU8( 8 ) ) ),
21414                                binop( Iop_Or64,
21415                                       binop( Iop_Shl64,
21416                                              mkexpr( byte[i+1] ),
21417                                              mkU8( 16 ) ),
21418                                       binop( Iop_Shl64,
21419                                              mkexpr( byte[i] ),
21420                                              mkU8( 24 ) ) ) ) ) );
21421            ea_off += 4;
21422         }
21423
21424      } else {
21425         for ( i = 0; i < 16; i = i + 4)  {
21426            irx_addr =
21427               binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21428                      ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21429
21430            store( irx_addr,
21431                   unop( Iop_64to32,
21432                         binop( Iop_Or64,
21433                                binop( Iop_Or64,
21434                                       mkexpr( byte[i] ),
21435                                       binop( Iop_Shl64,
21436                                              mkexpr( byte[i+1] ),
21437                                              mkU8( 8 ) ) ),
21438                                binop( Iop_Or64,
21439                                       binop( Iop_Shl64,
21440                                              mkexpr( byte[i+2] ),
21441                                              mkU8( 16 ) ),
21442                                       binop( Iop_Shl64,
21443                                              mkexpr( byte[i+3] ),
21444                                              mkU8( 24 ) ) ) ) ) );
21445
21446            ea_off += 4;
21447         }
21448      }
21449      break;
21450   }
21451
21452   default:
21453      vex_printf( "dis_vx_store(ppc)(opc2)\n" );
21454      return False;
21455   }
21456   return True;
21457}
21458
21459static Bool
21460dis_vx_Scalar_Round_to_quad_integer( UInt theInstr )
21461{
21462   /* The ISA 3.0 instructions supported in this function require
21463    * the underlying hardware platform that supports the ISA3.0
21464    * instruction set.
21465    */
21466   /* XX1-Form */
21467   UChar opc1 = ifieldOPC( theInstr );
21468   UInt opc2 = IFIELD( theInstr, 1, 8 );
21469   UChar vT_addr = ifieldRegDS( theInstr );
21470   UChar vB_addr = ifieldRegB( theInstr );
21471   IRTemp vB = newTemp( Ity_F128 );
21472   IRTemp vT = newTemp( Ity_F128 );
21473   UChar EX = IFIELD( theInstr, 0, 1 );
21474
21475   assign( vB, getF128Reg( vB_addr ) );
21476   if (opc1 != 0x3F) {
21477      vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(instr)\n" );
21478      return False;
21479   }
21480   switch (opc2) {
21481   case 0x005:     // VSX Scalar Round to Quad-Precision Integer [with Inexact]
21482      {
21483         UChar R   = IFIELD( theInstr, 16, 1 );
21484         UChar RMC = IFIELD( theInstr, 9, 2 );
21485
21486         /* Store the rm specification bits.  Will extract them later when
21487          * the isntruction is issued.
21488          */
21489         IRExpr* rm = mkU32( R << 3 | RMC << 1 | EX);
21490
21491         if ( EX == 0 ) {  // xsrqpi
21492            DIP("xsrqpi %d,v%d,v%d,%d\n",  R, vT_addr, vB_addr, RMC);
21493            assign( vT, binop( Iop_F128toI128S, rm, mkexpr( vB ) ) );
21494
21495         } else {     // xsrqpix
21496            DIP("xsrqpix %d,v%d,v%d,%d\n", R, vT_addr, vB_addr, RMC);
21497            assign( vT, binop( Iop_F128toI128S, rm, mkexpr( vB ) ) );
21498         }
21499         generate_store_FPRF( Ity_F128, vT );
21500      }   /* case 0x005 */
21501      break;
21502   case 0x025:     // xsrqpxp  VSX Scalar Round Quad-Precision to
21503                   // Double-Extended Precision
21504      {
21505         UChar R   = IFIELD( theInstr, 16, 1 );
21506         UChar RMC = IFIELD( theInstr, 9, 2 );
21507
21508         /* Store the rm specification bits.  Will extract them later when
21509          * the isntruction is issued.
21510          */
21511         IRExpr* rm = mkU32( R << 3 | RMC << 1 );
21512
21513        DIP("xsrqpxp %d,v%d,v%d,%d\n",  R, vT_addr, vB_addr, RMC);
21514         assign( vT, binop( Iop_RndF128, rm, mkexpr( vB ) ) );
21515         generate_store_FPRF( Ity_F128, vT );
21516      }   /* case 0x025 */
21517     break;
21518   default:
21519      vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(opc2)\n" );
21520      return False;
21521   }     /* switch opc2 */
21522   putF128Reg( vT_addr, mkexpr( vT ) );
21523   return True;
21524}
21525
21526static Bool
21527dis_vx_Floating_Point_Arithmetic_quad_precision( UInt theInstr )
21528{
21529   /* The ISA 3.0 instructions supported in this function require
21530    * the underlying hardware platform that supports the ISA 3.0
21531    * instruction set.
21532    */
21533   /* XX1-Form */
21534   UChar opc1 = ifieldOPC( theInstr );
21535   UInt opc2 = ifieldOPClo10( theInstr );
21536   UChar vT_addr = ifieldRegDS( theInstr );
21537   UChar vA_addr = ifieldRegA( theInstr );
21538   UChar vB_addr = ifieldRegB( theInstr );
21539   IRTemp vA = newTemp( Ity_F128 );
21540   IRTemp vB = newTemp( Ity_F128 );
21541   IRTemp vT = newTemp( Ity_F128 );
21542   IRExpr* rm = get_IR_roundingmode();
21543   UChar R0 = IFIELD( theInstr, 0, 1 );
21544
21545   assign( vB, getF128Reg( vB_addr ) );
21546
21547   if ( opc1 != 0x3F ) {
21548      vex_printf( "Erorr, dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(instr)\n" );
21549      return False;
21550   }
21551   switch ( opc2 ) {
21552   case 0x004:     // xsaddqp (VSX Scalar Add Quad-Precision[using round to Odd])
21553      {
21554         assign( vA, getF128Reg( vA_addr ) );
21555
21556         if ( R0 == 0 ) {
21557            /* rounding mode specified by RN. Issue inst with R0 = 0 */
21558            DIP("xsaddqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21559            assign( vT, triop( Iop_AddF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
21560
21561         } else {
21562           /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21563            DIP("xsaddqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21564            assign( vT, triop( Iop_AddF128, set_round_to_Oddmode(),
21565                               mkexpr( vA ), mkexpr( vB ) ) );
21566         }
21567         generate_store_FPRF( Ity_F128, vT );
21568         break;
21569      }
21570   case 0x024:     // xsmulqp (VSX Scalar Multiply Quad-Precision[using round to Odd])
21571      {
21572         assign( vA, getF128Reg( vA_addr ) );
21573
21574         if ( R0 == 0 ) {
21575            /* rounding mode specified by RN. Issue inst with R0 = 0 */
21576            DIP("xsmulqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21577            assign( vT, triop( Iop_MulF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
21578
21579         } else {
21580            /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21581            DIP("xsmulqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21582            assign( vT, triop( Iop_MulF128, set_round_to_Oddmode(), mkexpr( vA ),
21583                               mkexpr( vB ) ) );
21584         }
21585         generate_store_FPRF( Ity_F128, vT );
21586         break;
21587      }
21588   case 0x184:   // xsmaddqp (VSX Scalar Multiply add Quad-Precision[using round to Odd])
21589      {
21590         /* instruction computes (vA * vB) + vC */
21591         IRTemp vC = newTemp( Ity_F128 );
21592
21593         assign( vA, getF128Reg( vA_addr ) );
21594         assign( vC, getF128Reg( vT_addr ) );
21595
21596         if ( R0 == 0 ) {
21597            /* rounding mode specified by RN. Issue inst with R0 = 0 */
21598            DIP("xsmaddqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21599            assign( vT,
21600               qop( Iop_MAddF128, rm, mkexpr( vA ),
21601                    mkexpr( vC ), mkexpr( vB ) ) );
21602
21603         } else {
21604            /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21605            DIP("xsmaddqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21606            assign( vT,
21607               qop( Iop_MAddF128, set_round_to_Oddmode(), mkexpr( vA ),
21608                    mkexpr( vC ), mkexpr( vB ) ) );
21609         }
21610         generate_store_FPRF( Ity_F128, vT );
21611         break;
21612      }
21613   case 0x1A4:   // xsmsubqp (VSX Scalar Multiply Subtract Quad-Precision[using round to Odd])
21614      {
21615         IRTemp vC = newTemp( Ity_F128 );
21616
21617         assign( vA, getF128Reg( vA_addr ) );
21618         assign( vC, getF128Reg( vT_addr ) );
21619
21620         if ( R0 == 0 ) {
21621            /* rounding mode specified by RN. Issue inst with R0 = 0 */
21622            DIP("xsmsubqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21623            assign( vT,
21624               qop( Iop_MSubF128, rm, mkexpr( vA ),
21625                    mkexpr( vC ), mkexpr( vB ) ) );
21626
21627         } else {
21628            /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21629            DIP("xsmsubqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21630            assign( vT,
21631                    qop( Iop_MSubF128, set_round_to_Oddmode(),
21632                         mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
21633         }
21634         generate_store_FPRF( Ity_F128, vT );
21635         break;
21636      }
21637   case 0x1C4:   // xsnmaddqp (VSX Scalar Negative Multiply Add Quad-Precision[using round to Odd])
21638      {
21639         IRTemp vC = newTemp( Ity_F128 );
21640
21641         assign( vA, getF128Reg( vA_addr ) );
21642         assign( vC, getF128Reg( vT_addr ) );
21643
21644         if ( R0 == 0 ) {
21645            /* rounding mode specified by RN. Issue inst with R0 = 0 */
21646            DIP("xsnmaddqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21647            assign( vT,
21648               qop( Iop_NegMAddF128, rm, mkexpr( vA ),
21649                    mkexpr( vC ), mkexpr( vB ) ) );
21650
21651         } else {
21652            /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21653            DIP("xsnmaddqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21654            assign( vT,
21655                    qop( Iop_NegMAddF128, set_round_to_Oddmode(),
21656                         mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
21657         }
21658         generate_store_FPRF( Ity_F128, vT );
21659        break;
21660      }
21661   case 0x1E4:   // xsmsubqp (VSX Scalar Negatve Multiply Subtract Quad-Precision[using round to Odd])
21662      {
21663         IRTemp vC = newTemp( Ity_F128 );
21664
21665         assign( vA, getF128Reg( vA_addr ) );
21666         assign( vC, getF128Reg( vT_addr ) );
21667
21668         if ( R0 == 0 ) {
21669            /* rounding mode specified by RN. Issue inst with R0 = 0 */
21670            DIP("xsnmsubqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21671            assign( vT,
21672               qop( Iop_NegMSubF128, rm, mkexpr( vA ),
21673                    mkexpr( vC ), mkexpr( vB ) ) );
21674
21675         } else {
21676            /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21677            DIP("xsnmsubqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21678            assign( vT,
21679                    qop( Iop_NegMSubF128, set_round_to_Oddmode(),
21680                         mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
21681         }
21682         generate_store_FPRF( Ity_F128, vT );
21683         break;
21684      }
21685   case 0x204:     // xssubqp (VSX Scalar Subtract Quad-Precision[using round to Odd])
21686      {
21687         assign( vA, getF128Reg( vA_addr ) );
21688         if ( R0 == 0 ) {
21689            /* use rounding mode specified by RN. Issue inst with R0 = 0 */
21690            DIP("xssubqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21691            assign( vT, triop( Iop_SubF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
21692
21693         } else {
21694            /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21695            DIP("xssubqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21696            assign( vT, triop( Iop_SubF128, set_round_to_Oddmode(), mkexpr( vA ),
21697                               mkexpr( vB ) ) );
21698         }
21699         generate_store_FPRF( Ity_F128, vT );
21700        break;
21701      }
21702   case 0x224:     // xsdivqp (VSX Scalar Divide Quad-Precision[using round to Odd])
21703      {
21704         assign( vA, getF128Reg( vA_addr ) );
21705         if ( R0 == 0 ) {
21706            /* use rounding mode specified by RN. Issue inst with R0 = 0 */
21707            DIP("xsdivqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21708            assign( vT, triop( Iop_DivF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
21709
21710         } else {
21711            /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21712            DIP("xsdivqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21713            assign( vT, triop( Iop_DivF128, set_round_to_Oddmode(), mkexpr( vA ),
21714                               mkexpr( vB ) ) );
21715         }
21716         generate_store_FPRF( Ity_F128, vT );
21717         break;
21718      }
21719   case 0x324:  // xssqrtqp (VSX Scalar Square root Quad-Precision[using round to Odd])
21720      {
21721         UInt inst_select = IFIELD( theInstr, 16, 5 );
21722
21723         switch (inst_select) {
21724         case 27:
21725            {
21726               if ( R0 == 0 ) { // xssqrtqp
21727                  /* rounding mode specified by RN. Issue inst with R0 = 0 */
21728                  DIP("xssqrtqp v%d,v%d\n",  vT_addr, vB_addr);
21729                  assign( vT, binop( Iop_SqrtF128, rm, mkexpr( vB ) ) );
21730
21731               } else {      // xssqrtqpo
21732                  /* rounding mode is Round to odd. Issue inst with R0 = 1 */
21733                  DIP("xssqrtqpo v%d,v%d\n",  vT_addr, vB_addr);
21734                  assign( vT, binop( Iop_SqrtF128, set_round_to_Oddmode(),
21735                                     mkexpr( vB ) ) );
21736               }
21737               generate_store_FPRF( Ity_F128, vT );
21738               break;
21739            }   /* end case 27 */
21740         default:
21741            vex_printf("dis_vx_Floating_Point_Arithmetic_quad_precision(0x324 unknown inst_select)\n");
21742            return False;
21743         }  /* end switch inst_select */
21744         break;
21745      }   /* end case 0x324 */
21746
21747   case 0x344:
21748      {
21749         UInt inst_select = IFIELD( theInstr, 16, 5);
21750
21751         switch (inst_select) {
21752         case 1:    // xscvqpuwz  VSX Scalar Truncate & Convert Quad-Precision
21753                    // format to Unsigned Word format
21754            {
21755               DIP("xscvqpuwz v%d,v%d\n",  vT_addr, vB_addr);
21756               assign( vT, unop( Iop_TruncF128toI32U, mkexpr( vB ) ) );
21757               break;
21758            }
21759         case 2:    // xscvudqp  VSX Scalar Convert from Unsigned Doubleword
21760                    // format to Quad-Precision format
21761            {
21762               IRTemp tmp = newTemp( Ity_I64 );
21763
21764               DIP("xscvudqp v%d,v%d\n",  vT_addr, vB_addr);
21765               assign( tmp, unop( Iop_ReinterpF64asI64,
21766                                  unop( Iop_F128HItoF64, mkexpr( vB ) ) ) );
21767               assign( vT, unop( Iop_I64UtoF128, mkexpr( tmp ) ) );
21768               generate_store_FPRF( Ity_F128, vT );
21769               break;
21770            }
21771         case 9:    // xsvqpswz  VSX Scalar Truncate & Convert Quad-Precision
21772                    // format to Signed Word format
21773            {
21774               DIP("xscvqpswz v%d,v%d\n",  vT_addr, vB_addr);
21775               assign( vT, unop( Iop_TruncF128toI32S, mkexpr( vB ) ) );
21776               break;
21777            }
21778         case 10:   // xscvsdqp  VSX Scalar from Signed Doubleword format
21779                    // Quad-Precision format
21780            {
21781               IRTemp tmp = newTemp( Ity_I64 );
21782
21783               DIP("xscvsdqp v%d,v%d\n",  vT_addr, vB_addr);
21784
21785               assign( tmp, unop( Iop_ReinterpF64asI64,
21786                                  unop( Iop_F128HItoF64, mkexpr( vB ) ) ) );
21787               assign( vT, unop( Iop_I64StoF128, mkexpr( tmp ) ) );
21788               generate_store_FPRF( Ity_F128, vT );
21789               break;
21790            }
21791        case 17:    // xsvqpudz  VSX Scalar Truncate & Convert Quad-Precision
21792                    // format to Unigned Doubleword format
21793            {
21794              DIP("xscvqpudz v%d,v%d\n",  vT_addr, vB_addr);
21795               assign( vT, unop( Iop_TruncF128toI64U, mkexpr( vB ) ) );
21796               break;
21797            }
21798         case 20: //  xscvqpdp  Scalar round & Conver Quad-Precision
21799                  //  format to Double-Precision format [using round to Odd]
21800            {
21801               IRTemp ftmp = newTemp( Ity_F64 );
21802               IRTemp tmp = newTemp( Ity_I64 );
21803
21804               /* This instruction takes a 128-bit floating point value and
21805                * converts it to a 64-bit floating point value.  The 64-bit
21806                * result is stored in the upper 64-bit of the 128-bit result
21807                * register.  The lower 64-bit are undefined.
21808                */
21809               if (R0 == 0) { //  xscvqpdp
21810                  /* rounding mode specified by RN. Issue inst with R0 = 0 */
21811                  DIP("xscvqpdp v%d,v%d\n",  vT_addr, vB_addr);
21812
21813                  assign( ftmp, binop( Iop_F128toF64, rm, mkexpr( vB ) ) );
21814
21815               } else {       //  xscvqpdpo
21816                  /* rounding mode is Round to odd. Issue inst with R0 = 1 */
21817                  DIP("xscvqpdpo v%d,v%d\n",  vT_addr, vB_addr);
21818                  assign( ftmp,
21819                          binop( Iop_F128toF64,
21820                                 set_round_to_Oddmode(), mkexpr( vB ) ) );
21821               }
21822
21823               /* store 64-bit float in upper 64-bits of 128-bit register,
21824                * lower 64-bits are zero.
21825                */
21826               if (host_endness == VexEndnessLE)
21827                  assign( vT,
21828                          binop( Iop_F64HLtoF128,
21829                                 mkexpr( ftmp ),
21830                                 unop( Iop_ReinterpI64asF64, mkU64( 0 ) ) ) );
21831               else
21832                  assign( vT,
21833                          binop( Iop_F64HLtoF128,
21834                                 unop( Iop_ReinterpI64asF64, mkU64( 0 ) ),
21835                                 mkexpr( ftmp ) ) );
21836
21837               assign( tmp, unop( Iop_ReinterpF64asI64,
21838                                  unop( Iop_F128HItoF64, mkexpr( vT ) ) ) );
21839
21840               generate_store_FPRF( Ity_I64, tmp );
21841               break;
21842            }
21843         case 22:    // xscvdpqp VSX Scalar Convert from Double-Precision
21844                     // format to Quad-Precision format
21845            {
21846               DIP("xscvdpqp v%d,v%d\n",  vT_addr, vB_addr);
21847               /* The 64-bit value is in the upper 64 bit of the src */
21848               assign( vT, unop( Iop_F64toF128,
21849                                 unop( Iop_F128HItoF64, mkexpr( vB ) ) ) );
21850
21851               generate_store_FPRF( Ity_F128, vT );
21852               break;
21853            }
21854         case 25:    // xsvqpsdz  VSX Scalar Truncate & Convert Quad-Precision
21855                     // format to Signed Doubleword format
21856            {
21857               DIP("xscvqpsdz v%d,v%d\n",  vT_addr, vB_addr);
21858               assign( vT, unop( Iop_TruncF128toI64S, mkexpr( vB ) ) );
21859               break;
21860            }
21861         default:
21862           vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision invalid inst_select (ppc)(opc2)\n" );
21863           return False;
21864         }  /* switch inst_select */
21865      }   /* end case 0x344 */
21866      break;
21867   default:    /* switch opc2 */
21868      vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(opc2)\n" );
21869      return False;
21870   }
21871   putF128Reg( vT_addr, mkexpr( vT ) );
21872   return True;
21873}
21874
21875
21876/* VSX Scalar Quad-Precision instructions */
21877static Bool
21878dis_vx_scalar_quad_precision ( UInt theInstr )
21879{
21880   /* This function emulates the 128-bit floating point instructions
21881    * using existing 128-bit vector instructions (Iops).  The 128-bit
21882    * floating point instructions use the same 128-bit vector register
21883    * set.
21884    */
21885   /* XX1-Form */
21886   UChar opc1 = ifieldOPC( theInstr );
21887   UInt opc2 = ifieldOPClo10( theInstr );
21888   UChar vT_addr = ifieldRegDS( theInstr ) + 32;
21889   UChar vA_addr = ifieldRegA( theInstr ) + 32;
21890   UChar vB_addr = ifieldRegB( theInstr ) + 32;
21891   IRTemp vA = newTemp( Ity_V128 );
21892   IRTemp vB = newTemp( Ity_V128 );
21893   IRTemp vT = newTemp( Ity_V128 );
21894
21895   assign( vB, getVSReg( vB_addr ) );
21896
21897   if (opc1 != 0x3F) {
21898      vex_printf( "dis_vx_scalar_quad_precision(ppc)(instr)\n" );
21899      return False;
21900   }
21901
21902   switch (opc2) {
21903
21904   case 0x064:     // xscpsgnqp (VSX Scalar Copy Sign Quad-Precision)
21905      {
21906         IRTemp sign_vA = newTemp( Ity_I64 );
21907         IRTemp vB_hi = newTemp( Ity_I64 );
21908
21909         DIP("xscpsgnqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21910
21911         assign( vA, getVSReg(vA_addr) );
21912
21913         assign( sign_vA, binop( Iop_And64,
21914                                 unop( Iop_V128HIto64,
21915                                       mkexpr( vA ) ),
21916                                 mkU64( 0x8000000000000000ULL ) ) );
21917         assign( vB_hi, binop( Iop_Or64,
21918                               binop( Iop_And64,
21919                                      unop( Iop_V128HIto64,
21920                                            mkexpr( vB ) ),
21921                                      mkU64( 0x7FFFFFFFFFFFFFFFULL ) ),
21922                               mkexpr( sign_vA ) ) );
21923         assign( vT, binop( Iop_64HLtoV128,
21924                            mkexpr( vB_hi ),
21925                            unop( Iop_V128to64, mkexpr( vB ) ) ) );
21926         break;
21927      }
21928
21929   case 0x084:     // xscmpoqp (VSX Scalar Compare Ordered Quad-Precision)
21930   case 0x284:     // xscmpuqp (VSX Scalar Compare Unrdered Quad-Precision)
21931      {
21932         /* Note, only differece between xscmoqp and xscmpuqp is the
21933            exception flag settings which are not supported anyway. */
21934         IRExpr *bit4, *bit5, *bit6, *bit7;
21935         IRExpr *bit_zero, *bit_inf, *same_sign;
21936         UInt BF = IFIELD( theInstr, 23, 3 );
21937         IRTemp eq_lt_gt = newTemp( Ity_I32 );
21938         IRTemp CC = newTemp( Ity_I32 );
21939
21940         if (opc2 == 0x084) {
21941            DIP("xscmpoqp %d,v%d,v%d\n",  BF, vA_addr, vB_addr);
21942         } else {
21943            DIP("xscmpuqp %d,v%d,v%d\n",  BF, vA_addr, vB_addr);
21944         }
21945
21946         assign( vA, getVSReg(vA_addr));
21947
21948         /* A and B have the same sign */
21949         same_sign =  binop( Iop_CmpEQ64,
21950                             binop( Iop_Shr64,
21951                                    unop( Iop_V128HIto64,
21952                                          mkexpr( vA ) ),
21953                                    mkU8( 63 ) ),
21954                             binop( Iop_Shr64,
21955                                    unop( Iop_V128HIto64,
21956                                          mkexpr( vB ) ),
21957                                    mkU8( 63 ) ) );
21958
21959         /* A < B */
21960         bit4 = Quad_precision_gt( vB, vA );
21961
21962         /*  A > B  */
21963         bit5 = Quad_precision_gt( vA, vB );
21964
21965         /* A equal B */
21966         bit6 = mkAND1( binop( Iop_CmpEQ64,
21967                               unop( Iop_V128HIto64,
21968                                     mkexpr( vA ) ),
21969                               unop( Iop_V128HIto64,
21970                                     mkexpr( vB ) ) ),
21971                        binop( Iop_CmpEQ64,
21972                               unop( Iop_V128to64,
21973                                     mkexpr( vA ) ),
21974                               unop( Iop_V128to64,
21975                                     mkexpr( vB ) ) ) );
21976
21977         /* test both zero don't care about sign */
21978         bit_zero = mkAND1( is_Zero( Ity_V128, vA ), is_Zero( Ity_V128, vB ) );
21979
21980         /* test both for infinity, don't care about sign */
21981         bit_inf = mkAND1(
21982                          mkAND1( is_Inf( Ity_V128, vA ), is_Inf( Ity_V128, vB ) ),
21983                          binop( Iop_CmpEQ64,
21984                                 binop( Iop_And64,
21985                                        unop( Iop_V128to64,
21986                                              mkexpr( vA ) ),
21987                                        mkU64( 0x80000000) ),
21988                                 binop( Iop_And64,
21989                                        unop( Iop_V128to64,
21990                                              mkexpr( vB ) ),
21991                                        mkU64( 0x80000000) ) ) );
21992
21993         /* exp A or exp B is NaN */
21994         bit7 = mkOR1( is_NaN( Ity_V128, vA ),
21995                       is_NaN( Ity_V128, vB ) );
21996
21997         assign( eq_lt_gt,
21998                 binop( Iop_Or32,
21999                        binop( Iop_Or32,
22000                               binop( Iop_Shl32,
22001                                      unop( Iop_1Uto32, bit4 ),
22002                                      mkU8( 3 ) ),
22003                               binop( Iop_Shl32,
22004                                      unop( Iop_1Uto32, bit5 ),
22005                                      mkU8( 2 ) ) ),
22006                        binop( Iop_Or32,
22007                               binop( Iop_Shl32,
22008                                      unop( Iop_1Uto32, bit6 ),
22009                                      mkU8( 1 ) ),
22010                               binop( Iop_Or32,
22011                                      binop( Iop_Shl32,
22012                                             unop( Iop_1Uto32,
22013                                                   bit_zero ),
22014                                             mkU8( 1 ) ),
22015                                      binop( Iop_Shl32,
22016                                             unop( Iop_1Uto32,
22017                                                   mkAND1( bit_inf, same_sign ) ),
22018                                             mkU8( 1 ) ) ) ) ) );
22019
22020         assign(CC, binop( Iop_Or32,
22021                           binop( Iop_And32,
22022                                  unop( Iop_Not32,
22023                                        unop( Iop_1Sto32, bit7 ) ),
22024                                  mkexpr( eq_lt_gt ) ),
22025                           unop( Iop_1Uto32, bit7 ) ) );
22026
22027         /* put result of the comparison into CC and FPCC */
22028         putGST_field( PPC_GST_CR, mkexpr( CC ), BF );
22029         putFPCC( mkexpr( CC ) );
22030         return True;
22031      }
22032      break;
22033
22034   case 0xA4:     // xscmpexpqp (VSX Scalar Compare Exponents Double-Precision)
22035      {
22036         IRExpr *bit4, *bit5, *bit6, *bit7;
22037         UInt BF = IFIELD( theInstr, 23, 3 );
22038
22039         IRTemp eq_lt_gt = newTemp( Ity_I32 );
22040         IRTemp CC = newTemp( Ity_I32 );
22041
22042         DIP("xscmpexpqp %d,v%d,v%d\n",  BF, vA_addr, vB_addr);
22043
22044         assign( vA, getVSReg(vA_addr));
22045
22046         /* A exp < B exp */
22047         bit4 = binop( Iop_CmpLT64U,
22048                      binop( Iop_And64,
22049                             unop( Iop_V128HIto64,
22050                                   mkexpr( vA ) ),
22051                             mkU64( 0x7FFF000000000000 ) ),
22052                      binop( Iop_And64,
22053                             unop( Iop_V128HIto64,
22054                                   mkexpr( vB ) ),
22055                             mkU64( 0x7FFF000000000000 ) ) );
22056         /*  exp > B exp */
22057         bit5 = binop( Iop_CmpLT64U,
22058                      binop( Iop_And64,
22059                             unop( Iop_V128HIto64,
22060                                   mkexpr( vB ) ),
22061                             mkU64( 0x7FFF000000000000 ) ),
22062                      binop( Iop_And64,
22063                             unop( Iop_V128HIto64,
22064                                   mkexpr( vA ) ),
22065                             mkU64( 0x7FFF000000000000 ) ) );
22066         /* test equal */
22067         bit6 = binop( Iop_CmpEQ64,
22068                      binop( Iop_And64,
22069                             unop( Iop_V128HIto64,
22070                                   mkexpr( vA ) ),
22071                             mkU64( 0x7FFF000000000000 ) ),
22072                      binop( Iop_And64,
22073                             unop( Iop_V128HIto64,
22074                                   mkexpr( vB ) ),
22075                             mkU64( 0x7FFF000000000000 ) ) );
22076
22077         /* exp A or exp B is NaN */
22078         bit7 = mkOR1( is_NaN( Ity_V128, vA ),
22079                       is_NaN( Ity_V128, vB ) );
22080
22081         /* NaN over rules the other comparisons */
22082         assign( eq_lt_gt, binop( Iop_Or32,
22083                                  binop( Iop_Shl32,
22084                                         unop( Iop_1Uto32, bit4 ),
22085                                         mkU8( 3) ),
22086                                  binop( Iop_Or32,
22087                                         binop( Iop_Shl32,
22088                                                unop( Iop_1Uto32, bit5 ),
22089                                                mkU8( 2) ),
22090                                         binop( Iop_Shl32,
22091                                                unop( Iop_1Uto32, bit6 ),
22092                                                mkU8( 1 ) ) ) ) );
22093         assign(CC, binop( Iop_Or32,
22094                           binop( Iop_And32,
22095                                  unop( Iop_Not32,
22096                                        unop( Iop_1Sto32, bit7 ) ),
22097                                  mkexpr( eq_lt_gt ) ),
22098                           unop( Iop_1Uto32, bit7 ) ) );
22099
22100         /* put result of the comparison into CC and FPCC */
22101         putGST_field( PPC_GST_CR, mkexpr( CC ), BF );
22102         putFPCC( mkexpr( CC ) );
22103         return True;
22104      }
22105      break;
22106
22107   case 0x2C4:    // xststdcqp (VSX Scalar Quad-Precision Test Data Class)
22108      {
22109         UInt BF = IFIELD( theInstr, 23, 3 );
22110         UInt DCMX_mask = IFIELD( theInstr, 16, 7 );
22111         IRTemp CC = newTemp( Ity_I64 );
22112         IRTemp NaN = newTemp( Ity_I64 );
22113         IRTemp inf = newTemp( Ity_I64 );
22114         IRTemp pos = newTemp( Ity_I64 );
22115         IRTemp DCM = newTemp( Ity_I64 );
22116         IRTemp zero = newTemp( Ity_I64 );
22117         IRTemp dnorm = newTemp( Ity_I64 );
22118
22119         DIP("xststdcqp  %d,v%d,%d\n",  BF, vB_addr, DCMX_mask);
22120
22121         assign( zero, unop( Iop_1Uto64, is_Zero( Ity_V128, vB ) ) );
22122         assign( pos, unop( Iop_1Uto64,
22123                            binop( Iop_CmpEQ64,
22124                                   binop( Iop_Shr64,
22125                                          unop( Iop_V128HIto64,
22126                                                mkexpr( vB ) ),
22127                                          mkU8( 63 ) ),
22128                                   mkU64( 0 ) ) ) );
22129
22130         assign( NaN, unop( Iop_1Uto64, is_NaN( Ity_V128, vB ) ) );
22131         assign( inf, unop( Iop_1Uto64, is_Inf( Ity_V128, vB ) ) );
22132
22133         assign( dnorm, unop( Iop_1Uto64, is_Denorm( Ity_V128, vB ) ) );
22134         assign( DCM, create_DCM( Ity_I64, NaN, inf, zero, dnorm, pos ) );
22135         assign( CC, binop( Iop_Or64,
22136                            binop( Iop_And64,    /* vB sign bit */
22137                                  binop( Iop_Shr64,
22138                                         unop( Iop_V128HIto64, mkexpr( vB ) ),
22139                                         mkU8( 60 ) ),
22140                                  mkU64( 0x8 ) ),
22141                           binop( Iop_Shl64,
22142                                  unop( Iop_1Uto64,
22143                                        binop( Iop_CmpNE64,
22144                                               binop( Iop_And64,
22145                                                      mkexpr( DCM ),
22146                                                      mkU64( DCMX_mask ) ),
22147                                               mkU64( 0 ) ) ),
22148                                   mkU8( 1 ) ) ) );
22149
22150         putGST_field( PPC_GST_CR, unop(Iop_64to32, mkexpr( CC ) ), BF );
22151         putFPCC( unop(Iop_64to32, mkexpr( CC ) ) );
22152         return True;
22153      }
22154      break;
22155
22156   case 0x324:    // xsabsqp  (VSX Scalar Absolute Quad-Precision)
22157                  // xsxexpqp (VSX Scalaar Extract Exponent Quad-Precision)
22158                  // xsnabsqp (VSX Scalar Negative Absolute Quad-Precision)
22159                  // xsnegqp  (VSX Scalar Negate Quad-Precision)
22160                  // xsxsigqp (VSX Scalar Extract Significand Quad-Precision)
22161      {
22162         UInt inst_select = IFIELD( theInstr, 16, 5);
22163
22164         switch (inst_select) {
22165         case 0:
22166            DIP("xsabsqp  v%d,v%d\n",  vT_addr, vB_addr);
22167            assign( vT, binop( Iop_AndV128, mkexpr( vB ),
22168                               binop( Iop_64HLtoV128,
22169                                      mkU64( 0x7FFFFFFFFFFFFFFF ),
22170                                      mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) );
22171            break;
22172
22173         case 2:
22174            DIP("xsxexpqp  v%d,v%d\n",  vT_addr, vB_addr);
22175            assign( vT, binop( Iop_ShrV128,
22176                               binop( Iop_AndV128, mkexpr( vB ),
22177                                      binop( Iop_64HLtoV128,
22178                                             mkU64( 0x7FFF000000000000 ),
22179                                             mkU64( 0x0000000000000000 ) ) ),
22180                               mkU8( 48 ) ) );
22181            break;
22182
22183         case 8:
22184            DIP("xsnabsqp  v%d,v%d\n",  vT_addr, vB_addr);
22185            assign( vT, binop( Iop_OrV128, mkexpr( vB ),
22186                            binop( Iop_64HLtoV128,
22187                                   mkU64( 0x8000000000000000 ),
22188                                   mkU64( 0x0000000000000000 ) ) ) );
22189            break;
22190
22191         case 16:
22192            DIP("xsnegqp  v%d,v%d\n",  vT_addr, vB_addr);
22193            assign( vT, binop( Iop_XorV128, mkexpr( vB ),
22194                            binop( Iop_64HLtoV128,
22195                                   mkU64( 0x8000000000000000 ),
22196                                   mkU64( 0x0000000000000000 ) ) ) );
22197            break;
22198
22199         case 18:
22200         {
22201            IRTemp expZero = newTemp( Ity_I64 );
22202            IRTemp expInfinity = newTemp( Ity_I64 );
22203
22204            DIP("xsxsigqp  v%d,v%d\n",  vT_addr, vB_addr);
22205
22206            assign( expZero, unop( Iop_1Uto64,
22207                                   binop( Iop_CmpNE64,
22208                                          binop( Iop_And64,
22209                                                 unop( Iop_V128HIto64,
22210                                                       mkexpr( vB ) ),
22211                                                 mkU64( 0x7FFF000000000000 ) ),
22212                                          mkU64( 0x0 ) ) ) );
22213
22214            assign( expInfinity,
22215                    unop( Iop_1Uto64,
22216                          binop( Iop_CmpNE64,
22217                                 binop( Iop_And64,
22218                                        unop( Iop_V128HIto64,
22219                                              mkexpr( vB ) ),
22220                                        mkU64( 0x7FFF000000000000 ) ),
22221                                 mkU64( 0x7FFF000000000000 ) ) ) );
22222
22223            /* Clear upper 16 bits to 0x0000.  If the exp was zero or infinity
22224             * set bit 48 (lsb = 0) to 0, otherwise  set bit 48 to 1.
22225             */
22226            assign( vT,
22227                    binop( Iop_OrV128,
22228                           binop( Iop_ShrV128,
22229                                  binop( Iop_ShlV128,
22230                                         mkexpr( vB ),
22231                                         mkU8( 16 ) ),
22232                                  mkU8( 16 ) ),
22233                           binop( Iop_64HLtoV128,
22234                                  binop( Iop_Shl64,
22235                                         binop( Iop_And64,
22236                                                mkexpr( expZero ),
22237                                                mkexpr( expInfinity ) ),
22238                                         mkU8( 48 ) ),
22239                                  mkU64( 0 ) ) ) );
22240         }
22241         break;
22242
22243         default:
22244            vex_printf( "dis_vx_scalar_quad_precision invalid inst_select (ppc)(opc2)\n" );
22245            return False;
22246         }
22247      }
22248      break;
22249   case 0x364:    // xsiexpqp (VST Scalar Insert Exponent Quad-Precision)
22250      {
22251         IRTemp exp = newTemp( Ity_I64 );
22252
22253         DIP("xsiexpqp  v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
22254
22255         assign( vA, getVSReg( vA_addr ) );
22256         assign( exp, binop( Iop_And64,
22257                                 unop( Iop_V128HIto64,
22258                                       mkexpr( vB ) ),
22259                                 mkU64( 0x7FFFULL ) ) );
22260         assign( vT, binop( Iop_64HLtoV128,
22261                            binop( Iop_Or64,
22262                                   binop( Iop_And64,
22263                                          unop( Iop_V128HIto64,
22264                                                mkexpr( vA ) ),
22265                                          mkU64( 0x8000FFFFFFFFFFFFULL ) ),
22266                                   binop( Iop_Shl64,
22267                                          mkexpr( exp ),
22268                                          mkU8( 48 ) ) ),
22269                            unop( Iop_V128to64,
22270                                  mkexpr( vA ) ) ) );
22271      }
22272      break;
22273
22274   default:
22275      vex_printf( "dis_vx_scalar_quad_precision(ppc)(opc2)\n" );
22276
22277      return False;
22278   }
22279
22280   putVSReg( vT_addr, mkexpr( vT ) );
22281   return True;
22282}
22283
22284/*
22285 * VSX permute and other miscealleous instructions
22286 */
22287static Bool
22288dis_vx_permute_misc( UInt theInstr, UInt opc2 )
22289{
22290   /* XX3-Form */
22291   UChar opc1 = ifieldOPC( theInstr );
22292   UChar XT = ifieldRegXT ( theInstr );
22293   UChar XA = ifieldRegXA ( theInstr );
22294   UChar XB = ifieldRegXB ( theInstr );
22295   IRTemp vT = newTemp( Ity_V128 );
22296   IRTemp vA = newTemp( Ity_V128 );
22297   IRTemp vB = newTemp( Ity_V128 );
22298
22299   if (opc1 != 0x3C) {
22300      vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
22301      return False;
22302   }
22303
22304   assign( vA, getVSReg( XA ) );
22305   assign( vB, getVSReg( XB ) );
22306
22307   switch (opc2) {
22308      case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
22309      {
22310         UChar SHW = ifieldSHW ( theInstr );
22311         IRTemp result = newTemp(Ity_V128);
22312         if ( SHW != 0 ) {
22313             IRTemp hi = newTemp(Ity_V128);
22314             IRTemp lo = newTemp(Ity_V128);
22315             assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
22316             assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
22317             assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
22318         } else
22319             assign ( result, mkexpr(vA) );
22320         DIP("xxsldwi v%d,v%d,v%d,%d\n", XT, XA, XB, SHW);
22321         putVSReg( XT, mkexpr(result) );
22322         break;
22323      }
22324      case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
22325      {
22326         UChar DM = ifieldDM ( theInstr );
22327         IRTemp hi = newTemp(Ity_I64);
22328         IRTemp lo = newTemp(Ity_I64);
22329
22330         if (DM & 0x2)
22331           assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
22332         else
22333           assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
22334
22335         if (DM & 0x1)
22336           assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
22337         else
22338           assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
22339
22340         assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
22341
22342         DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT, XA, XB, DM);
22343         putVSReg( XT, mkexpr( vT ) );
22344         break;
22345      }
22346      case 0x48: // xxmrghw (VSX Merge High Word)
22347      case 0xc8: // xxmrglw (VSX Merge Low Word)
22348      {
22349         const HChar type = (opc2 == 0x48) ? 'h' : 'l';
22350         IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
22351         IRTemp a64 = newTemp(Ity_I64);
22352         IRTemp ahi32 = newTemp(Ity_I32);
22353         IRTemp alo32 = newTemp(Ity_I32);
22354         IRTemp b64 = newTemp(Ity_I64);
22355         IRTemp bhi32 = newTemp(Ity_I32);
22356         IRTemp blo32 = newTemp(Ity_I32);
22357
22358         assign( a64, unop(word_op, mkexpr(vA)) );
22359         assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
22360         assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
22361
22362         assign( b64, unop(word_op, mkexpr(vB)) );
22363         assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
22364         assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
22365
22366         assign( vT, binop(Iop_64HLtoV128,
22367                           binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
22368                           binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
22369
22370         DIP("xxmrg%cw v%d,v%d,v%d\n", type, XT, XA, XB);
22371         putVSReg( XT, mkexpr( vT ) );
22372         break;
22373      }
22374      case 0x018: // xxsel (VSX Select)
22375      {
22376         UChar XC = ifieldRegXC(theInstr);
22377         IRTemp vC = newTemp( Ity_V128 );
22378         assign( vC, getVSReg( XC ) );
22379         DIP("xxsel v%d,v%d,v%d,v%d\n", XT, XA, XB, XC);
22380         /* vD = (vA & ~vC) | (vB & vC) */
22381         putVSReg( XT, binop(Iop_OrV128,
22382            binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
22383            binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
22384         break;
22385      }
22386
22387      case 0x68: // xxperm  (VSX Permute )
22388      case 0xE8: // xxpermr (VSX Permute right-index )
22389      {
22390         int i;
22391         IRTemp new_Vt[17];
22392         IRTemp perm_val[16];
22393         IRTemp perm_val_gt16[16];
22394         IRTemp tmp_val[16];
22395         IRTemp perm_idx[16];
22396         IRTemp perm_mask = newTemp( Ity_V128 );
22397         IRTemp val_mask  = newTemp( Ity_V128 );
22398         int    dest_shift_amount = 0;
22399
22400         if ( opc2 == 0x68 ) {
22401            DIP("xxperm v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
22402
22403         } else {
22404            /* Same as xperm just the index is 31 - idx */
22405            DIP("xxpermr v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
22406         }
22407
22408         new_Vt[0] = newTemp( Ity_V128 );
22409
22410         assign( vT, getVSReg( XT ) );
22411
22412         assign( new_Vt[0], binop( Iop_64HLtoV128,
22413                                   mkU64( 0x0 ), mkU64( 0x0 ) ) );
22414         assign( perm_mask, binop( Iop_64HLtoV128,
22415                                   mkU64( 0x0 ), mkU64( 0x1F ) ) );
22416         assign( val_mask, binop( Iop_64HLtoV128,
22417                                  mkU64( 0x0 ), mkU64( 0xFF ) ) );
22418
22419         /* For each permute index in XB, the permute list, select the byte
22420          * from XA indexed by the permute index if the permute index is less
22421          * then 16.  Copy the selected byte to the destination location in
22422          * the result.
22423          */
22424         for ( i = 0; i < 16; i++ ) {
22425            perm_val_gt16[i] = newTemp( Ity_V128 );
22426            perm_val[i] = newTemp( Ity_V128 );
22427            perm_idx[i] = newTemp( Ity_I8 );
22428            tmp_val[i]  = newTemp( Ity_V128 );
22429            new_Vt[i+1]  = newTemp( Ity_V128 );
22430
22431            /* create mask to extract the permute index value from vB,
22432             * store value in least significant bits of perm_val
22433             */
22434            if ( opc2 == 0x68 )
22435               /* xxperm, the perm value is the index value in XB */
22436               assign( perm_val[i], binop( Iop_ShrV128,
22437                                           binop( Iop_AndV128,
22438                                                  mkexpr(vB),
22439                                                  binop( Iop_ShlV128,
22440                                                         mkexpr( perm_mask ),
22441                                                         mkU8( (15 - i) * 8 ) ) ),
22442                                           mkU8( (15 - i) * 8 ) ) );
22443
22444            else
22445               /* xxpermr, the perm value is 31 - index value in XB */
22446               assign( perm_val[i],
22447                       binop( Iop_Sub8x16,
22448                              binop( Iop_64HLtoV128,
22449                                     mkU64( 0 ), mkU64( 31 ) ),
22450                              binop( Iop_ShrV128,
22451                                     binop( Iop_AndV128,
22452                                            mkexpr( vB ),
22453                                            binop( Iop_ShlV128,
22454                                                   mkexpr( perm_mask ),
22455                                                   mkU8( ( 15 - i ) * 8 ) ) ),
22456                                     mkU8( ( 15 - i ) * 8 ) ) ) );
22457
22458            /* Determine if the perm_val[] > 16.  If it is, then the value
22459             * will come from xT otherwise it comes from xA.  Either way,
22460             * create the mask to get the value from the source using the
22461             * lower 3 bits of perm_val[].  Create a 128 bit mask from the
22462             * upper bit of perm_val[] to be used to select from xT or xA.
22463             */
22464            assign( perm_val_gt16[i],
22465                    binop(Iop_64HLtoV128,
22466                          unop( Iop_1Sto64,
22467                                unop( Iop_64to1,
22468                                      unop( Iop_V128to64,
22469                                            binop( Iop_ShrV128,
22470                                                   mkexpr( perm_val[i] ),
22471                                                   mkU8( 4 ) ) ) ) ),
22472                          unop( Iop_1Sto64,
22473                                unop( Iop_64to1,
22474                                      unop( Iop_V128to64,
22475                                            binop( Iop_ShrV128,
22476                                                   mkexpr( perm_val[i] ),
22477                                                   mkU8( 4 ) ) ) ) ) ) );
22478
22479            assign( perm_idx[i],
22480                    unop(Iop_32to8,
22481                         binop( Iop_Mul32,
22482                                binop( Iop_Sub32,
22483                                       mkU32( 15 ),
22484                                       unop( Iop_64to32,
22485                                             binop( Iop_And64,
22486                                                  unop( Iop_V128to64,
22487                                                       mkexpr( perm_val[i] ) ),
22488                                                  mkU64( 0xF ) ) ) ),
22489                                mkU32( 8 ) ) ) );
22490
22491            dest_shift_amount = ( 15 - i )*8;
22492
22493            /* Use perm_val_gt16 to select value from vA or vT */
22494            assign( tmp_val[i],
22495                    binop( Iop_ShlV128,
22496                           binop( Iop_ShrV128,
22497                                  binop( Iop_OrV128,
22498                                         binop( Iop_AndV128,
22499                                                mkexpr( vA ),
22500                                                binop( Iop_AndV128,
22501                                                       unop( Iop_NotV128,
22502                                                             mkexpr( perm_val_gt16[i] ) ),
22503                                                       binop( Iop_ShlV128,
22504                                                              mkexpr( val_mask ),
22505                                                              mkexpr( perm_idx[i] ) ) ) ),
22506                                         binop( Iop_AndV128,
22507                                                mkexpr( vT ),
22508                                                binop( Iop_AndV128,
22509                                                       mkexpr( perm_val_gt16[i] ),
22510                                                       binop( Iop_ShlV128,
22511                                                              mkexpr( val_mask ),
22512                                                              mkexpr( perm_idx[i] ) ) ) ) ),
22513                                  mkexpr( perm_idx[i] ) ),
22514                           mkU8( dest_shift_amount ) ) );
22515
22516            assign( new_Vt[i+1], binop( Iop_OrV128,
22517                                       mkexpr( tmp_val[i] ),
22518                                       mkexpr( new_Vt[i] ) ) );
22519         }
22520         putVSReg( XT, mkexpr( new_Vt[16] ) );
22521         break;
22522      }
22523
22524      case 0x148: // xxspltw (VSX Splat Word)
22525      {
22526         UChar UIM   = ifieldRegA(theInstr) & 3;
22527         UChar sh_uim = (3 - (UIM)) * 32;
22528         DIP("xxspltw v%d,v%d,%d\n", XT, XB, UIM);
22529         putVSReg( XT,
22530                   unop( Iop_Dup32x4,
22531                         unop( Iop_V128to32,
22532                               binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
22533         break;
22534      }
22535
22536      default:
22537         vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
22538         return False;
22539   }
22540   return True;
22541}
22542
22543/*
22544  AltiVec Load Instructions
22545*/
22546static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr )
22547{
22548   /* X-Form */
22549   UChar opc1     = ifieldOPC(theInstr);
22550   UChar vD_addr  = ifieldRegDS(theInstr);
22551   UChar rA_addr  = ifieldRegA(theInstr);
22552   UChar rB_addr  = ifieldRegB(theInstr);
22553   UInt  opc2     = ifieldOPClo10(theInstr);
22554   UChar b0       = ifieldBIT0(theInstr);
22555
22556   IRType ty         = mode64 ? Ity_I64 : Ity_I32;
22557   IRTemp EA         = newTemp(ty);
22558   IRTemp EA_align16 = newTemp(ty);
22559
22560   if (opc1 != 0x1F || b0 != 0) {
22561      vex_printf("dis_av_load(ppc)(instr)\n");
22562      return False;
22563   }
22564
22565   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
22566   assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
22567
22568   switch (opc2) {
22569
22570   case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
22571      IRDirty* d;
22572      UInt vD_off = vectorGuestRegOffset(vD_addr);
22573      IRExpr** args_be = mkIRExprVec_5(
22574                         IRExpr_GSPTR(),
22575                         mkU32(vD_off),
22576                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
22577                                          mkU32(0xF)),
22578                         mkU32(0)/*left*/,
22579                         mkU32(1)/*Big Endian*/);
22580      IRExpr** args_le = mkIRExprVec_5(
22581                         IRExpr_GSPTR(),
22582                         mkU32(vD_off),
22583                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
22584                                          mkU32(0xF)),
22585                         mkU32(0)/*left*/,
22586                         mkU32(0)/*Little Endian*/);
22587      if (!mode64) {
22588         d = unsafeIRDirty_0_N (
22589                        0/*regparms*/,
22590                        "ppc32g_dirtyhelper_LVS",
22591                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
22592                        args_be );
22593      } else {
22594         if (host_endness == VexEndnessBE)
22595            d = unsafeIRDirty_0_N (
22596                           0/*regparms*/,
22597                           "ppc64g_dirtyhelper_LVS",
22598                           fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
22599                           args_be );
22600         else
22601            d = unsafeIRDirty_0_N (
22602                           0/*regparms*/,
22603                           "ppc64g_dirtyhelper_LVS",
22604                           fnptr_to_fnentry( vbi, &ppc64g_dirtyhelper_LVS ),
22605                           args_le );
22606      }
22607      DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22608      /* declare guest state effects */
22609      d->nFxState = 1;
22610      vex_bzero(&d->fxState, sizeof(d->fxState));
22611      d->fxState[0].fx     = Ifx_Write;
22612      d->fxState[0].offset = vD_off;
22613      d->fxState[0].size   = sizeof(U128);
22614
22615      /* execute the dirty call, side-effecting guest state */
22616      stmt( IRStmt_Dirty(d) );
22617      break;
22618   }
22619   case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
22620      IRDirty* d;
22621      UInt vD_off = vectorGuestRegOffset(vD_addr);
22622      IRExpr** args_be = mkIRExprVec_5(
22623                             IRExpr_GSPTR(),
22624                             mkU32(vD_off),
22625                             binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
22626                                              mkU32(0xF)),
22627                             mkU32(1)/*right*/,
22628                             mkU32(1)/*Big Endian*/);
22629      IRExpr** args_le = mkIRExprVec_5(
22630                             IRExpr_GSPTR(),
22631                             mkU32(vD_off),
22632                             binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
22633                                              mkU32(0xF)),
22634                             mkU32(1)/*right*/,
22635                             mkU32(0)/*Little Endian*/);
22636
22637      if (!mode64) {
22638         d = unsafeIRDirty_0_N (
22639                        0/*regparms*/,
22640                        "ppc32g_dirtyhelper_LVS",
22641                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
22642                        args_be );
22643      } else {
22644         if (host_endness == VexEndnessBE)
22645            d = unsafeIRDirty_0_N (
22646                           0/*regparms*/,
22647                           "ppc64g_dirtyhelper_LVS",
22648                           fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
22649                           args_be );
22650         else
22651            d = unsafeIRDirty_0_N (
22652                           0/*regparms*/,
22653                           "ppc64g_dirtyhelper_LVS",
22654                           fnptr_to_fnentry( vbi, &ppc64g_dirtyhelper_LVS ),
22655                           args_le );
22656      }
22657      DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22658      /* declare guest state effects */
22659      d->nFxState = 1;
22660      vex_bzero(&d->fxState, sizeof(d->fxState));
22661      d->fxState[0].fx     = Ifx_Write;
22662      d->fxState[0].offset = vD_off;
22663      d->fxState[0].size   = sizeof(U128);
22664
22665      /* execute the dirty call, side-effecting guest state */
22666      stmt( IRStmt_Dirty(d) );
22667      break;
22668   }
22669   case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
22670      DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22671      /* loads addressed byte into vector[EA[0:3]
22672         since all other destination bytes are undefined,
22673         can simply load entire vector from 16-aligned EA */
22674      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
22675      break;
22676
22677   case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
22678      DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22679      /* see note for lvebx */
22680      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
22681      break;
22682
22683   case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
22684      DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22685      /* see note for lvebx */
22686      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
22687      break;
22688
22689   case 0x067: // lvx (Load Vector Indexed, AV p127)
22690      DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22691      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
22692      break;
22693
22694   case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
22695      DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22696      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
22697      break;
22698
22699   default:
22700      vex_printf("dis_av_load(ppc)(opc2)\n");
22701      return False;
22702   }
22703   return True;
22704}
22705
22706/*
22707  AltiVec Store Instructions
22708*/
22709static Bool dis_av_store ( UInt theInstr )
22710{
22711   /* X-Form */
22712   UChar opc1     = ifieldOPC(theInstr);
22713   UChar vS_addr  = ifieldRegDS(theInstr);
22714   UChar rA_addr  = ifieldRegA(theInstr);
22715   UChar rB_addr  = ifieldRegB(theInstr);
22716   UInt  opc2     = ifieldOPClo10(theInstr);
22717   UChar b0       = ifieldBIT0(theInstr);
22718
22719   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
22720   IRTemp EA           = newTemp(ty);
22721   IRTemp addr_aligned = newTemp(ty);
22722   IRTemp vS           = newTemp(Ity_V128);
22723   IRTemp eb           = newTemp(Ity_I8);
22724   IRTemp idx          = newTemp(Ity_I8);
22725
22726   if (opc1 != 0x1F || b0 != 0) {
22727      vex_printf("dis_av_store(ppc)(instr)\n");
22728      return False;
22729   }
22730
22731   assign( vS, getVReg(vS_addr));
22732   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
22733
22734   switch (opc2) {
22735   case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
22736      DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
22737      assign( eb, binop(Iop_And8, mkU8(0xF),
22738                        unop(Iop_32to8,
22739                             mkNarrowTo32(ty, mkexpr(EA)) )) );
22740     if (host_endness == VexEndnessLE) {
22741         assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
22742      } else {
22743         assign( idx, binop(Iop_Shl8,
22744                            binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
22745                            mkU8(3)) );
22746      }
22747      store( mkexpr(EA),
22748             unop( Iop_32to8, unop(Iop_V128to32,
22749                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
22750      break;
22751   }
22752   case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
22753      DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
22754      assign( addr_aligned, addr_align(mkexpr(EA), 2) );
22755      assign( eb, binop(Iop_And8, mkU8(0xF),
22756                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
22757      if (host_endness == VexEndnessLE) {
22758          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
22759      } else {
22760         assign( idx, binop(Iop_Shl8,
22761                            binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
22762                            mkU8(3)) );
22763      }
22764      store( mkexpr(addr_aligned),
22765             unop( Iop_32to16, unop(Iop_V128to32,
22766                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
22767      break;
22768   }
22769   case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
22770      DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
22771      assign( addr_aligned, addr_align(mkexpr(EA), 4) );
22772      assign( eb, binop(Iop_And8, mkU8(0xF),
22773                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
22774      if (host_endness == VexEndnessLE) {
22775         assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
22776      } else {
22777         assign( idx, binop(Iop_Shl8,
22778                            binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
22779                            mkU8(3)) );
22780      }
22781      store( mkexpr( addr_aligned),
22782             unop( Iop_V128to32,
22783                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
22784      break;
22785   }
22786
22787   case 0x0E7: // stvx (Store Vector Indexed, AV p134)
22788      DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
22789      store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
22790      break;
22791
22792   case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
22793      DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
22794      store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
22795      break;
22796
22797   default:
22798      vex_printf("dis_av_store(ppc)(opc2)\n");
22799      return False;
22800   }
22801   return True;
22802}
22803
22804/*
22805  AltiVec Arithmetic Instructions
22806*/
22807static Bool dis_av_arith ( UInt theInstr )
22808{
22809   /* VX-Form */
22810   UChar opc1     = ifieldOPC(theInstr);
22811   UChar vD_addr  = ifieldRegDS(theInstr);
22812   UChar vA_addr  = ifieldRegA(theInstr);
22813   UChar vB_addr  = ifieldRegB(theInstr);
22814   UInt  opc2     = IFIELD( theInstr, 0, 11 );
22815
22816   IRTemp vA = newTemp(Ity_V128);
22817   IRTemp vB = newTemp(Ity_V128);
22818   IRTemp z3 = newTemp(Ity_I64);
22819   IRTemp z2 = newTemp(Ity_I64);
22820   IRTemp z1 = newTemp(Ity_I64);
22821   IRTemp z0 = newTemp(Ity_I64);
22822   IRTemp aEvn, aOdd;
22823   IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
22824   IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
22825   IRTemp b3, b2, b1, b0;
22826
22827   aEvn = aOdd = IRTemp_INVALID;
22828   a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
22829   a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
22830   b3 = b2 = b1 = b0 = IRTemp_INVALID;
22831
22832   assign( vA, getVReg( vA_addr ) );
22833   assign( vB, getVReg( vB_addr ) );
22834
22835   if (opc1 != 0x4) {
22836      vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
22837      return False;
22838   }
22839
22840   switch (opc2) {
22841   /* Add */
22842   case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
22843      DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22844      /* unsigned_ov(x+y) = (y >u not(x)) */
22845      putVReg( vD_addr, binop( Iop_ShrN32x4,
22846                               binop( Iop_CmpGT32Ux4, mkexpr( vB ),
22847                                    unop( Iop_NotV128, mkexpr( vA ) ) ),
22848                              mkU8( 31 ) ) );
22849      break;
22850   }
22851   case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
22852      DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22853      putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
22854      break;
22855
22856   case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
22857      DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22858      putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
22859      break;
22860
22861   case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
22862      DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22863      putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
22864      break;
22865
22866   case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
22867      DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22868      putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
22869      break;
22870
22871   case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
22872      DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22873      putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
22874      // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
22875      break;
22876
22877   case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
22878      DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22879      putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
22880      // TODO: set VSCR[SAT]
22881      break;
22882
22883   case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
22884      DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22885      putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
22886      // TODO: set VSCR[SAT]
22887      break;
22888
22889   case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
22890      DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22891      putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
22892      // TODO: set VSCR[SAT]
22893      break;
22894
22895   case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
22896      DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22897      putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
22898      // TODO: set VSCR[SAT]
22899      break;
22900
22901   case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
22902      DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22903      putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
22904      // TODO: set VSCR[SAT]
22905      break;
22906
22907
22908   /* Subtract */
22909   case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
22910      DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22911      /* unsigned_ov(x-y) = (y >u x) */
22912      putVReg( vD_addr, binop(Iop_ShrN32x4,
22913                              unop(Iop_NotV128,
22914                                   binop(Iop_CmpGT32Ux4, mkexpr(vB),
22915                                         mkexpr(vA))),
22916                              mkU8(31)) );
22917      break;
22918   }
22919   case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
22920      DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22921      putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
22922      break;
22923
22924   case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
22925      DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22926      putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
22927      break;
22928
22929   case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
22930      DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22931      putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
22932      break;
22933
22934   case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
22935      DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22936      putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
22937      break;
22938
22939   case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
22940      DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22941      putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
22942      // TODO: set VSCR[SAT]
22943      break;
22944
22945   case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
22946      DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22947      putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
22948      // TODO: set VSCR[SAT]
22949      break;
22950
22951   case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
22952      DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22953      putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
22954      // TODO: set VSCR[SAT]
22955      break;
22956
22957   case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
22958      DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22959      putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
22960      // TODO: set VSCR[SAT]
22961      break;
22962
22963   case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
22964      DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22965      putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
22966      // TODO: set VSCR[SAT]
22967      break;
22968
22969   case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
22970      DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22971      putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
22972      // TODO: set VSCR[SAT]
22973      break;
22974
22975
22976   /* Maximum */
22977   case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
22978      DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22979      putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
22980      break;
22981
22982   case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
22983      DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22984      putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
22985      break;
22986
22987   case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
22988      DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22989      putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
22990      break;
22991
22992   case 0x0C2: // vmaxud (Maximum Unsigned Double word)
22993      DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22994      putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
22995      break;
22996
22997   case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
22998      DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
22999      putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
23000      break;
23001
23002   case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
23003      DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23004      putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
23005      break;
23006
23007   case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
23008      DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23009      putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
23010      break;
23011
23012   case 0x1C2: // vmaxsd (Maximum Signed Double word)
23013      DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23014      putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
23015      break;
23016
23017   /* Minimum */
23018   case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
23019      DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23020      putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
23021      break;
23022
23023   case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
23024      DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23025      putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
23026      break;
23027
23028   case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
23029      DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23030      putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
23031      break;
23032
23033   case 0x2C2: // vminud (Minimum Unsigned Double Word)
23034      DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23035      putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
23036      break;
23037
23038   case 0x302: // vminsb (Minimum Signed Byte, AV p188)
23039      DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23040      putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
23041      break;
23042
23043   case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
23044      DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23045      putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
23046      break;
23047
23048   case 0x382: // vminsw (Minimum Signed Word, AV p190)
23049      DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23050      putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
23051      break;
23052
23053   case 0x3C2: // vminsd (Minimum Signed Double Word)
23054      DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23055      putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
23056      break;
23057
23058
23059   /* Average */
23060   case 0x402: // vavgub (Average Unsigned Byte, AV p152)
23061      DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23062      putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
23063      break;
23064
23065   case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
23066      DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23067      putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
23068      break;
23069
23070   case 0x482: // vavguw (Average Unsigned Word, AV p154)
23071      DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23072      putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
23073      break;
23074
23075   case 0x502: // vavgsb (Average Signed Byte, AV p149)
23076      DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23077      putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
23078      break;
23079
23080   case 0x542: // vavgsh (Average Signed Half Word, AV p150)
23081      DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23082      putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
23083      break;
23084
23085   case 0x582: // vavgsw (Average Signed Word, AV p151)
23086      DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23087      putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
23088      break;
23089
23090
23091   /* Multiply */
23092   case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
23093      DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23094      putVReg( vD_addr,
23095               binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
23096      break;
23097
23098   case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
23099      DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23100      putVReg( vD_addr,
23101               binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
23102      break;
23103
23104   case 0x088: // vmulouw (Multiply Odd Unsigned Word)
23105      DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23106      putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
23107      break;
23108
23109   case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
23110      DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23111      putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
23112      break;
23113
23114   case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
23115      DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23116      putVReg( vD_addr,
23117               binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
23118      break;
23119
23120   case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
23121      DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23122      putVReg( vD_addr,
23123               binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
23124      break;
23125
23126   case 0x188: // vmulosw (Multiply Odd Signed Word)
23127      DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23128      putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
23129      break;
23130
23131   case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
23132      DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23133      putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
23134      break;
23135
23136   case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
23137      DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23138      putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
23139      break;
23140
23141   case 0x288: // vmuleuw (Multiply Even Unsigned Word)
23142      DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23143      putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
23144      break;
23145
23146   case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
23147      DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23148      putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
23149      break;
23150
23151   case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
23152      DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23153      putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
23154      break;
23155
23156   case 0x388: // vmulesw (Multiply Even Signed Word)
23157      DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23158      putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
23159      break;
23160
23161   /* Sum Across Partial */
23162   case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
23163      IRTemp aEE, aEO, aOE, aOO;
23164      aEE = aEO = aOE = aOO = IRTemp_INVALID;
23165      DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23166
23167      /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
23168      expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
23169      expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
23170      expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
23171
23172      /* break V128 to 4xI32's, zero-extending to I64's */
23173      breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
23174      breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
23175      breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
23176      breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
23177      breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
23178
23179      /* add lanes */
23180      assign( z3, binop(Iop_Add64, mkexpr(b3),
23181                     binop(Iop_Add64,
23182                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
23183                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
23184      assign( z2, binop(Iop_Add64, mkexpr(b2),
23185                     binop(Iop_Add64,
23186                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
23187                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
23188      assign( z1, binop(Iop_Add64, mkexpr(b1),
23189                     binop(Iop_Add64,
23190                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
23191                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
23192      assign( z0, binop(Iop_Add64, mkexpr(b0),
23193                     binop(Iop_Add64,
23194                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
23195                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
23196
23197      /* saturate-narrow to 32bit, and combine to V128 */
23198      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
23199                                         mkexpr(z1), mkexpr(z0)) );
23200      break;
23201   }
23202   case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
23203      IRTemp aEE, aEO, aOE, aOO;
23204      aEE = aEO = aOE = aOO = IRTemp_INVALID;
23205      DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23206
23207      /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
23208      expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
23209      expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
23210      expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
23211
23212      /* break V128 to 4xI32's, sign-extending to I64's */
23213      breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
23214      breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
23215      breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
23216      breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
23217      breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
23218
23219      /* add lanes */
23220      assign( z3, binop(Iop_Add64, mkexpr(b3),
23221                     binop(Iop_Add64,
23222                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
23223                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
23224      assign( z2, binop(Iop_Add64, mkexpr(b2),
23225                     binop(Iop_Add64,
23226                        binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
23227                        binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
23228      assign( z1, binop(Iop_Add64, mkexpr(b1),
23229                     binop(Iop_Add64,
23230                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
23231                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
23232      assign( z0, binop(Iop_Add64, mkexpr(b0),
23233                     binop(Iop_Add64,
23234                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
23235                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
23236
23237      /* saturate-narrow to 32bit, and combine to V128 */
23238      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
23239                                         mkexpr(z1), mkexpr(z0)) );
23240      break;
23241   }
23242   case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
23243      DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23244
23245      /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
23246      expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
23247
23248      /* break V128 to 4xI32's, sign-extending to I64's */
23249      breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
23250      breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
23251      breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
23252
23253      /* add lanes */
23254      assign( z3, binop(Iop_Add64, mkexpr(b3),
23255                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
23256      assign( z2, binop(Iop_Add64, mkexpr(b2),
23257                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
23258      assign( z1, binop(Iop_Add64, mkexpr(b1),
23259                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
23260      assign( z0, binop(Iop_Add64, mkexpr(b0),
23261                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
23262
23263      /* saturate-narrow to 32bit, and combine to V128 */
23264      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
23265                                         mkexpr(z1), mkexpr(z0)) );
23266      break;
23267   }
23268   case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
23269      DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23270
23271      /* break V128 to 4xI32's, sign-extending to I64's */
23272      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
23273      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
23274
23275      /* add lanes */
23276      assign( z2, binop(Iop_Add64, mkexpr(b2),
23277                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
23278      assign( z0, binop(Iop_Add64, mkexpr(b0),
23279                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
23280
23281      /* saturate-narrow to 32bit, and combine to V128 */
23282      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
23283                                         mkU64(0), mkexpr(z0)) );
23284      break;
23285   }
23286   case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
23287      DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23288
23289      /* break V128 to 4xI32's, sign-extending to I64's */
23290      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
23291      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
23292
23293      /* add lanes */
23294      assign( z0, binop(Iop_Add64, mkexpr(b0),
23295                     binop(Iop_Add64,
23296                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
23297                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
23298
23299      /* saturate-narrow to 32bit, and combine to V128 */
23300      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
23301                                         mkU64(0), mkexpr(z0)) );
23302      break;
23303   }
23304   default:
23305      vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
23306      return False;
23307   }
23308   return True;
23309}
23310
23311/*
23312  AltiVec Logic Instructions
23313*/
23314static Bool dis_av_logic ( UInt theInstr )
23315{
23316   /* VX-Form */
23317   UChar opc1    = ifieldOPC(theInstr);
23318   UChar vD_addr = ifieldRegDS(theInstr);
23319   UChar vA_addr = ifieldRegA(theInstr);
23320   UChar vB_addr = ifieldRegB(theInstr);
23321   UInt  opc2    = IFIELD( theInstr, 0, 11 );
23322
23323   IRTemp vA = newTemp(Ity_V128);
23324   IRTemp vB = newTemp(Ity_V128);
23325   assign( vA, getVReg(vA_addr));
23326   assign( vB, getVReg(vB_addr));
23327
23328   if (opc1 != 0x4) {
23329      vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
23330      return False;
23331   }
23332
23333   switch (opc2) {
23334   case 0x404: // vand (And, AV p147)
23335      DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23336      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
23337      break;
23338
23339   case 0x444: // vandc (And, AV p148)
23340      DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23341      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
23342                              unop(Iop_NotV128, mkexpr(vB))) );
23343      break;
23344
23345   case 0x484: // vor (Or, AV p217)
23346      DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23347      putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
23348      break;
23349
23350   case 0x4C4: // vxor (Xor, AV p282)
23351      DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23352      putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
23353      break;
23354
23355   case 0x504: // vnor (Nor, AV p216)
23356      DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23357      putVReg( vD_addr,
23358         unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
23359      break;
23360
23361   case 0x544: // vorc (vA Or'd with complement of vb)
23362      DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23363      putVReg( vD_addr, binop( Iop_OrV128,
23364                               mkexpr( vA ),
23365                               unop( Iop_NotV128, mkexpr( vB ) ) ) );
23366      break;
23367
23368   case 0x584: // vnand (Nand)
23369      DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23370      putVReg( vD_addr, unop( Iop_NotV128,
23371                              binop(Iop_AndV128, mkexpr( vA ),
23372                              mkexpr( vB ) ) ) );
23373      break;
23374
23375   case 0x684: // veqv (complemented XOr)
23376      DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23377      putVReg( vD_addr, unop( Iop_NotV128,
23378                              binop( Iop_XorV128, mkexpr( vA ),
23379                              mkexpr( vB ) ) ) );
23380      break;
23381
23382   default:
23383      vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
23384      return False;
23385   }
23386   return True;
23387}
23388
23389/*
23390  AltiVec Compare Instructions
23391*/
23392static Bool dis_av_cmp ( UInt theInstr )
23393{
23394   /* VXR-Form */
23395   UChar opc1     = ifieldOPC(theInstr);
23396   UChar vD_addr  = ifieldRegDS(theInstr);
23397   UChar vA_addr  = ifieldRegA(theInstr);
23398   UChar vB_addr  = ifieldRegB(theInstr);
23399   UChar flag_rC  = ifieldBIT10(theInstr);
23400   UInt  opc2     = IFIELD( theInstr, 0, 10 );
23401
23402   IRTemp vA = newTemp(Ity_V128);
23403   IRTemp vB = newTemp(Ity_V128);
23404   IRTemp vD = newTemp(Ity_V128);
23405   assign( vA, getVReg(vA_addr));
23406   assign( vB, getVReg(vB_addr));
23407
23408   if (opc1 != 0x4) {
23409      vex_printf("dis_av_cmp(ppc)(instr)\n");
23410      return False;
23411   }
23412
23413   switch (opc2) {
23414   case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
23415      DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23416                                      vD_addr, vA_addr, vB_addr);
23417      assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
23418      break;
23419
23420   case 0x007: // vcmpneb (Compare Not Equal byte)
23421      DIP("vcmpneb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23422                                      vD_addr, vA_addr, vB_addr);
23423      assign( vD, unop( Iop_NotV128,
23424                        binop( Iop_CmpEQ8x16, mkexpr( vA ), mkexpr( vB ) ) ) );
23425      break;
23426
23427   case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
23428      DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23429                                      vD_addr, vA_addr, vB_addr);
23430      assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
23431      break;
23432
23433   case 0x047: // vcmpneh (Compare Not Equal-to  Halfword)
23434      DIP("vcmpneh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23435                                      vD_addr, vA_addr, vB_addr);
23436      assign( vD, unop( Iop_NotV128,
23437                        binop( Iop_CmpEQ16x8, mkexpr( vA ), mkexpr( vB ) ) ) );
23438      break;
23439
23440   case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
23441      DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23442                                      vD_addr, vA_addr, vB_addr);
23443      assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
23444      break;
23445
23446   case 0x087: // vcmpnew (Compare Not Equal-to Word)
23447      DIP("vcmpnew%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23448                                      vD_addr, vA_addr, vB_addr);
23449      assign( vD, unop( Iop_NotV128,
23450                        binop( Iop_CmpEQ32x4, mkexpr( vA ), mkexpr( vB ) ) ) );
23451      break;
23452
23453   case 0x107: // vcmpnezb (Compare Not Equal or Zero byte)
23454      {
23455         IRTemp vAeqvB = newTemp( Ity_V128 );
23456         IRTemp vAeq0  = newTemp( Ity_V128 );
23457         IRTemp vBeq0  = newTemp( Ity_V128 );
23458         IRTemp zero   = newTemp( Ity_V128 );
23459
23460         DIP("vcmpnezb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23461                                         vD_addr, vA_addr, vB_addr);
23462
23463         assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) );
23464         assign( vAeq0, binop( Iop_CmpEQ8x16, mkexpr( vA ), mkexpr( zero ) ) );
23465         assign( vBeq0, binop( Iop_CmpEQ8x16, mkexpr( vB ), mkexpr( zero ) ) );
23466         assign( vAeqvB, unop( Iop_NotV128,
23467                               binop( Iop_CmpEQ8x16, mkexpr( vA ),
23468                                      mkexpr( vB ) ) ) );
23469
23470         assign( vD, mkOr3_V128( vAeqvB, vAeq0, vBeq0  ) );
23471      }
23472      break;
23473
23474   case 0x147: // vcmpnezh (Compare Not Equal or Zero Halfword)
23475      {
23476         IRTemp vAeqvB = newTemp( Ity_V128 );
23477         IRTemp vAeq0  = newTemp( Ity_V128 );
23478         IRTemp vBeq0  = newTemp( Ity_V128 );
23479         IRTemp zero   = newTemp( Ity_V128 );
23480
23481         DIP("vcmpnezh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23482                                         vD_addr, vA_addr, vB_addr);
23483
23484         assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) );
23485         assign( vAeq0, binop( Iop_CmpEQ16x8, mkexpr( vA ), mkexpr( zero ) ) );
23486         assign( vBeq0, binop( Iop_CmpEQ16x8, mkexpr( vB ), mkexpr( zero ) ) );
23487         assign( vAeqvB, unop( Iop_NotV128,
23488                               binop(Iop_CmpEQ16x8, mkexpr( vA ),
23489                                     mkexpr( vB ) ) ) );
23490
23491         assign( vD, binop( Iop_OrV128,
23492                            binop( Iop_OrV128,
23493                                   mkexpr( vAeq0 ),
23494                                   mkexpr( vBeq0 ) ),
23495                            mkexpr( vAeqvB ) ) );
23496      }
23497      break;
23498
23499   case 0x187: // vcmpnezw (Compare Not Equal or Zero Word)
23500      {
23501         IRTemp vAeqvB = newTemp( Ity_V128 );
23502         IRTemp vAeq0  = newTemp( Ity_V128 );
23503         IRTemp vBeq0  = newTemp( Ity_V128 );
23504         IRTemp zero   = newTemp( Ity_V128 );
23505
23506         DIP("vcmpnezw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23507                                         vD_addr, vA_addr, vB_addr);
23508
23509         assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) );
23510         assign( vAeq0, binop( Iop_CmpEQ32x4, mkexpr( vA ), mkexpr( zero ) ) );
23511         assign( vBeq0, binop( Iop_CmpEQ32x4, mkexpr( vB ), mkexpr( zero ) ) );
23512         assign( vAeqvB, unop( Iop_NotV128,
23513                               binop(Iop_CmpEQ32x4, mkexpr( vA ),
23514                                     mkexpr( vB ) ) ) );
23515
23516         assign( vD, binop( Iop_OrV128,
23517                            binop( Iop_OrV128,
23518                                   mkexpr( vAeq0 ),
23519                                   mkexpr( vBeq0 ) ),
23520                            mkexpr( vAeqvB ) ) );
23521      }
23522      break;
23523
23524   case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
23525      DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23526                                      vD_addr, vA_addr, vB_addr);
23527      assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
23528      break;
23529
23530   case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
23531      DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23532                                      vD_addr, vA_addr, vB_addr);
23533      assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
23534      break;
23535
23536   case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
23537      DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23538                                      vD_addr, vA_addr, vB_addr);
23539      assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
23540      break;
23541
23542   case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
23543      DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23544                                       vD_addr, vA_addr, vB_addr);
23545      assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
23546      break;
23547
23548   case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
23549      DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23550                                      vD_addr, vA_addr, vB_addr);
23551      assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
23552      break;
23553
23554   case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
23555      DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23556                                       vD_addr, vA_addr, vB_addr);
23557      assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
23558      break;
23559
23560   case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
23561      DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23562                                      vD_addr, vA_addr, vB_addr);
23563      assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
23564      break;
23565
23566   case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
23567      DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23568                                      vD_addr, vA_addr, vB_addr);
23569      assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
23570      break;
23571
23572   case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
23573      DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23574                                      vD_addr, vA_addr, vB_addr);
23575      assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
23576      break;
23577
23578   default:
23579      vex_printf("dis_av_cmp(ppc)(opc2)\n");
23580      return False;
23581   }
23582
23583   putVReg( vD_addr, mkexpr(vD) );
23584
23585   if (flag_rC) {
23586      set_AV_CR6( mkexpr(vD), True );
23587   }
23588   return True;
23589}
23590
23591/*
23592  AltiVec Multiply-Sum Instructions
23593*/
23594static Bool dis_av_multarith ( UInt theInstr )
23595{
23596   /* VA-Form */
23597   UChar opc1     = ifieldOPC(theInstr);
23598   UChar vD_addr  = ifieldRegDS(theInstr);
23599   UChar vA_addr  = ifieldRegA(theInstr);
23600   UChar vB_addr  = ifieldRegB(theInstr);
23601   UChar vC_addr  = ifieldRegC(theInstr);
23602   UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
23603
23604   IRTemp vA    = newTemp(Ity_V128);
23605   IRTemp vB    = newTemp(Ity_V128);
23606   IRTemp vC    = newTemp(Ity_V128);
23607   IRTemp zeros = newTemp(Ity_V128);
23608   IRTemp aLo   = newTemp(Ity_V128);
23609   IRTemp bLo   = newTemp(Ity_V128);
23610   IRTemp cLo   = newTemp(Ity_V128);
23611   IRTemp zLo   = newTemp(Ity_V128);
23612   IRTemp aHi   = newTemp(Ity_V128);
23613   IRTemp bHi   = newTemp(Ity_V128);
23614   IRTemp cHi   = newTemp(Ity_V128);
23615   IRTemp zHi   = newTemp(Ity_V128);
23616   IRTemp abEvn = newTemp(Ity_V128);
23617   IRTemp abOdd = newTemp(Ity_V128);
23618   IRTemp z3    = newTemp(Ity_I64);
23619   IRTemp z2    = newTemp(Ity_I64);
23620   IRTemp z1    = newTemp(Ity_I64);
23621   IRTemp z0    = newTemp(Ity_I64);
23622   IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
23623   IRTemp c3, c2, c1, c0;
23624
23625   ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
23626   c3 = c2 = c1 = c0 = IRTemp_INVALID;
23627
23628   assign( vA, getVReg(vA_addr));
23629   assign( vB, getVReg(vB_addr));
23630   assign( vC, getVReg(vC_addr));
23631   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
23632
23633   if (opc1 != 0x4) {
23634      vex_printf("dis_av_multarith(ppc)(instr)\n");
23635      return False;
23636   }
23637
23638   switch (opc2) {
23639   /* Multiply-Add */
23640   case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
23641      IRTemp cSigns = newTemp(Ity_V128);
23642      DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
23643          vD_addr, vA_addr, vB_addr, vC_addr);
23644      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
23645      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
23646      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
23647      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
23648      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
23649      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
23650      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
23651
23652      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
23653                         binop(Iop_SarN32x4,
23654                               binop(Iop_MullEven16Sx8,
23655                                     mkexpr(aLo), mkexpr(bLo)),
23656                               mkU8(15))) );
23657
23658      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
23659                         binop(Iop_SarN32x4,
23660                               binop(Iop_MullEven16Sx8,
23661                                     mkexpr(aHi), mkexpr(bHi)),
23662                               mkU8(15))) );
23663
23664      putVReg( vD_addr,
23665               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
23666      break;
23667   }
23668   case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
23669      IRTemp zKonst = newTemp(Ity_V128);
23670      IRTemp cSigns = newTemp(Ity_V128);
23671      DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
23672          vD_addr, vA_addr, vB_addr, vC_addr);
23673      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
23674      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
23675      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
23676      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
23677      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
23678      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
23679      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
23680
23681      /* shifting our const avoids store/load version of Dup */
23682      assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
23683                            mkU8(14)) );
23684
23685      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
23686                         binop(Iop_SarN32x4,
23687                               binop(Iop_Add32x4, mkexpr(zKonst),
23688                                     binop(Iop_MullEven16Sx8,
23689                                           mkexpr(aLo), mkexpr(bLo))),
23690                               mkU8(15))) );
23691
23692      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
23693                         binop(Iop_SarN32x4,
23694                               binop(Iop_Add32x4, mkexpr(zKonst),
23695                                     binop(Iop_MullEven16Sx8,
23696                                           mkexpr(aHi), mkexpr(bHi))),
23697                               mkU8(15))) );
23698
23699      putVReg( vD_addr,
23700               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
23701      break;
23702   }
23703   case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
23704      DIP("vmladduhm v%d,v%d,v%d,v%d\n",
23705          vD_addr, vA_addr, vB_addr, vC_addr);
23706      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
23707      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
23708      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
23709      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
23710      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
23711      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
23712      assign(zLo, binop(Iop_Add32x4,
23713                     binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
23714                     mkexpr(cLo)) );
23715      assign(zHi, binop(Iop_Add32x4,
23716                     binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
23717                     mkexpr(cHi)));
23718      putVReg( vD_addr,
23719               binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
23720      break;
23721   }
23722
23723   case 0x23: { // vmsumudm
23724      DIP("vmsumudm v%d,v%d,v%d,v%d\n",
23725          vD_addr, vA_addr, vB_addr, vC_addr);
23726      /* This instruction takes input vectors VA, VB consisting of 2 usigned
23727         64-bit integer elements and a 128 bit unsigned input U128_C.  The
23728         instruction performs the following operation:
23729
23730            VA[0] * VB[0] -> U128_mul_result0;
23731            VA[1] * VB[1] -> U128_mul_result1;
23732            U128_C + U128_mul_result0 + U128_mul_result1 -> U128_partial_sum;
23733            carry out and overflow is discarded.
23734      */
23735
23736      /* The Iop_MulI128low assumes the upper 64-bits in the two input operands
23737         are zero. */
23738      IRTemp mul_result0 = newTemp( Ity_I128 );
23739      IRTemp mul_result1 = newTemp( Ity_I128 );
23740      IRTemp partial_sum_hi = newTemp( Ity_I64 );
23741      IRTemp partial_sum_low = newTemp( Ity_I64 );
23742      IRTemp result_hi  = newTemp( Ity_I64 );
23743      IRTemp result_low = newTemp( Ity_I64 );
23744      IRExpr *ca_sum, *ca_result;
23745
23746
23747      /* Do multiplications */
23748      assign ( mul_result0, binop( Iop_MullU64,
23749                                   unop( Iop_V128to64, mkexpr( vA ) ),
23750                                   unop( Iop_V128to64, mkexpr( vB) ) ) );
23751
23752      assign ( mul_result1, binop( Iop_MullU64,
23753                                   unop( Iop_V128HIto64, mkexpr( vA ) ),
23754                                   unop( Iop_V128HIto64, mkexpr( vB) ) ) );
23755
23756      /* Add the two 128-bit results using 64-bit unsigned adds, calculate carry
23757         from low 64-bits add into sum of upper 64-bits.  Throw away carry out
23758         of the upper 64-bit sum. */
23759      assign ( partial_sum_low, binop( Iop_Add64,
23760                                       unop( Iop_128to64, mkexpr( mul_result0 ) ),
23761                                       unop( Iop_128to64, mkexpr( mul_result1 ) )
23762                                       ) );
23763
23764      /* ca_sum is type U32 */
23765      ca_sum =  calculate_XER_CA_64 ( PPCG_FLAG_OP_ADD,
23766                                      mkexpr(partial_sum_low ),
23767                                      unop( Iop_128to64, mkexpr( mul_result0 ) ),
23768                                      unop( Iop_128to64, mkexpr( mul_result1 ) ),
23769                                      mkU64( 0 ) );
23770
23771      assign ( partial_sum_hi,
23772               binop( Iop_Add64,
23773                      binop( Iop_Add64,
23774                             unop( Iop_128HIto64, mkexpr( mul_result0 ) ),
23775                             unop( Iop_128HIto64, mkexpr( mul_result1 ) ) ),
23776                      binop( Iop_32HLto64, mkU32( 0 ), ca_sum ) ) );
23777
23778      /* Now add in the value of C */
23779      assign ( result_low, binop( Iop_Add64,
23780                                  mkexpr( partial_sum_low ),
23781                                  unop( Iop_V128to64, mkexpr( vC ) ) ) );
23782
23783      /* ca_result is type U32 */
23784      ca_result =  calculate_XER_CA_64(  PPCG_FLAG_OP_ADD,
23785                                         mkexpr( result_low ),
23786                                         mkexpr( partial_sum_low ),
23787                                         unop( Iop_V128to64,
23788                                               mkexpr( vC ) ),
23789                                         mkU64( 0 ) );
23790
23791      assign ( result_hi,
23792               binop( Iop_Add64,
23793                      binop( Iop_Add64,
23794                             mkexpr( partial_sum_hi ),
23795                             unop( Iop_V128HIto64, mkexpr( vC ) ) ),
23796                      binop( Iop_32HLto64, mkU32( 0 ), ca_result ) ) );
23797
23798      putVReg( vD_addr, binop( Iop_64HLtoV128,
23799                               mkexpr( result_hi ), mkexpr ( result_low ) ) );
23800      break;
23801   }
23802
23803   /* Multiply-Sum */
23804   case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
23805      IRTemp abEE, abEO, abOE, abOO;
23806      abEE = abEO = abOE = abOO = IRTemp_INVALID;
23807      DIP("vmsumubm v%d,v%d,v%d,v%d\n",
23808          vD_addr, vA_addr, vB_addr, vC_addr);
23809
23810      /* multiply vA,vB (unsigned, widening) */
23811      assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
23812      assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
23813
23814      /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
23815      expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
23816      expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
23817
23818      putVReg( vD_addr,
23819         binop(Iop_Add32x4, mkexpr(vC),
23820               binop(Iop_Add32x4,
23821                     binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
23822                     binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
23823      break;
23824   }
23825   case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
23826      IRTemp aEvn, aOdd, bEvn, bOdd;
23827      IRTemp abEE = newTemp(Ity_V128);
23828      IRTemp abEO = newTemp(Ity_V128);
23829      IRTemp abOE = newTemp(Ity_V128);
23830      IRTemp abOO = newTemp(Ity_V128);
23831      aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
23832      DIP("vmsummbm v%d,v%d,v%d,v%d\n",
23833          vD_addr, vA_addr, vB_addr, vC_addr);
23834
23835      /* sign-extend vA, zero-extend vB, for mixed-sign multiply
23836         (separating out adjacent lanes to different vectors) */
23837      expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
23838      expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
23839
23840      /* multiply vA, vB, again separating adjacent lanes */
23841      assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
23842      assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
23843      assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
23844      assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
23845
23846      /* add results together, + vC */
23847      putVReg( vD_addr,
23848         binop(Iop_QAdd32Sx4, mkexpr(vC),
23849               binop(Iop_QAdd32Sx4,
23850                     binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
23851                     binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
23852      break;
23853   }
23854   case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
23855      DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
23856          vD_addr, vA_addr, vB_addr, vC_addr);
23857      assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
23858      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
23859      putVReg( vD_addr,
23860         binop(Iop_Add32x4, mkexpr(vC),
23861               binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
23862      break;
23863   }
23864   case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
23865      DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
23866          vD_addr, vA_addr, vB_addr, vC_addr);
23867      /* widening multiply, separating lanes */
23868      assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
23869      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
23870
23871      /* break V128 to 4xI32's, zero-extending to I64's */
23872      breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
23873      breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
23874      breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
23875
23876      /* add lanes */
23877      assign( z3, binop(Iop_Add64, mkexpr(c3),
23878                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
23879      assign( z2, binop(Iop_Add64, mkexpr(c2),
23880                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
23881      assign( z1, binop(Iop_Add64, mkexpr(c1),
23882                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
23883      assign( z0, binop(Iop_Add64, mkexpr(c0),
23884                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
23885
23886      /* saturate-narrow to 32bit, and combine to V128 */
23887      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
23888                                         mkexpr(z1), mkexpr(z0)) );
23889
23890      break;
23891   }
23892   case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
23893      DIP("vmsumshm v%d,v%d,v%d,v%d\n",
23894          vD_addr, vA_addr, vB_addr, vC_addr);
23895      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
23896      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
23897      putVReg( vD_addr,
23898         binop(Iop_Add32x4, mkexpr(vC),
23899               binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
23900      break;
23901   }
23902   case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
23903      DIP("vmsumshs v%d,v%d,v%d,v%d\n",
23904          vD_addr, vA_addr, vB_addr, vC_addr);
23905      /* widening multiply, separating lanes */
23906      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
23907      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
23908
23909      /* break V128 to 4xI32's, sign-extending to I64's */
23910      breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
23911      breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
23912      breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
23913
23914      /* add lanes */
23915      assign( z3, binop(Iop_Add64, mkexpr(c3),
23916                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
23917      assign( z2, binop(Iop_Add64, mkexpr(c2),
23918                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
23919      assign( z1, binop(Iop_Add64, mkexpr(c1),
23920                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
23921      assign( z0, binop(Iop_Add64, mkexpr(c0),
23922                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
23923
23924      /* saturate-narrow to 32bit, and combine to V128 */
23925      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
23926                                         mkexpr(z1), mkexpr(z0)) );
23927      break;
23928   }
23929   default:
23930      vex_printf("dis_av_multarith(ppc)(opc2)\n");
23931      return False;
23932   }
23933   return True;
23934}
23935
23936/*
23937  AltiVec Polynomial Multiply-Sum Instructions
23938*/
23939static Bool dis_av_polymultarith ( UInt theInstr )
23940{
23941   /* VA-Form */
23942   UChar opc1     = ifieldOPC(theInstr);
23943   UChar vD_addr  = ifieldRegDS(theInstr);
23944   UChar vA_addr  = ifieldRegA(theInstr);
23945   UChar vB_addr  = ifieldRegB(theInstr);
23946   UChar vC_addr  = ifieldRegC(theInstr);
23947   UInt  opc2     = IFIELD(theInstr, 0, 11);
23948   IRTemp vA    = newTemp(Ity_V128);
23949   IRTemp vB    = newTemp(Ity_V128);
23950   IRTemp vC    = newTemp(Ity_V128);
23951
23952   assign( vA, getVReg(vA_addr));
23953   assign( vB, getVReg(vB_addr));
23954   assign( vC, getVReg(vC_addr));
23955
23956   if (opc1 != 0x4) {
23957      vex_printf("dis_av_polymultarith(ppc)(instr)\n");
23958      return False;
23959   }
23960
23961   switch (opc2) {
23962      /* Polynomial Multiply-Add */
23963      case 0x408:  // vpmsumb   Vector Polynomial Multiply-sum Byte
23964         DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23965         putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
23966                                 mkexpr(vA), mkexpr(vB)) );
23967         break;
23968      case 0x448:  // vpmsumd   Vector Polynomial Multiply-sum Double Word
23969         DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23970         putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
23971                                 mkexpr(vA), mkexpr(vB)) );
23972         break;
23973      case 0x488:  // vpmsumw   Vector Polynomial Multiply-sum Word
23974         DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23975         putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
23976                                 mkexpr(vA), mkexpr(vB)) );
23977         break;
23978      case 0x4C8:  // vpmsumh   Vector Polynomial Multiply-sum Half Word
23979         DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23980         putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
23981                                 mkexpr(vA), mkexpr(vB)) );
23982         break;
23983      default:
23984         vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
23985         return False;
23986   }
23987   return True;
23988}
23989
23990/*
23991  AltiVec Shift/Rotate Instructions
23992*/
23993static Bool dis_av_shift ( UInt theInstr )
23994{
23995   /* VX-Form */
23996   UChar opc1    = ifieldOPC(theInstr);
23997   UChar vD_addr = ifieldRegDS(theInstr);
23998   UChar vA_addr = ifieldRegA(theInstr);
23999   UChar vB_addr = ifieldRegB(theInstr);
24000   UInt  opc2    = IFIELD( theInstr, 0, 11 );
24001
24002   IRTemp vA = newTemp(Ity_V128);
24003   IRTemp vB = newTemp(Ity_V128);
24004   assign( vA, getVReg(vA_addr));
24005   assign( vB, getVReg(vB_addr));
24006
24007   if (opc1 != 0x4){
24008      vex_printf("dis_av_shift(ppc)(instr)\n");
24009      return False;
24010   }
24011
24012   switch (opc2) {
24013   /* Rotate */
24014   case 0x004: // vrlb (Rotate Left Integer B, AV p234)
24015      DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24016      putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
24017      break;
24018
24019   case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
24020      DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24021      putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
24022      break;
24023
24024   case 0x084: // vrlw (Rotate Left Integer W, AV p236)
24025      DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24026      putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
24027      break;
24028
24029   case 0x0C4: // vrld (Rotate Left Integer Double Word)
24030      DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24031      putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
24032      break;
24033
24034
24035   /* Shift Left */
24036   case 0x104: // vslb (Shift Left Integer B, AV p240)
24037      DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24038      putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
24039      break;
24040
24041   case 0x144: // vslh (Shift Left Integer HW, AV p242)
24042      DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24043      putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
24044      break;
24045
24046   case 0x184: // vslw (Shift Left Integer W, AV p244)
24047      DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24048      putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
24049      break;
24050
24051   case 0x5C4: // vsld (Shift Left Integer Double Word)
24052      DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24053      putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
24054      break;
24055
24056   case 0x1C4: { // vsl (Shift Left, AV p239)
24057      IRTemp sh = newTemp(Ity_I8);
24058      DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24059      assign( sh, binop(Iop_And8, mkU8(0x7),
24060                        unop(Iop_32to8,
24061                             unop(Iop_V128to32, mkexpr(vB)))) );
24062      putVReg( vD_addr,
24063               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
24064      break;
24065   }
24066   case 0x40C: { // vslo (Shift Left by Octet, AV p243)
24067      IRTemp sh = newTemp(Ity_I8);
24068      DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24069      assign( sh, binop(Iop_And8, mkU8(0x78),
24070                        unop(Iop_32to8,
24071                             unop(Iop_V128to32, mkexpr(vB)))) );
24072      putVReg( vD_addr,
24073               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
24074      break;
24075   }
24076
24077
24078   /* Shift Right */
24079   case 0x204: // vsrb (Shift Right B, AV p256)
24080      DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24081      putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
24082      break;
24083
24084   case 0x244: // vsrh (Shift Right HW, AV p257)
24085      DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24086      putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
24087      break;
24088
24089   case 0x284: // vsrw (Shift Right W, AV p259)
24090      DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24091      putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
24092      break;
24093
24094   case 0x2C4: { // vsr (Shift Right, AV p251)
24095      IRTemp sh = newTemp(Ity_I8);
24096      DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24097      assign( sh, binop(Iop_And8, mkU8(0x7),
24098                        unop(Iop_32to8,
24099                             unop(Iop_V128to32, mkexpr(vB)))) );
24100      putVReg( vD_addr,
24101               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
24102      break;
24103   }
24104   case 0x304: // vsrab (Shift Right Alg B, AV p253)
24105      DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24106      putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
24107      break;
24108
24109   case 0x344: // vsrah (Shift Right Alg HW, AV p254)
24110      DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24111      putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
24112      break;
24113
24114   case 0x384: // vsraw (Shift Right Alg W, AV p255)
24115      DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24116      putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
24117      break;
24118
24119   case 0x3C4: // vsrad (Shift Right Alg Double Word)
24120      DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24121      putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
24122      break;
24123
24124   case 0x44C: { // vsro (Shift Right by Octet, AV p258)
24125      IRTemp sh = newTemp(Ity_I8);
24126      DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24127      assign( sh, binop(Iop_And8, mkU8(0x78),
24128                        unop(Iop_32to8,
24129                             unop(Iop_V128to32, mkexpr(vB)))) );
24130      putVReg( vD_addr,
24131               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
24132      break;
24133   }
24134
24135   case 0x6C4: // vsrd (Shift Right Double Word)
24136      DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24137      putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
24138      break;
24139
24140
24141   default:
24142      vex_printf("dis_av_shift(ppc)(opc2)\n");
24143      return False;
24144   }
24145   return True;
24146}
24147
24148/*
24149  AltiVec Permute Instructions
24150*/
24151static Bool dis_av_permute ( UInt theInstr )
24152{
24153   /* VA-Form, VX-Form */
24154   UChar opc1      = ifieldOPC(theInstr);
24155   UChar vD_addr   = ifieldRegDS(theInstr);
24156   UChar vA_addr   = ifieldRegA(theInstr);
24157   UChar UIMM_5    = vA_addr;
24158   UChar vB_addr   = ifieldRegB(theInstr);
24159   UChar vC_addr   = ifieldRegC(theInstr);
24160   UChar b10       = ifieldBIT10(theInstr);
24161   UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
24162   UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
24163
24164   UChar SIMM_8 = extend_s_5to8(UIMM_5);
24165
24166   IRTemp vA = newTemp(Ity_V128);
24167   IRTemp vB = newTemp(Ity_V128);
24168   IRTemp vC = newTemp(Ity_V128);
24169   assign( vA, getVReg(vA_addr));
24170   assign( vB, getVReg(vB_addr));
24171   assign( vC, getVReg(vC_addr));
24172
24173   if (opc1 != 0x4) {
24174      vex_printf("dis_av_permute(ppc)(instr)\n");
24175      return False;
24176   }
24177
24178   switch (opc2) {
24179   case 0x2A: // vsel (Conditional Select, AV p238)
24180      DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
24181      /* vD = (vA & ~vC) | (vB & vC) */
24182      putVReg( vD_addr, binop(Iop_OrV128,
24183         binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
24184         binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
24185      return True;
24186
24187   case 0x2B: { // vperm (Permute, AV p218)
24188      /* limited to two args for IR, so have to play games... */
24189      IRTemp a_perm  = newTemp(Ity_V128);
24190      IRTemp b_perm  = newTemp(Ity_V128);
24191      IRTemp mask    = newTemp(Ity_V128);
24192      IRTemp vC_andF = newTemp(Ity_V128);
24193      DIP("vperm v%d,v%d,v%d,v%d\n",
24194          vD_addr, vA_addr, vB_addr, vC_addr);
24195      /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
24196         IR specifies, and also to hide irrelevant bits from
24197         memcheck */
24198      assign( vC_andF,
24199              binop(Iop_AndV128, mkexpr(vC),
24200                                 unop(Iop_Dup8x16, mkU8(0xF))) );
24201      assign( a_perm,
24202              binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
24203      assign( b_perm,
24204              binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
24205      // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
24206      assign( mask, binop(Iop_SarN8x16,
24207                          binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
24208                          mkU8(7)) );
24209      // dst = (a & ~mask) | (b & mask)
24210      putVReg( vD_addr, binop(Iop_OrV128,
24211                              binop(Iop_AndV128, mkexpr(a_perm),
24212                                    unop(Iop_NotV128, mkexpr(mask))),
24213                              binop(Iop_AndV128, mkexpr(b_perm),
24214                                    mkexpr(mask))) );
24215      return True;
24216   }
24217   case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
24218      if (b10 != 0) {
24219         vex_printf("dis_av_permute(ppc)(vsldoi)\n");
24220         return False;
24221      }
24222      DIP("vsldoi v%d,v%d,v%d,%d\n",
24223          vD_addr, vA_addr, vB_addr, SHB_uimm4);
24224      if (SHB_uimm4 == 0)
24225         putVReg( vD_addr, mkexpr(vA) );
24226      else
24227         putVReg( vD_addr,
24228            binop(Iop_OrV128,
24229                  binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
24230                  binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
24231      return True;
24232   case 0x2D: {  // vpermxor (Vector Permute and Exclusive-OR)
24233      IRTemp a_perm  = newTemp(Ity_V128);
24234      IRTemp b_perm  = newTemp(Ity_V128);
24235      IRTemp vrc_a   = newTemp(Ity_V128);
24236      IRTemp vrc_b   = newTemp(Ity_V128);
24237
24238      DIP("vpermxor v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
24239
24240      /* IBM index  is 0:7, Change index value to index 7:0 */
24241      assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
24242                            unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
24243      assign( vrc_a, binop( Iop_ShrV128,
24244                            binop( Iop_AndV128, mkexpr( vC ),
24245                                   unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
24246                            mkU8 ( 4 ) ) );
24247      assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
24248      assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
24249      putVReg( vD_addr, binop( Iop_XorV128,
24250                               mkexpr( a_perm ), mkexpr( b_perm) ) );
24251      return True;
24252   }
24253
24254   case 0x3B: {  // vpermr (Vector Permute Right-indexed)
24255      int i;
24256      IRTemp new_Vt[17];
24257      IRTemp tmp[16];
24258      IRTemp index[16];
24259      IRTemp index_gt16[16];
24260      IRTemp mask[16];
24261
24262      DIP("vpermr v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
24263
24264      new_Vt[0] = newTemp( Ity_V128 );
24265      assign( new_Vt[0], binop( Iop_64HLtoV128,
24266                                mkU64( 0x0 ),
24267                                mkU64( 0x0 ) ) );
24268
24269      for ( i = 0; i < 16; i++ ) {
24270         index_gt16[i] = newTemp( Ity_V128 );
24271         mask[i]  = newTemp( Ity_V128 );
24272         index[i] = newTemp( Ity_I32 );
24273         tmp[i]   = newTemp( Ity_V128 );
24274         new_Vt[i+1] = newTemp( Ity_V128 );
24275
24276         assign( index[i],
24277                 binop( Iop_Sub32,
24278                        mkU32( 31 ),
24279                        unop( Iop_64to32,
24280                              unop( Iop_V128to64,
24281                                    binop( Iop_ShrV128,
24282                                           binop( Iop_AndV128,
24283                                                  binop( Iop_ShlV128,
24284                                                         binop( Iop_64HLtoV128,
24285                                                                mkU64( 0x0 ),
24286                                                                mkU64( 0x3F ) ),
24287                                                         mkU8(  (15 - i) * 8 ) ),
24288                                                  mkexpr( vC ) ),
24289                                           mkU8( (15 - i) * 8 ) ) ) ) ) );
24290
24291         /* Determine if index < 16, src byte is vA[index], otherwise
24292          * vB[31-index]. Check if msb of index is 1 or not.
24293          */
24294         assign( index_gt16[i],
24295                 binop( Iop_64HLtoV128,
24296                        unop( Iop_1Sto64,
24297                              unop( Iop_32to1,
24298                                    binop( Iop_Shr32,
24299                                           mkexpr( index[i] ),
24300                                           mkU8( 4 ) ) ) ),
24301                        unop( Iop_1Sto64,
24302                              unop( Iop_32to1,
24303                                    binop( Iop_Shr32,
24304                                           mkexpr( index[i] ),
24305                                           mkU8( 4 ) ) ) ) ) );
24306         assign( mask[i],
24307                 binop( Iop_ShlV128,
24308                        binop( Iop_64HLtoV128,
24309                               mkU64( 0x0 ),
24310                               mkU64( 0xFF ) ),
24311                        unop( Iop_32to8,
24312                              binop( Iop_Mul32,
24313                                     binop( Iop_Sub32,
24314                                            mkU32( 15 ),
24315                                            binop( Iop_And32,
24316                                                   mkexpr( index[i] ),
24317                                                   mkU32( 0xF ) ) ),
24318                                     mkU32( 8 ) ) ) ) );
24319
24320         /* Extract the indexed byte from vA and vB using the lower 4-bits
24321          * of the index. Then use the index_gt16 mask to select vA if the
24322          * index < 16 or vB if index > 15.  Put the selected byte in the
24323          * least significant byte.
24324          */
24325         assign( tmp[i],
24326                 binop( Iop_ShrV128,
24327                        binop( Iop_OrV128,
24328                               binop( Iop_AndV128,
24329                                      binop( Iop_AndV128,
24330                                             mkexpr( mask[i] ),
24331                                             mkexpr( vA ) ),
24332                                      unop( Iop_NotV128,
24333                                            mkexpr( index_gt16[i] ) ) ),
24334                               binop( Iop_AndV128,
24335                                      binop( Iop_AndV128,
24336                                             mkexpr( mask[i] ),
24337                                             mkexpr( vB ) ),
24338                                      mkexpr( index_gt16[i] ) ) ),
24339                        unop( Iop_32to8,
24340                              binop( Iop_Mul32,
24341                                     binop( Iop_Sub32,
24342                                            mkU32( 15 ),
24343                                            binop( Iop_And32,
24344                                                   mkexpr( index[i] ),
24345                                                   mkU32( 0xF ) ) ),
24346                                     mkU32( 8 ) ) ) ) );
24347
24348         /* Move the selected byte to the position to store in the result */
24349         assign( new_Vt[i+1], binop( Iop_OrV128,
24350                                     binop( Iop_ShlV128,
24351                                            mkexpr( tmp[i] ),
24352                                            mkU8(  (15 - i) * 8 ) ),
24353                                     mkexpr( new_Vt[i] ) ) );
24354         }
24355      putVReg( vD_addr, mkexpr( new_Vt[16] ) );
24356      return True;
24357   }
24358
24359   default:
24360     break; // Fall through...
24361   }
24362
24363   opc2 = IFIELD( theInstr, 0, 11 );
24364   switch (opc2) {
24365
24366   /* Merge */
24367   case 0x00C: // vmrghb (Merge High B, AV p195)
24368      DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24369      putVReg( vD_addr,
24370               binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
24371      break;
24372
24373   case 0x04C: // vmrghh (Merge High HW, AV p196)
24374      DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24375      putVReg( vD_addr,
24376               binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
24377      break;
24378
24379   case 0x08C: // vmrghw (Merge High W, AV p197)
24380      DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24381      putVReg( vD_addr,
24382               binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
24383      break;
24384
24385   case 0x10C: // vmrglb (Merge Low B, AV p198)
24386      DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24387      putVReg( vD_addr,
24388               binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
24389      break;
24390
24391   case 0x14C: // vmrglh (Merge Low HW, AV p199)
24392      DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24393      putVReg( vD_addr,
24394               binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
24395      break;
24396
24397   case 0x18C: // vmrglw (Merge Low W, AV p200)
24398      DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24399      putVReg( vD_addr,
24400               binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
24401      break;
24402
24403   /* Extract instructions */
24404   case 0x20D: // vextractub  (Vector Extract Unsigned Byte)
24405   {
24406      UChar uim = IFIELD( theInstr, 16, 4 );
24407
24408      DIP("vextractub v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24409
24410      putVReg( vD_addr, binop( Iop_ShlV128,
24411                               binop( Iop_AndV128,
24412                                      binop( Iop_ShrV128,
24413                                             mkexpr( vB ),
24414                                             unop( Iop_32to8,
24415                                                   binop( Iop_Mul32,
24416                                                          mkU32( 8 ),
24417                                                          mkU32( 31 - uim ) ) ) ),
24418                                      binop( Iop_64HLtoV128,
24419                                             mkU64( 0x0ULL ),
24420                                             mkU64( 0xFFULL ) ) ),
24421                               mkU8( 64 ) ) );
24422   }
24423   break;
24424
24425   case 0x24D: // vextractuh  (Vector Extract Unsigned Halfword)
24426   {
24427      UChar uim = IFIELD( theInstr, 16, 4 );
24428
24429      DIP("vextractuh v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24430
24431      putVReg( vD_addr, binop( Iop_ShlV128,
24432                               binop( Iop_AndV128,
24433                                      binop( Iop_ShrV128,
24434                                             mkexpr( vB ),
24435                                             unop( Iop_32to8,
24436                                                   binop( Iop_Mul32,
24437                                                          mkU32( 8 ),
24438                                                          mkU32( 30 - uim ) ) ) ),
24439                                      binop( Iop_64HLtoV128,
24440                                             mkU64( 0x0ULL ),
24441                                             mkU64( 0xFFFFULL ) ) ),
24442                               mkU8( 64 ) ) );
24443   }
24444   break;
24445
24446   case 0x28D: // vextractuw  (Vector Extract Unsigned Word)
24447   {
24448      UChar uim = IFIELD( theInstr, 16, 4 );
24449
24450      DIP("vextractuw v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24451
24452      putVReg( vD_addr,
24453               binop( Iop_ShlV128,
24454                      binop( Iop_AndV128,
24455                             binop( Iop_ShrV128,
24456                                    mkexpr( vB ),
24457                                    unop( Iop_32to8,
24458                                          binop( Iop_Mul32,
24459                                                 mkU32( 8 ),
24460                                                 mkU32( 28 - uim ) ) ) ),
24461                             binop( Iop_64HLtoV128,
24462                                    mkU64( 0x0ULL ),
24463                                    mkU64( 0xFFFFFFFFULL ) ) ),
24464                      mkU8( 64 ) ) );
24465   }
24466   break;
24467
24468   case 0x2CD: // vextractd  (Vector Extract Double Word)
24469   {
24470      UChar uim = IFIELD( theInstr, 16, 4 );
24471
24472      DIP("vextractd v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24473
24474      putVReg( vD_addr,
24475               binop( Iop_ShlV128,
24476                      binop( Iop_AndV128,
24477                             binop( Iop_ShrV128,
24478                                    mkexpr( vB ),
24479                                    unop( Iop_32to8,
24480                                          binop( Iop_Mul32,
24481                                                 mkU32( 8 ),
24482                                                 mkU32( 24 - uim ) ) ) ),
24483                             binop( Iop_64HLtoV128,
24484                                    mkU64( 0x0ULL ),
24485                                    mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) ),
24486                      mkU8( 64 ) ) );
24487   }
24488   break;
24489
24490   /* Insert instructions */
24491   case 0x30D:  // vinsertb  (Vector insert Unsigned Byte)
24492   {
24493      UChar uim = IFIELD( theInstr, 16, 4 );
24494      IRTemp shift = newTemp( Ity_I8 );
24495      IRTemp vD = newTemp( Ity_V128 );
24496
24497      DIP("vinsertb v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24498
24499      assign( vD, getVReg( vD_addr ) );
24500
24501      assign( shift, unop( Iop_32to8,
24502                           binop( Iop_Mul32,
24503                                  mkU32( 8 ),
24504                                  mkU32( 15 - ( uim + 0 ) ) ) ) );
24505
24506      putVReg( vD_addr,
24507               binop( Iop_OrV128,
24508                      binop( Iop_ShlV128,
24509                             binop( Iop_AndV128,
24510                                    binop( Iop_ShrV128,
24511                                           mkexpr( vB ),
24512                                           mkU8( ( 15 - 7 )*8 ) ),
24513                                    binop( Iop_64HLtoV128,
24514                                           mkU64( 0x0ULL ),
24515                                           mkU64( 0xFFULL ) ) ),
24516                             mkexpr( shift ) ),
24517                      binop( Iop_AndV128,
24518                             unop( Iop_NotV128,
24519                                   binop( Iop_ShlV128,
24520                                          binop( Iop_64HLtoV128,
24521                                                 mkU64( 0x0ULL ),
24522                                                 mkU64( 0xFFULL ) ),
24523                                          mkexpr( shift ) ) ),
24524                             mkexpr( vD ) ) ) );
24525   }
24526   break;
24527
24528   case 0x34D: // vinserth  (Vector insert Halfword)
24529   {
24530      UChar uim = IFIELD( theInstr, 16, 4 );
24531      IRTemp shift = newTemp( Ity_I8 );
24532      IRTemp vD = newTemp( Ity_V128 );
24533
24534      DIP("vinserth v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24535
24536      assign( vD, getVReg( vD_addr ) );
24537
24538      assign( shift, unop( Iop_32to8,
24539                           binop( Iop_Mul32,
24540                                  mkU32( 8 ),
24541                                  mkU32( 15 - ( uim + 1 ) ) ) ) );
24542
24543      putVReg( vD_addr,
24544               binop( Iop_OrV128,
24545                      binop( Iop_ShlV128,
24546                             binop( Iop_AndV128,
24547                                    binop( Iop_ShrV128,
24548                                           mkexpr( vB ),
24549                                           mkU8( (7 - 3)*16 ) ),
24550                                    binop( Iop_64HLtoV128,
24551                                           mkU64( 0x0ULL ),
24552                                           mkU64( 0xFFFFULL ) ) ),
24553                             mkexpr( shift ) ),
24554                      binop( Iop_AndV128,
24555                             unop( Iop_NotV128,
24556                                   binop( Iop_ShlV128,
24557                                          binop( Iop_64HLtoV128,
24558                                                 mkU64( 0x0ULL ),
24559                                                 mkU64( 0xFFFFULL ) ),
24560                                          mkexpr( shift ) ) ),
24561                             mkexpr( vD ) ) ) );
24562   }
24563   break;
24564
24565   case 0x38D: // vinsertw  (Vector insert Word)
24566   {
24567      UChar uim = IFIELD( theInstr, 16, 4 );
24568      IRTemp shift = newTemp( Ity_I8 );
24569      IRTemp vD = newTemp( Ity_V128 );
24570
24571      DIP("vinsertw v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24572
24573      assign( vD, getVReg( vD_addr ) );
24574
24575      assign( shift, unop( Iop_32to8,
24576                           binop( Iop_Mul32,
24577                                  mkU32( 8 ),
24578                                  mkU32( 15 - ( uim + 3 ) ) ) ) );
24579
24580      putVReg( vD_addr,
24581               binop( Iop_OrV128,
24582                      binop( Iop_ShlV128,
24583                             binop( Iop_AndV128,
24584                                    binop( Iop_ShrV128,
24585                                           mkexpr( vB ),
24586                                           mkU8( (3 - 1) * 32 ) ),
24587                                    binop( Iop_64HLtoV128,
24588                                           mkU64( 0x0ULL ),
24589                                           mkU64( 0xFFFFFFFFULL ) ) ),
24590                             mkexpr( shift ) ),
24591                      binop( Iop_AndV128,
24592                             unop( Iop_NotV128,
24593                                   binop( Iop_ShlV128,
24594                                          binop( Iop_64HLtoV128,
24595                                                 mkU64( 0x0ULL ),
24596                                                 mkU64( 0xFFFFFFFFULL ) ),
24597                                          mkexpr( shift ) ) ),
24598                             mkexpr( vD ) ) ) );
24599   }
24600   break;
24601
24602   case 0x3CD: // vinsertd  (Vector insert Doubleword)
24603   {
24604      UChar uim = IFIELD( theInstr, 16, 4 );
24605      IRTemp shift = newTemp( Ity_I8 );
24606      IRTemp vD = newTemp( Ity_V128 );
24607
24608      DIP("vinsertd v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24609
24610      assign( vD, getVReg( vD_addr ) );
24611
24612      assign( shift, unop( Iop_32to8,
24613                           binop( Iop_Mul32,
24614                                  mkU32( 8 ),
24615                                  mkU32( 15 - ( uim + 7 ) ) ) ) );
24616
24617      putVReg( vD_addr,
24618               binop( Iop_OrV128,
24619                      binop( Iop_ShlV128,
24620                             binop( Iop_AndV128,
24621                                    binop( Iop_ShrV128,
24622                                           mkexpr( vB ),
24623                                           mkU8( ( 1 - 0 ) * 64 ) ),
24624                                    binop( Iop_64HLtoV128,
24625                                           mkU64( 0x0ULL ),
24626                                           mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) ),
24627                             mkexpr( shift ) ),
24628                      binop( Iop_AndV128,
24629                             unop( Iop_NotV128,
24630                                   binop( Iop_ShlV128,
24631                                          binop( Iop_64HLtoV128,
24632                                                 mkU64( 0x0ULL ),
24633                                                 mkU64( 0xFFFFFFFFFFFFFFFFULL ) ),
24634                                          mkexpr( shift ) ) ),
24635                             mkexpr( vD ) ) ) );
24636   }
24637   break;
24638
24639   /* Splat */
24640   case 0x20C: { // vspltb (Splat Byte, AV p245)
24641      /* vD = Dup8x16( vB[UIMM_5] ) */
24642      UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
24643      DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
24644      putVReg( vD_addr, unop(Iop_Dup8x16,
24645           unop(Iop_32to8, unop(Iop_V128to32,
24646                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
24647      break;
24648   }
24649   case 0x24C: { // vsplth (Splat Half Word, AV p246)
24650      UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
24651      DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
24652      putVReg( vD_addr, unop(Iop_Dup16x8,
24653           unop(Iop_32to16, unop(Iop_V128to32,
24654                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
24655      break;
24656   }
24657   case 0x28C: { // vspltw (Splat Word, AV p250)
24658      /* vD = Dup32x4( vB[UIMM_5] ) */
24659      UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
24660      DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
24661      putVReg( vD_addr, unop(Iop_Dup32x4,
24662         unop(Iop_V128to32,
24663              binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
24664      break;
24665   }
24666   case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
24667      DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
24668      putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
24669      break;
24670
24671   case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
24672      DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
24673      putVReg( vD_addr,
24674               unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
24675      break;
24676
24677   case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
24678      DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
24679      putVReg( vD_addr,
24680               unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
24681      break;
24682
24683   case 0x68C: // vmrgow (Merge Odd Word)
24684     DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24685      /*   VD[0] <- VA[1]
24686           VD[1] <- VB[1]
24687           VD[2] <- VA[3]
24688           VD[3] <- VB[3]
24689      */
24690      putVReg( vD_addr,
24691               binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
24692      break;
24693
24694   case 0x78C: // vmrgew (Merge Even Word)
24695      DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24696      /*   VD[0] <- VA[0]
24697           VD[1] <- VB[0]
24698           VD[2] <- VA[2]
24699           VD[3] <- VB[2]
24700      */
24701      putVReg( vD_addr,
24702               binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
24703      break;
24704
24705   default:
24706      vex_printf("dis_av_permute(ppc)(opc2)\n");
24707      return False;
24708   }
24709   return True;
24710}
24711
24712/*
24713  Vector Integer Absolute Difference
24714*/
24715static Bool dis_abs_diff ( UInt theInstr )
24716{
24717   /* VX-Form */
24718   UChar opc1     = ifieldOPC( theInstr );
24719   UChar vT_addr  = ifieldRegDS( theInstr );
24720   UChar vA_addr  = ifieldRegA( theInstr );
24721   UChar vB_addr  = ifieldRegB( theInstr );
24722   UInt  opc2     = IFIELD( theInstr, 0, 11 );
24723
24724   IRTemp vA    = newTemp( Ity_V128 );
24725   IRTemp vB    = newTemp( Ity_V128 );
24726   IRTemp vT    = newTemp( Ity_V128 );
24727
24728   IRTemp vAminusB = newTemp( Ity_V128 );
24729   IRTemp vBminusA = newTemp( Ity_V128 );
24730   IRTemp vMask    = newTemp( Ity_V128 );
24731
24732   assign( vA, getVReg( vA_addr ) );
24733   assign( vB, getVReg( vB_addr ) );
24734
24735   if ( opc1 != 0x4 ) {
24736      vex_printf("dis_abs_diff(ppc)(instr)\n");
24737      return False;
24738   }
24739
24740   switch ( opc2 ) {
24741   case 0x403: // vabsdub  Vector absolute difference Unsigned Byte
24742   {
24743      DIP("vabsdub v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
24744
24745      /* Determine which of the corresponding bytes is larger,
24746       * create mask with 1's in byte positions where vA[i] > vB[i]
24747       */
24748      assign( vMask, binop( Iop_CmpGT8Ux16, mkexpr( vA ), mkexpr( vB ) ) );
24749
24750      assign( vAminusB,
24751              binop( Iop_AndV128,
24752                     binop( Iop_Sub8x16, mkexpr( vA ), mkexpr( vB ) ),
24753                     mkexpr( vMask ) ) );
24754
24755      assign( vBminusA,
24756              binop( Iop_AndV128,
24757                     binop( Iop_Sub8x16, mkexpr( vB ), mkexpr( vA ) ),
24758                     unop ( Iop_NotV128, mkexpr( vMask ) ) ) );
24759
24760      assign( vT, binop( Iop_OrV128,
24761                         mkexpr( vAminusB ),
24762                         mkexpr( vBminusA ) ) );
24763   }
24764   break;
24765
24766   case 0x443: // vabsduh  Vector absolute difference Unsigned Halfword
24767   {
24768      DIP("vabsduh v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
24769
24770      /* Determine which of the corresponding halfwords is larger,
24771       * create mask with 1's in halfword positions where vA[i] > vB[i]
24772       */
24773      assign( vMask, binop( Iop_CmpGT16Ux8, mkexpr( vA ), mkexpr( vB ) ) );
24774
24775      assign( vAminusB,
24776              binop( Iop_AndV128,
24777                     binop( Iop_Sub16x8, mkexpr( vA ), mkexpr( vB ) ),
24778                     mkexpr( vMask ) ) );
24779
24780      assign( vBminusA,
24781              binop( Iop_AndV128,
24782                     binop( Iop_Sub16x8, mkexpr( vB ), mkexpr( vA ) ),
24783                     unop ( Iop_NotV128, mkexpr( vMask ) ) ) );
24784
24785      assign( vT, binop( Iop_OrV128,
24786                         mkexpr( vAminusB ),
24787                         mkexpr( vBminusA ) ) );
24788   }
24789   break;
24790
24791   case 0x483: // vabsduw  Vector absolute difference Unsigned Word
24792   {
24793         DIP("vabsduw v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
24794
24795         /* Determine which of the corresponding words is larger,
24796          * create mask with 1's in word positions where vA[i] > vB[i]
24797          */
24798         assign( vMask, binop( Iop_CmpGT32Ux4, mkexpr( vA ), mkexpr( vB ) ) );
24799
24800         assign( vAminusB,
24801                 binop( Iop_AndV128,
24802                        binop( Iop_Sub32x4, mkexpr( vA ), mkexpr( vB ) ),
24803                        mkexpr( vMask ) ) );
24804
24805         assign( vBminusA,
24806                 binop( Iop_AndV128,
24807                        binop( Iop_Sub32x4, mkexpr( vB ), mkexpr( vA ) ),
24808                        unop ( Iop_NotV128, mkexpr( vMask ) ) ) );
24809
24810         assign( vT, binop( Iop_OrV128,
24811                            mkexpr( vAminusB ),
24812                            mkexpr( vBminusA ) ) );
24813   }
24814   break;
24815
24816   default:
24817      return False;
24818   }
24819
24820   putVReg( vT_addr, mkexpr( vT ) );
24821
24822  return True;
24823}
24824
24825/*
24826  AltiVec 128 bit integer multiply by 10 Instructions
24827*/
24828static Bool dis_av_mult10 ( UInt theInstr )
24829{
24830   /* VX-Form */
24831   UChar opc1     = ifieldOPC(theInstr);
24832   UChar vT_addr  = ifieldRegDS(theInstr);
24833   UChar vA_addr  = ifieldRegA(theInstr);
24834   UChar vB_addr  = ifieldRegB(theInstr);
24835   UInt  opc2     = IFIELD( theInstr, 0, 11 );
24836
24837   IRTemp vA    = newTemp(Ity_V128);
24838   assign( vA, getVReg(vA_addr));
24839
24840   if (opc1 != 0x4) {
24841      vex_printf("dis_av_mult10(ppc)(instr)\n");
24842      return False;
24843   }
24844   switch (opc2) {
24845   case 0x001: { // vmul10cuq (Vector Multiply-by-10 and write carry
24846      DIP("vmul10cuq v%d,v%d\n", vT_addr, vA_addr);
24847      putVReg( vT_addr,
24848               unop( Iop_MulI128by10Carry, mkexpr( vA ) ) );
24849      break;
24850  }
24851   case 0x041: { // vmul10uq (Vector Multiply-by-10 Extended and write carry
24852                 //           Unsigned Quadword VX form)
24853      IRTemp vB    = newTemp(Ity_V128);
24854      assign( vB, getVReg(vB_addr));
24855      DIP("vmul10ecuq v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
24856      putVReg( vT_addr,
24857               binop( Iop_MulI128by10ECarry, mkexpr( vA ), mkexpr( vB ) ) );
24858      break;
24859   }
24860   case 0x201: { // vmul10uq (Vector Multiply-by-10 Unsigned Quadword VX form)
24861      DIP("vmul10uq v%d,v%d\n", vT_addr, vA_addr);
24862      putVReg( vT_addr,
24863               unop( Iop_MulI128by10, mkexpr( vA ) ) );
24864      break;
24865   }
24866  case 0x241: { // vmul10uq (Vector Multiply-by-10 Extended
24867                //           Unsigned Quadword VX form)
24868      IRTemp vB    = newTemp(Ity_V128);
24869      assign( vB, getVReg(vB_addr));
24870      DIP("vmul10euq v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
24871      putVReg( vT_addr,
24872               binop( Iop_MulI128by10E, mkexpr( vA ), mkexpr( vB ) ) );
24873      break;
24874   }
24875   default:
24876      vex_printf("dis_av_mult10(ppc)(opc2)\n");
24877      return False;
24878   }
24879   return True;
24880}
24881
24882/*
24883  AltiVec Pack/Unpack Instructions
24884*/
24885static Bool dis_av_pack ( UInt theInstr )
24886{
24887   /* VX-Form */
24888   UChar opc1     = ifieldOPC(theInstr);
24889   UChar vD_addr  = ifieldRegDS(theInstr);
24890   UChar vA_addr  = ifieldRegA(theInstr);
24891   UChar vB_addr  = ifieldRegB(theInstr);
24892   UInt  opc2     = IFIELD( theInstr, 0, 11 );
24893
24894   IRTemp signs = IRTemp_INVALID;
24895   IRTemp zeros = IRTemp_INVALID;
24896   IRTemp vA    = newTemp(Ity_V128);
24897   IRTemp vB    = newTemp(Ity_V128);
24898   assign( vA, getVReg(vA_addr));
24899   assign( vB, getVReg(vB_addr));
24900
24901   if (opc1 != 0x4) {
24902      vex_printf("dis_av_pack(ppc)(instr)\n");
24903      return False;
24904   }
24905   switch (opc2) {
24906   /* Packing */
24907   case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
24908      DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24909      putVReg( vD_addr,
24910               binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
24911      return True;
24912
24913   case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
24914      DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24915      putVReg( vD_addr,
24916               binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
24917      return True;
24918
24919   case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
24920      DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24921      putVReg( vD_addr,
24922               binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
24923      // TODO: set VSCR[SAT]
24924      return True;
24925
24926   case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
24927      DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24928      putVReg( vD_addr,
24929               binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
24930      // TODO: set VSCR[SAT]
24931      return True;
24932
24933   case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
24934      // This insn does a signed->unsigned saturating conversion.
24935      // Conversion done here, then uses unsigned->unsigned vpk insn:
24936      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
24937      IRTemp vA_tmp = newTemp(Ity_V128);
24938      IRTemp vB_tmp = newTemp(Ity_V128);
24939      DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24940      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
24941                            unop(Iop_NotV128,
24942                                 binop(Iop_SarN16x8,
24943                                       mkexpr(vA), mkU8(15)))) );
24944      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
24945                            unop(Iop_NotV128,
24946                                 binop(Iop_SarN16x8,
24947                                       mkexpr(vB), mkU8(15)))) );
24948      putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
24949                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
24950      // TODO: set VSCR[SAT]
24951      return True;
24952   }
24953   case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
24954      // This insn does a signed->unsigned saturating conversion.
24955      // Conversion done here, then uses unsigned->unsigned vpk insn:
24956      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
24957      IRTemp vA_tmp = newTemp(Ity_V128);
24958      IRTemp vB_tmp = newTemp(Ity_V128);
24959      DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24960      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
24961                            unop(Iop_NotV128,
24962                                 binop(Iop_SarN32x4,
24963                                       mkexpr(vA), mkU8(31)))) );
24964      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
24965                            unop(Iop_NotV128,
24966                                 binop(Iop_SarN32x4,
24967                                       mkexpr(vB), mkU8(31)))) );
24968      putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
24969                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
24970      // TODO: set VSCR[SAT]
24971      return True;
24972   }
24973   case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
24974      DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24975      putVReg( vD_addr,
24976               binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
24977      // TODO: set VSCR[SAT]
24978      return True;
24979
24980   case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
24981      DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24982      putVReg( vD_addr,
24983               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
24984      // TODO: set VSCR[SAT]
24985      return True;
24986
24987   case 0x30E: { // vpkpx (Pack Pixel, AV p219)
24988      /* CAB: Worth a new primop? */
24989      /* Using shifts to compact pixel elements, then packing them */
24990      IRTemp a1 = newTemp(Ity_V128);
24991      IRTemp a2 = newTemp(Ity_V128);
24992      IRTemp a3 = newTemp(Ity_V128);
24993      IRTemp a_tmp = newTemp(Ity_V128);
24994      IRTemp b1 = newTemp(Ity_V128);
24995      IRTemp b2 = newTemp(Ity_V128);
24996      IRTemp b3 = newTemp(Ity_V128);
24997      IRTemp b_tmp = newTemp(Ity_V128);
24998      DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24999      assign( a1, binop(Iop_ShlN16x8,
25000                        binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
25001                        mkU8(10)) );
25002      assign( a2, binop(Iop_ShlN16x8,
25003                        binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
25004                        mkU8(5)) );
25005      assign( a3,  binop(Iop_ShrN16x8,
25006                         binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
25007                         mkU8(11)) );
25008      assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
25009                           binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
25010
25011      assign( b1, binop(Iop_ShlN16x8,
25012                        binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
25013                        mkU8(10)) );
25014      assign( b2, binop(Iop_ShlN16x8,
25015                        binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
25016                        mkU8(5)) );
25017      assign( b3,  binop(Iop_ShrN16x8,
25018                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
25019                         mkU8(11)) );
25020      assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
25021                           binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
25022
25023      putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
25024                              mkexpr(a_tmp), mkexpr(b_tmp)) );
25025      return True;
25026   }
25027
25028   case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
25029      DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25030      putVReg( vD_addr,
25031               binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
25032      return True;
25033
25034   case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
25035      DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25036      putVReg( vD_addr,
25037               binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
25038      // TODO: set VSCR[SAT]
25039      return True;
25040
25041   case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
25042      // This insn does a doubled signed->double unsigned saturating conversion
25043      // Conversion done here, then uses unsigned->unsigned vpk insn:
25044      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
25045      // This is similar to the technique used for vpkswus, except done
25046      // with double word integers versus word integers.
25047      IRTemp vA_tmp = newTemp(Ity_V128);
25048      IRTemp vB_tmp = newTemp(Ity_V128);
25049      DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25050      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
25051                            unop(Iop_NotV128,
25052                                 binop(Iop_SarN64x2,
25053                                       mkexpr(vA), mkU8(63)))) );
25054      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
25055                            unop(Iop_NotV128,
25056                                 binop(Iop_SarN64x2,
25057                                       mkexpr(vB), mkU8(63)))) );
25058      putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
25059                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
25060      // TODO: set VSCR[SAT]
25061      return True;
25062   }
25063
25064   case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
25065      DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25066      putVReg( vD_addr,
25067               binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
25068      // TODO: set VSCR[SAT]
25069      return True;
25070   default:
25071      break; // Fall through...
25072   }
25073
25074
25075   if (vA_addr != 0) {
25076      vex_printf("dis_av_pack(ppc)(vA_addr)\n");
25077      return False;
25078   }
25079
25080   signs = newTemp(Ity_V128);
25081   zeros = newTemp(Ity_V128);
25082   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
25083
25084   switch (opc2) {
25085   /* Unpacking */
25086   case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
25087      DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
25088      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
25089      putVReg( vD_addr,
25090               binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
25091      break;
25092   }
25093   case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
25094      DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
25095      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
25096      putVReg( vD_addr,
25097               binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
25098      break;
25099   }
25100   case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
25101      DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
25102      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
25103      putVReg( vD_addr,
25104               binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
25105      break;
25106   }
25107   case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
25108      DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
25109      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
25110      putVReg( vD_addr,
25111               binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
25112      break;
25113   }
25114   case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
25115      /* CAB: Worth a new primop? */
25116      /* Using shifts to isolate pixel elements, then expanding them */
25117      IRTemp z0  = newTemp(Ity_V128);
25118      IRTemp z1  = newTemp(Ity_V128);
25119      IRTemp z01 = newTemp(Ity_V128);
25120      IRTemp z2  = newTemp(Ity_V128);
25121      IRTemp z3  = newTemp(Ity_V128);
25122      IRTemp z23 = newTemp(Ity_V128);
25123      DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
25124      assign( z0,  binop(Iop_ShlN16x8,
25125                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
25126                         mkU8(8)) );
25127      assign( z1,  binop(Iop_ShrN16x8,
25128                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
25129                         mkU8(11)) );
25130      assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
25131                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
25132      assign( z2,  binop(Iop_ShrN16x8,
25133                         binop(Iop_ShlN16x8,
25134                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
25135                               mkU8(11)),
25136                         mkU8(3)) );
25137      assign( z3,  binop(Iop_ShrN16x8,
25138                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
25139                         mkU8(11)) );
25140      assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
25141                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
25142      putVReg( vD_addr,
25143               binop(Iop_OrV128,
25144                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
25145                     mkexpr(z23)) );
25146      break;
25147   }
25148   case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
25149      /* identical to vupkhpx, except interleaving LO */
25150      IRTemp z0  = newTemp(Ity_V128);
25151      IRTemp z1  = newTemp(Ity_V128);
25152      IRTemp z01 = newTemp(Ity_V128);
25153      IRTemp z2  = newTemp(Ity_V128);
25154      IRTemp z3  = newTemp(Ity_V128);
25155      IRTemp z23 = newTemp(Ity_V128);
25156      DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
25157      assign( z0,  binop(Iop_ShlN16x8,
25158                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
25159                         mkU8(8)) );
25160      assign( z1,  binop(Iop_ShrN16x8,
25161                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
25162                         mkU8(11)) );
25163      assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
25164                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
25165      assign( z2,  binop(Iop_ShrN16x8,
25166                         binop(Iop_ShlN16x8,
25167                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
25168                               mkU8(11)),
25169                         mkU8(3)) );
25170      assign( z3,  binop(Iop_ShrN16x8,
25171                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
25172                         mkU8(11)) );
25173      assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
25174                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
25175      putVReg( vD_addr,
25176               binop(Iop_OrV128,
25177                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
25178                     mkexpr(z23)) );
25179      break;
25180   }
25181   case 0x64E: { // vupkhsw (Unpack High Signed Word)
25182      DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
25183      assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
25184      putVReg( vD_addr,
25185               binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
25186      break;
25187   }
25188   case 0x6CE: { // vupklsw (Unpack Low Signed Word)
25189      DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
25190      assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
25191      putVReg( vD_addr,
25192               binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
25193      break;
25194   }
25195   default:
25196      vex_printf("dis_av_pack(ppc)(opc2)\n");
25197      return False;
25198   }
25199   return True;
25200}
25201
25202/*
25203  AltiVec Cipher Instructions
25204*/
25205static Bool dis_av_cipher ( UInt theInstr )
25206{
25207   /* VX-Form */
25208   UChar opc1     = ifieldOPC(theInstr);
25209   UChar vD_addr  = ifieldRegDS(theInstr);
25210   UChar vA_addr  = ifieldRegA(theInstr);
25211   UChar vB_addr  = ifieldRegB(theInstr);
25212   UInt  opc2     = IFIELD( theInstr, 0, 11 );
25213
25214   IRTemp vA    = newTemp(Ity_V128);
25215   IRTemp vB    = newTemp(Ity_V128);
25216   assign( vA, getVReg(vA_addr));
25217   assign( vB, getVReg(vB_addr));
25218
25219   if (opc1 != 0x4) {
25220      vex_printf("dis_av_cipher(ppc)(instr)\n");
25221      return False;
25222   }
25223   switch (opc2) {
25224      case 0x508: // vcipher (Vector Inverser Cipher)
25225         DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25226         putVReg( vD_addr,
25227                  binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
25228         return True;
25229
25230      case 0x509: // vcipherlast (Vector Inverser Cipher Last)
25231         DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25232         putVReg( vD_addr,
25233                  binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
25234         return True;
25235
25236      case 0x548: // vncipher (Vector Inverser Cipher)
25237         DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25238         putVReg( vD_addr,
25239                  binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
25240         return True;
25241
25242      case 0x549: // vncipherlast (Vector Inverser Cipher Last)
25243         DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25244         putVReg( vD_addr,
25245                  binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
25246         return True;
25247
25248      case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
25249       * subBytes transform)
25250       */
25251         DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
25252         putVReg( vD_addr,
25253                  unop(Iop_CipherSV128, mkexpr(vA) ) );
25254         return True;
25255
25256      default:
25257         vex_printf("dis_av_cipher(ppc)(opc2)\n");
25258         return False;
25259   }
25260   return True;
25261}
25262
25263/*
25264  AltiVec Secure Hash Instructions
25265*/
25266static Bool dis_av_hash ( UInt theInstr )
25267{
25268   /* VX-Form */
25269   UChar opc1     = ifieldOPC(theInstr);
25270   UChar vRT_addr = ifieldRegDS(theInstr);
25271   UChar vRA_addr  = ifieldRegA(theInstr);
25272   UChar s_field  = IFIELD( theInstr, 11, 5 );  // st and six field
25273   UChar st       = IFIELD( theInstr, 15, 1 );  // st
25274   UChar six      = IFIELD( theInstr, 11, 4 );  // six field
25275   UInt  opc2     = IFIELD( theInstr, 0, 11 );
25276
25277   IRTemp vA    = newTemp(Ity_V128);
25278   IRTemp dst    = newTemp(Ity_V128);
25279   assign( vA, getVReg(vRA_addr));
25280
25281   if (opc1 != 0x4) {
25282      vex_printf("dis_av_hash(ppc)(instr)\n");
25283      return False;
25284   }
25285
25286   switch (opc2) {
25287      case 0x682:  // vshasigmaw
25288         DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
25289         assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
25290         putVReg( vRT_addr, mkexpr(dst));
25291         return True;
25292
25293      case 0x6C2:  // vshasigmad,
25294         DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
25295         putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
25296         return True;
25297
25298      default:
25299         vex_printf("dis_av_hash(ppc)(opc2)\n");
25300         return False;
25301   }
25302   return True;
25303}
25304
25305/*
25306 * This function is used by the Vector add/subtract [extended] modulo/carry
25307 * instructions.
25308 *   - For the non-extended add instructions, the cin arg is set to zero.
25309 *   - For the extended add instructions, cin is the integer value of
25310 *     src3.bit[127].
25311 *   - For the non-extended subtract instructions, src1 is added to the one's
25312 *     complement of src2 + 1.  We re-use the cin argument to hold the '1'
25313 *     value for this operation.
25314 *   - For the extended subtract instructions, cin is the integer value of src3.bit[127].
25315 */
25316static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
25317                                        IRExpr * cin, Bool modulo)
25318{
25319   IRTemp _vecA_32   = IRTemp_INVALID;
25320   IRTemp _vecB_32   = IRTemp_INVALID;
25321   IRTemp res_32     = IRTemp_INVALID;
25322   IRTemp res_64     = IRTemp_INVALID;
25323   IRTemp result     = IRTemp_INVALID;
25324   IRTemp tmp_result = IRTemp_INVALID;
25325   IRTemp carry      = IRTemp_INVALID;
25326   Int i;
25327   IRExpr * _vecA_low64 =  unop( Iop_V128to64, vecA );
25328   IRExpr * _vecB_low64 =  unop( Iop_V128to64, vecB );
25329   IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
25330   IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
25331
25332   carry = newTemp(Ity_I32);
25333   assign( carry, cin );
25334
25335   for (i = 0; i < 4; i++) {
25336      _vecA_32 = newTemp(Ity_I32);
25337      _vecB_32 = newTemp(Ity_I32);
25338      res_32   = newTemp(Ity_I32);
25339      res_64   = newTemp(Ity_I64);
25340
25341      switch (i) {
25342      case 0:
25343         assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
25344         assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
25345         break;
25346      case 1:
25347         assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
25348         assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
25349         break;
25350      case 2:
25351         assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
25352         assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
25353         break;
25354      case 3:
25355         assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
25356         assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
25357         break;
25358      }
25359
25360      assign( res_64, binop( Iop_Add64,
25361                             binop ( Iop_Add64,
25362                                     binop( Iop_32HLto64,
25363                                            mkU32( 0 ),
25364                                            mkexpr(_vecA_32) ),
25365                                     binop( Iop_32HLto64,
25366                                            mkU32( 0 ),
25367                                            mkexpr(_vecB_32) ) ),
25368                             binop( Iop_32HLto64,
25369                                    mkU32( 0 ),
25370                                    mkexpr( carry ) ) ) );
25371
25372      /* Calculate the carry to the next higher 32 bits. */
25373      carry = newTemp(Ity_I32);
25374      assign(carry, unop( Iop_64HIto32, mkexpr( res_64 ) ) );
25375
25376      /* result is the lower 32-bits */
25377      assign(res_32, unop( Iop_64to32, mkexpr( res_64 ) ) );
25378
25379      if (modulo) {
25380         result = newTemp(Ity_V128);
25381         assign(result, binop( Iop_OrV128,
25382                              (i == 0) ? binop( Iop_64HLtoV128,
25383                                                mkU64(0),
25384                                                mkU64(0) ) : mkexpr(tmp_result),
25385                              binop( Iop_ShlV128,
25386                                     binop( Iop_64HLtoV128,
25387                                            mkU64(0),
25388                                            binop( Iop_32HLto64,
25389                                                   mkU32(0),
25390                                                   mkexpr(res_32) ) ),
25391                                     mkU8(i * 32) ) ) );
25392         tmp_result = newTemp(Ity_V128);
25393         assign(tmp_result, mkexpr(result));
25394      }
25395   }
25396   if (modulo)
25397      return result;
25398   else
25399      return carry;
25400}
25401
25402
25403static Bool dis_av_quad ( UInt theInstr )
25404{
25405   /* VX-Form */
25406   UChar opc1     = ifieldOPC(theInstr);
25407   UChar vRT_addr = ifieldRegDS(theInstr);
25408   UChar vRA_addr = ifieldRegA(theInstr);
25409   UChar vRB_addr = ifieldRegB(theInstr);
25410   UChar vRC_addr;
25411   UInt  opc2     = IFIELD( theInstr, 0, 11 );
25412
25413   IRTemp vA    = newTemp(Ity_V128);
25414   IRTemp vB    = newTemp(Ity_V128);
25415   IRTemp vC    = IRTemp_INVALID;
25416   IRTemp cin    = IRTemp_INVALID;
25417   assign( vA, getVReg(vRA_addr));
25418   assign( vB, getVReg(vRB_addr));
25419
25420   if (opc1 != 0x4) {
25421      vex_printf("dis_av_quad(ppc)(instr)\n");
25422      return False;
25423   }
25424
25425   switch (opc2) {
25426   case 0x140:  // vaddcuq
25427     DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25428     putVReg( vRT_addr, unop( Iop_32UtoV128,
25429                              mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25430                                                               mkexpr(vB),
25431                                                               mkU32(0), False) ) ) );
25432     return True;
25433   case 0x100: // vadduqm
25434      DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25435      putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25436                                                          mkexpr(vB), mkU32(0), True) ) );
25437      return True;
25438   case 0x540: // vsubcuq
25439      DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25440      putVReg( vRT_addr,
25441               unop( Iop_32UtoV128,
25442                     mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25443                                                      unop( Iop_NotV128,
25444                                                            mkexpr(vB) ),
25445                                                      mkU32(1), False) ) ) );
25446      return True;
25447   case 0x500: // vsubuqm
25448      DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25449      putVReg( vRT_addr,
25450               mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25451                                                unop( Iop_NotV128, mkexpr(vB) ),
25452                                                mkU32(1), True) ) );
25453      return True;
25454   case 0x054C: // vbpermq
25455   {
25456#define BPERMD_IDX_MASK 0x00000000000000FFULL
25457#define BPERMD_BIT_MASK 0x8000000000000000ULL
25458      int i;
25459      IRExpr * vB_expr = mkexpr(vB);
25460      IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
25461      DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25462      for (i = 0; i < 16; i++) {
25463         IRTemp idx_tmp = newTemp( Ity_V128 );
25464         IRTemp perm_bit = newTemp( Ity_V128 );
25465         IRTemp idx = newTemp( Ity_I8 );
25466         IRTemp idx_LT127 = newTemp( Ity_I1 );
25467         IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
25468
25469         assign( idx_tmp,
25470                 binop( Iop_AndV128,
25471                        binop( Iop_64HLtoV128,
25472                               mkU64(0),
25473                               mkU64(BPERMD_IDX_MASK) ),
25474                        vB_expr ) );
25475         assign( idx_LT127,
25476                 binop( Iop_CmpEQ32,
25477                        unop ( Iop_64to32,
25478                               unop( Iop_V128to64, binop( Iop_ShrV128,
25479                                                          mkexpr(idx_tmp),
25480                                                          mkU8(7) ) ) ),
25481                        mkU32(0) ) );
25482
25483         /* Below, we set idx to determine which bit of vA to use for the
25484          * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
25485          */
25486         assign( idx,
25487                 binop( Iop_And8,
25488                        unop( Iop_1Sto8,
25489                              mkexpr(idx_LT127) ),
25490                        unop( Iop_32to8,
25491                              unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
25492
25493         assign( idx_LT127_ity128,
25494                 binop( Iop_64HLtoV128,
25495                        mkU64(0),
25496                        unop( Iop_32Uto64,
25497                              unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
25498         assign( perm_bit,
25499                 binop( Iop_AndV128,
25500                        mkexpr( idx_LT127_ity128 ),
25501                        binop( Iop_ShrV128,
25502                               binop( Iop_AndV128,
25503                                      binop (Iop_64HLtoV128,
25504                                             mkU64( BPERMD_BIT_MASK ),
25505                                             mkU64(0)),
25506                                      binop( Iop_ShlV128,
25507                                             mkexpr( vA ),
25508                                             mkexpr( idx ) ) ),
25509                               mkU8( 127 ) ) ) );
25510         res = binop( Iop_OrV128,
25511                      res,
25512                      binop( Iop_ShlV128,
25513                             mkexpr( perm_bit ),
25514                             mkU8( i + 64 ) ) );
25515         vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
25516      }
25517      putVReg( vRT_addr, res);
25518      return True;
25519#undef BPERMD_IDX_MASK
25520#undef BPERMD_BIT_MASK
25521   }
25522
25523   default:
25524      break;  // fall through
25525   }
25526
25527   opc2     = IFIELD( theInstr, 0, 6 );
25528   vRC_addr = ifieldRegC(theInstr);
25529   vC = newTemp(Ity_V128);
25530   cin = newTemp(Ity_I32);
25531   switch (opc2) {
25532      case 0x3D: // vaddecuq
25533         assign( vC, getVReg(vRC_addr));
25534         DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
25535             vRC_addr);
25536         assign(cin, binop( Iop_And32,
25537                            unop( Iop_64to32,
25538                                  unop( Iop_V128to64, mkexpr(vC) ) ),
25539                            mkU32(1) ) );
25540         putVReg( vRT_addr,
25541                  unop( Iop_32UtoV128,
25542                        mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
25543                                                         mkexpr(cin),
25544                                                         False) ) ) );
25545         return True;
25546      case 0x3C: // vaddeuqm
25547         assign( vC, getVReg(vRC_addr));
25548         DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
25549             vRC_addr);
25550         assign(cin, binop( Iop_And32,
25551                            unop( Iop_64to32,
25552                                  unop( Iop_V128to64, mkexpr(vC) ) ),
25553                            mkU32(1) ) );
25554         putVReg( vRT_addr,
25555                  mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
25556                                                   mkexpr(cin),
25557                                                   True) ) );
25558         return True;
25559      case 0x3F: // vsubecuq
25560         assign( vC, getVReg(vRC_addr));
25561         DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
25562             vRC_addr);
25563         assign(cin, binop( Iop_And32,
25564                            unop( Iop_64to32,
25565                                  unop( Iop_V128to64, mkexpr(vC) ) ),
25566                            mkU32(1) ) );
25567         putVReg( vRT_addr,
25568                  unop( Iop_32UtoV128,
25569                        mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25570                                                         unop( Iop_NotV128,
25571                                                               mkexpr(vB) ),
25572                                                         mkexpr(cin),
25573                                                         False) ) ) );
25574         return True;
25575      case 0x3E: // vsubeuqm
25576         assign( vC, getVReg(vRC_addr));
25577         DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
25578             vRC_addr);
25579         assign(cin, binop( Iop_And32,
25580                            unop( Iop_64to32,
25581                                  unop( Iop_V128to64, mkexpr(vC) ) ),
25582                            mkU32(1) ) );
25583         putVReg( vRT_addr,
25584                  mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25585                                                   unop( Iop_NotV128, mkexpr(vB) ),
25586                                                   mkexpr(cin),
25587                                                   True) ) );
25588         return True;
25589      default:
25590         vex_printf("dis_av_quad(ppc)(opc2.2)\n");
25591         return False;
25592   }
25593
25594   return True;
25595}
25596
25597static IRExpr * bcd_sign_code_adjust( UInt ps, IRExpr * tmp)
25598{
25599   /* The Iop_BCDAdd and Iop_BCDSub will result in the corresponding Power PC
25600    * instruction being issued with ps = 0.  If ps = 1, the sign code, which
25601    * is in the least significant four bits of the result, needs to be updated
25602    * per the ISA:
25603    *
25604    *    If PS=0, the sign code of the result is set to 0b1100.
25605    *    If PS=1, the sign code of the result is set to 0b1111.
25606    *
25607    * Note, the ps value is NOT being passed down to the instruction issue
25608    * because passing a constant via triop() breaks the vbit-test test.  The
25609    * vbit-tester assumes it can set non-zero shadow bits for the triop()
25610    * arguments.  Thus they have to be expressions not a constant.
25611    * Use 32-bit compare instructiions as 64-bit compares are not supported
25612    * in 32-bit mode.
25613    */
25614   IRTemp mask  = newTemp(Ity_I64);
25615   IRExpr *rtn;
25616
25617   if ( ps == 0 ) {
25618      /* sign code is correct, just return it.  */
25619      rtn = tmp;
25620
25621   } else {
25622      /* Check if lower four bits are 0b1100, if so, change to 0b1111 */
25623      /* Make this work in 32-bit mode using only 32-bit compares */
25624      assign( mask, unop( Iop_1Sto64,
25625                          binop( Iop_CmpEQ32, mkU32( 0xC ),
25626                                 binop( Iop_And32, mkU32( 0xF ),
25627                                        unop( Iop_64to32,
25628                                              unop( Iop_V128to64, tmp )
25629                                              ) ) ) ) );
25630      rtn = binop( Iop_64HLtoV128,
25631                   unop( Iop_V128HIto64, tmp ),
25632                   binop( Iop_Or64,
25633                          binop( Iop_And64, mkU64( 0xF ), mkexpr( mask ) ),
25634                          unop( Iop_V128to64, tmp ) ) );
25635   }
25636
25637   return rtn;
25638}
25639
25640/*
25641  AltiVec BCD Arithmetic instructions.
25642  These instructions modify CR6 for various conditions in the result,
25643  including when an overflow occurs.  We could easily detect all conditions
25644  except when an overflow occurs.  But since we can't be 100% accurate
25645  in our emulation of CR6, it seems best to just not support it all.
25646*/
25647static Bool dis_av_bcd_misc ( UInt theInstr, const VexAbiInfo* vbi )
25648{
25649   UChar opc1     = ifieldOPC(theInstr);
25650   UChar vRT_addr = ifieldRegDS(theInstr);
25651   UChar vRA_addr = ifieldRegA(theInstr);
25652   UChar vRB_addr = ifieldRegB(theInstr);
25653   IRTemp vA      = newTemp(Ity_V128);
25654   IRTemp vB      = newTemp(Ity_V128);
25655   UInt  opc2     = IFIELD( theInstr, 0, 11 );
25656   IRExpr *pos, *neg, *valid, *zero, *sign;
25657   IRTemp eq_lt_gt = newTemp( Ity_I32 );
25658
25659   assign( vA, getVReg(vRA_addr));
25660   assign( vB, getVReg(vRB_addr));
25661
25662   if (opc1 != 0x4) {
25663      vex_printf("dis_av_bcd_misc(ppc)(instr)\n");
25664      return False;
25665   }
25666
25667   switch (opc2) {
25668   case 0x341: // bcdcpsgn. Decimal Copy Sign VX-form
25669      {
25670         IRExpr *sign_vb, *value_va;
25671         DIP("bcdcpsgn. v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25672
25673         zero =
25674            BCDstring_zero( binop( Iop_AndV128,
25675                                   binop( Iop_64HLtoV128,
25676                                          mkU64( 0xFFFFFFFFFFFFFFFF ),
25677                                          mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
25678                                   mkexpr( vA ) ) );
25679
25680         /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
25681          * codes 0xB and 0xD are negative.
25682          */
25683         sign = binop( Iop_And64, mkU64( 0xF ),
25684                       unop( Iop_V128to64, mkexpr( vB ) ) );
25685
25686         neg = mkOR1( binop( Iop_CmpEQ64,
25687                             sign,
25688                             mkU64 ( 0xB ) ),
25689                      binop( Iop_CmpEQ64,
25690                             sign,
25691                             mkU64 ( 0xD ) ) );
25692
25693         pos = mkNOT1( neg );
25694
25695         /* invalid if vA or vB is not valid */
25696         valid =
25697            unop( Iop_64to32,
25698                  binop( Iop_And64,
25699                         is_BCDstring128( vbi,
25700                                          /*Signed*/True, mkexpr( vA ) ),
25701                         is_BCDstring128( vbi,
25702                                          /*Signed*/True, mkexpr( vB ) ) ) );
25703
25704         sign_vb = binop( Iop_AndV128,
25705                          binop( Iop_64HLtoV128,
25706                                 mkU64( 0 ),
25707                                 mkU64( 0xF ) ),
25708                          mkexpr( vB ) );
25709
25710         value_va = binop( Iop_AndV128,
25711                           binop( Iop_64HLtoV128,
25712                                  mkU64( 0xFFFFFFFFFFFFFFFF ),
25713                                  mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
25714                           mkexpr( vA ) );
25715         putVReg( vRT_addr, binop( Iop_OrV128, sign_vb, value_va ) );
25716      }
25717      break;
25718
25719   default:
25720      vex_printf("dis_av_bcd_misc(ppc)(opc2)\n");
25721      return False;
25722   }
25723
25724   /* set CR field 6 to:
25725    *    0b1000  if vB less then 0, i.e. vB is neg and not zero,
25726    *    0b0100  if vB greter then 0,  i.e. vB is pos and not zero,
25727    *    0b1000  if vB equals 0,
25728    *    0b0001  if vB is invalid  over rules lt, gt, eq
25729    */
25730   assign( eq_lt_gt,
25731           binop( Iop_Or32,
25732                  binop( Iop_Shl32,
25733                         unop( Iop_1Uto32,
25734                               mkAND1( neg,
25735                                       mkNOT1( zero ) ) ),
25736                         mkU8( 3 ) ),
25737                  binop( Iop_Or32,
25738                         binop( Iop_Shl32,
25739                                unop( Iop_1Uto32,
25740                                      mkAND1( pos,
25741                                              mkNOT1( zero ) ) ),
25742                                mkU8( 2 ) ),
25743                         binop( Iop_Shl32,
25744                                unop( Iop_1Uto32, zero ),
25745                                mkU8( 1 ) ) ) ) );
25746
25747   IRTemp valid_mask = newTemp( Ity_I32 );
25748
25749   assign( valid_mask, unop( Iop_1Sto32, unop( Iop_32to1, valid ) ) );
25750
25751   putGST_field( PPC_GST_CR,
25752                 binop( Iop_Or32,
25753                        binop( Iop_And32,
25754                               mkexpr( valid_mask ),
25755                               mkexpr( eq_lt_gt ) ),
25756                        binop( Iop_And32,
25757                               unop( Iop_Not32, mkexpr( valid_mask ) ),
25758                               mkU32( 1 ) ) ),
25759                 6 );
25760   return True;
25761}
25762
25763static Bool dis_av_bcd ( UInt theInstr, const VexAbiInfo* vbi )
25764{
25765   /* VX-Form */
25766   UChar opc1     = ifieldOPC(theInstr);
25767   UChar vRT_addr = ifieldRegDS(theInstr);
25768   UChar vRA_addr = ifieldRegA(theInstr);
25769   UChar vRB_addr = ifieldRegB(theInstr);
25770   UChar ps       = IFIELD( theInstr, 9, 1 );
25771   UInt  opc2     = IFIELD( theInstr, 0, 9 );
25772   IRTemp vA    = newTemp(Ity_V128);
25773   IRTemp vB    = newTemp(Ity_V128);
25774   IRTemp dst    = newTemp(Ity_V128);
25775   IRExpr *pos, *neg, *valid, *zero, *sign_digit, *in_range;
25776   IRTemp eq_lt_gt = newTemp( Ity_I32 );
25777   IRExpr *overflow, *value;
25778
25779   assign( vA, getVReg(vRA_addr));
25780   assign( vB, getVReg(vRB_addr));
25781
25782   if (opc1 != 0x4) {
25783      vex_printf("dis_av_bcd(ppc)(instr)\n");
25784      return False;
25785   }
25786
25787   switch (opc2) {
25788   case 0x1:   // bcdadd.
25789   case 0x41:  // bcdsub.
25790      {
25791         /* NOTE 64 bit compares are not supported in 32-bit mode.  Use
25792          * 32-bit compares only.
25793          */
25794
25795         IRExpr *sign, *res_smaller;
25796         IRExpr *signA, *signB, *sign_digitA, *sign_digitB;
25797         IRExpr *zeroA, *zeroB, *posA, *posB, *negA, *negB;
25798
25799         if ( opc2 == 0x1 ) {
25800            DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
25801            assign( dst, bcd_sign_code_adjust( ps,
25802                                               binop( Iop_BCDAdd,
25803                                                      mkexpr( vA ),
25804                                                      mkexpr( vB ) ) ) );
25805         } else {
25806            DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
25807            assign( dst, bcd_sign_code_adjust( ps,
25808                                               binop( Iop_BCDSub,
25809                                                      mkexpr( vA ),
25810                                                      mkexpr( vB ) ) ) );
25811         }
25812
25813         putVReg( vRT_addr, mkexpr( dst ) );
25814         /* set CR field 6 */
25815         /* result */
25816         zero = BCDstring_zero( binop( Iop_AndV128,
25817                                       binop( Iop_64HLtoV128,
25818                                              mkU64( 0xFFFFFFFFFFFFFFFF ),
25819                                              mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
25820                                       mkexpr(dst) ) );  // ignore sign
25821
25822         sign_digit = binop( Iop_And32, mkU32( 0xF ),
25823                             unop( Iop_64to32,
25824                                   unop( Iop_V128to64, mkexpr( dst ) ) ) );
25825
25826         sign = mkOR1( binop( Iop_CmpEQ32,
25827                              sign_digit,
25828                              mkU32 ( 0xB ) ),
25829                       binop( Iop_CmpEQ32,
25830                              sign_digit,
25831                              mkU32 ( 0xD ) ) );
25832         neg = mkAND1( sign, mkNOT1( zero ) );
25833
25834         /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
25835         pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
25836         valid =  unop( Iop_64to32,
25837                        binop( Iop_And64,
25838                               is_BCDstring128( vbi,
25839                                                /*Signed*/True, mkexpr( vA ) ),
25840                               is_BCDstring128( vbi,
25841                                                /*Signed*/True, mkexpr( vB ) )
25842                                                ) );
25843
25844         /* src A */
25845         zeroA = BCDstring_zero( binop( Iop_AndV128,
25846                                        binop( Iop_64HLtoV128,
25847                                               mkU64( 0xFFFFFFFFFFFFFFFF ),
25848                                               mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
25849                                        mkexpr( vA ) ) );  // ignore sign
25850         sign_digitA = binop( Iop_And32, mkU32( 0xF ),
25851                              unop( Iop_64to32,
25852                                    unop( Iop_V128to64, mkexpr( vA ) ) ) );
25853
25854         signA = mkOR1( binop( Iop_CmpEQ32,
25855                               sign_digitA,
25856                               mkU32 ( 0xB ) ),
25857                        binop( Iop_CmpEQ32,
25858                               sign_digitA,
25859                               mkU32 ( 0xD ) ) );
25860         negA = mkAND1( signA, mkNOT1( zeroA ) );
25861         /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
25862         posA = mkAND1( mkNOT1( signA ), mkNOT1( zeroA ) );
25863
25864         /* src B */
25865         zeroB = BCDstring_zero( binop( Iop_AndV128,
25866                                        binop( Iop_64HLtoV128,
25867                                               mkU64( 0xFFFFFFFFFFFFFFFF ),
25868                                               mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
25869                                        mkexpr( vB ) ) );  // ignore sign
25870         sign_digitB = binop( Iop_And32, mkU32( 0xF ),
25871                              unop( Iop_64to32,
25872                                    unop( Iop_V128to64, mkexpr( vB ) ) ) );
25873
25874         signB = mkOR1( binop( Iop_CmpEQ32,
25875                               sign_digitB,
25876                               mkU32 ( 0xB ) ),
25877                        binop( Iop_CmpEQ32,
25878                               sign_digitB,
25879                               mkU32 ( 0xD ) ) );
25880         negB = mkAND1( signB, mkNOT1( zeroB ) );
25881
25882
25883         /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
25884         posB = mkAND1( mkNOT1( signB ), mkNOT1( zeroB ) );
25885
25886
25887         if (mode64) {
25888	    res_smaller = mkAND1( CmpGT128U( mkexpr( vA ), mkexpr( dst ) ),
25889				  CmpGT128U( mkexpr( vB ), mkexpr( dst ) ) );
25890
25891         } else {
25892            /* Have to do this with 32-bit compares, expensive */
25893            res_smaller = mkAND1( UNSIGNED_CMP_GT_V128( mkexpr( vA ),
25894                                                        mkexpr( dst ) ),
25895                                  UNSIGNED_CMP_GT_V128( mkexpr( vB ),
25896                                                        mkexpr( dst ) ) );
25897         }
25898
25899         if ( opc2 == 0x1) {
25900            /* Overflow for Add can only occur if the signs of the operands
25901             * are the same and the two operands are non-zero.  On overflow,
25902             * the PPC hardware produces a result consisting of just the lower
25903             * digits of the result.  So, if the result is less then both
25904             * operands and the sign of the operands are the same overflow
25905             * occured.
25906             */
25907            overflow = mkOR1( mkAND1( res_smaller, mkAND1( negA, negB ) ),
25908                              mkAND1( res_smaller, mkAND1( posA, posB ) ) );
25909         } else {
25910            /* Overflow for Add can only occur if the signs of the operands
25911             * are the different and the two operands are non-zero.  On overflow,
25912             * the PPC hardware produces a result consisting of just the lower
25913             * digits of the result.  So, if the result is less then both
25914             * operands and the sign of the operands are different overflow
25915             * occured.
25916             */
25917            overflow = mkOR1( mkAND1( res_smaller, mkAND1( negA, posB ) ),
25918                              mkAND1( res_smaller, mkAND1( posA, negB ) ) );
25919         }
25920      }
25921     break;
25922
25923   case 0x081: // bcdus.  Decimal Unsigned Shift VX-form
25924   case 0x0C1: // bcds.   Decimal Shift VX-form
25925   case 0x1C1: // bcdsr.  Decimal Shift and Round VX-form
25926      {
25927         IRExpr *shift_dir;
25928         IRExpr *shift_mask, *result, *new_sign_val, *sign;
25929         IRExpr *not_excess_shift, *not_excess_shift_mask;
25930         IRTemp shift_dir_mask = newTemp( Ity_I64 );
25931         IRTemp shift_by = newTemp( Ity_I64 );
25932         IRTemp shift_field = newTemp( Ity_I64 );
25933         IRTemp shifted_out = newTemp( Ity_V128 );
25934         IRTemp value_shl = newTemp( Ity_V128 );
25935         IRTemp value_shr = newTemp( Ity_V128 );
25936         IRTemp round = newTemp( Ity_I32);
25937
25938         ULong value_mask_low = 0;
25939         UInt max_shift = 0;
25940
25941         if (opc2 == 0x0C1) {
25942            DIP("bcds. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr, vRB_addr, ps);
25943            value_mask_low = 0xFFFFFFFFFFFFFFF0;
25944            max_shift = 30 * 4; /* maximum without shifting all digits out */
25945
25946         }  else if (opc2 == 0x1C1) {
25947            DIP("bcdsr. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr, vRB_addr, ps);
25948
25949            value_mask_low = 0xFFFFFFFFFFFFFFF0;
25950            max_shift = 30 * 4; /* maximum without shifting all digits out */
25951
25952         } else {
25953            DIP("bcdus. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr,
25954                vRB_addr, ps);
25955            value_mask_low = 0xFFFFFFFFFFFFFFFF;
25956            max_shift = 31 * 4; /* maximum without shifting all digits out */
25957         }
25958
25959         value = binop( Iop_AndV128,
25960                        binop( Iop_64HLtoV128,
25961                               mkU64( 0xFFFFFFFFFFFFFFFF ),
25962                               mkU64( value_mask_low ) ),
25963                        mkexpr( vB ) );
25964
25965         zero = BCDstring_zero( value );
25966
25967         /* Shift field is 2's complement value */
25968         assign( shift_field, unop( Iop_V128to64,
25969                                    binop( Iop_ShrV128,
25970                                           binop( Iop_AndV128,
25971                                                  binop( Iop_64HLtoV128,
25972                                                         mkU64( 0xFF ),
25973                                                         mkU64( 0x0) ),
25974                                                  mkexpr( vA ) ),
25975                                           mkU8( 64 ) ) ) );
25976
25977         /* if shift_dir = 0 shift left, otherwise shift right */
25978         shift_dir = binop( Iop_CmpEQ64,
25979                            binop( Iop_Shr64,
25980                                   mkexpr( shift_field ),
25981                                   mkU8( 7 ) ),
25982                            mkU64( 1 ) );
25983
25984         assign( shift_dir_mask, unop( Iop_1Sto64, shift_dir ) );
25985
25986         /* Shift field is stored in 2's complement form */
25987         assign(shift_by,
25988                binop( Iop_Mul64,
25989                       binop( Iop_Or64,
25990                              binop( Iop_And64,
25991                                     unop( Iop_Not64,
25992                                           mkexpr( shift_dir_mask ) ),
25993                                     mkexpr( shift_field ) ),
25994                              binop( Iop_And64,
25995                                     mkexpr( shift_dir_mask ),
25996                                     binop( Iop_And64,
25997                                            binop( Iop_Add64,
25998                                                   mkU64( 1 ),
25999                                                   unop( Iop_Not64,
26000                                                         mkexpr( shift_field ) ) ),
26001                                            mkU64( 0xFF ) ) ) ),
26002                       mkU64( 4 ) ) );
26003
26004         /* If the shift exceeds 128 bits, we need to force the result
26005          * to zero because Valgrind shift amount is only 7-bits. Otherwise,
26006          * we get a shift amount of mod(shift_by, 127)
26007          */
26008         not_excess_shift = unop( Iop_1Sto64,
26009                                  binop( Iop_CmpLE64U,
26010                                         mkexpr( shift_by ),
26011                                         mkU64( max_shift ) ) );
26012
26013         not_excess_shift_mask = binop( Iop_64HLtoV128,
26014                                        not_excess_shift,
26015                                        not_excess_shift );
26016
26017         assign( value_shl,
26018                 binop( Iop_ShlV128, value, unop( Iop_64to8,
26019                                                  mkexpr( shift_by) ) ) );
26020         assign( value_shr,
26021                 binop( Iop_AndV128,
26022                        binop( Iop_64HLtoV128,
26023                               mkU64( 0xFFFFFFFFFFFFFFFF ),
26024                               mkU64( value_mask_low) ),
26025                        binop( Iop_ShrV128,
26026                               value,
26027                               unop( Iop_64to8,
26028                                     mkexpr( shift_by ) )  ) ) );
26029
26030         /* Overflow occurs if the shift amount is greater than zero, the
26031          * operation is a left shift and any non-zero digits are left
26032          * shifted out.
26033          */
26034         assign( shifted_out,
26035                 binop( Iop_OrV128,
26036                        binop( Iop_ShrV128,
26037                               value,
26038                               unop( Iop_64to8,
26039                                     binop( Iop_Sub64,
26040                                            mkU64( 32*4 ),
26041                                            mkexpr( shift_by ) ) ) ),
26042                        binop( Iop_AndV128,
26043                               unop( Iop_NotV128,
26044                                     not_excess_shift_mask ),
26045                               value ) ) );
26046
26047         overflow = mkAND1( mkNOT1( BCDstring_zero( mkexpr( shifted_out ) ) ),
26048                            mkAND1( mkNOT1( shift_dir ),
26049                                    binop( Iop_CmpNE64,
26050                                           mkexpr( shift_by ),
26051                                           mkU64( 0 ) ) ) );
26052
26053         if ((opc2 == 0xC1) || (opc2 == 0x1C1)) {
26054            /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26055             * codes 0xB and 0xD are negative.
26056             */
26057            sign_digit = binop( Iop_And64, mkU64( 0xF ),
26058                                unop( Iop_V128to64, mkexpr( vB ) ) );
26059
26060            sign = mkOR1( binop( Iop_CmpEQ64,
26061                                 sign_digit,
26062                                 mkU64 ( 0xB ) ),
26063                          binop( Iop_CmpEQ64,
26064                                 sign_digit,
26065                                 mkU64 ( 0xD ) ) );
26066            neg = mkAND1( sign, mkNOT1( zero ) );
26067
26068            /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
26069            pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26070
26071            valid =
26072               unop( Iop_64to32,
26073                     is_BCDstring128( vbi, /* Signed */True, mkexpr( vB ) ) );
26074
26075         } else {
26076            /* string is an unsigned BCD value */
26077            pos = mkU1( 1 );
26078            neg = mkU1( 0 );
26079            sign = mkU1( 0 );
26080
26081            valid =
26082               unop( Iop_64to32,
26083                     is_BCDstring128( vbi, /* Unsigned */False,
26084                                      mkexpr( vB ) ) );
26085         }
26086
26087         /* if PS = 0
26088                  vB positive, sign is C
26089                  vB negative, sign is D
26090            if PS = 1
26091                  vB positive, sign is F
26092                  vB negative, sign is D
26093            Note can't use pos or neg here since they are ANDed with zero,
26094            use sign instead.
26095         */
26096         if (ps == 0) {
26097            new_sign_val = binop( Iop_Or64,
26098                                  unop( Iop_1Uto64, sign ),
26099                                  mkU64( 0xC ) );
26100
26101         } else {
26102            new_sign_val = binop( Iop_Xor64,
26103                                  binop( Iop_Shl64,
26104                                         unop( Iop_1Uto64, sign ),
26105                                         mkU8( 1 ) ),
26106                                  mkU64( 0xF ) );
26107         }
26108
26109         shift_mask = binop( Iop_64HLtoV128,
26110                             unop( Iop_1Sto64, shift_dir ),
26111                             unop( Iop_1Sto64, shift_dir ) );
26112
26113         result = binop( Iop_OrV128,
26114                         binop( Iop_AndV128, mkexpr( value_shr ), shift_mask ),
26115                         binop( Iop_AndV128,
26116                                mkexpr( value_shl ),
26117                                unop( Iop_NotV128, shift_mask ) ) );
26118
26119         if (opc2 == 0xC1) {    // bcds.
26120            putVReg( vRT_addr, binop( Iop_OrV128,
26121                                      binop( Iop_64HLtoV128,
26122                                             mkU64( 0 ),
26123                                             new_sign_val ),
26124                                      binop( Iop_AndV128,
26125                                             not_excess_shift_mask,
26126                                             result ) ) );
26127         } else if (opc2 == 0x1C1) {  //bcdsr.
26128            /* If shifting right, need to round up if needed */
26129            assign( round, unop( Iop_1Uto32,
26130                                 mkAND1( shift_dir,
26131                                         check_BCD_round( value,
26132                                                          shift_by ) ) ) );
26133
26134            putVReg( vRT_addr,
26135                     binop( Iop_OrV128,
26136                            binop( Iop_64HLtoV128,
26137                                   mkU64( 0 ),
26138                                   new_sign_val ),
26139                            binop( Iop_AndV128,
26140                                   not_excess_shift_mask,
26141                                   mkexpr( increment_BCDstring( vbi, result,
26142                                                                mkexpr( round)
26143                                                                ) ) ) ) );
26144         } else {  // bcdus.
26145            putVReg( vRT_addr, binop( Iop_AndV128,
26146                                      not_excess_shift_mask,
26147                                      result ) );
26148         }
26149      }
26150      break;
26151
26152   case 0x101:  // bcdtrunc.   Decimal Truncate VX-form
26153   case 0x141:  // bcdutrunc.  Decimal Unsigned Truncate VX-form
26154      {
26155         IRTemp length = newTemp( Ity_I64 );
26156         IRTemp masked_out = newTemp( Ity_V128 );
26157         IRExpr *new_sign_val, *result, *shift;
26158         IRExpr *length_neq_128, *sign;
26159         ULong value_mask_low;
26160         Int max_digits;
26161
26162         if ( opc2 == 0x101) {     // bcdtrunc.
26163            value_mask_low = 0xFFFFFFFFFFFFFFF0;
26164            max_digits = 31;
26165         } else {
26166            value_mask_low = 0xFFFFFFFFFFFFFFFF;
26167            max_digits = 32;
26168         }
26169
26170         assign( length, binop( Iop_And64,
26171                                     unop( Iop_V128HIto64,
26172                                           mkexpr( vA ) ),
26173                                     mkU64( 0xFFFF ) ) );
26174         shift = unop( Iop_64to8,
26175                       binop( Iop_Mul64,
26176                              binop( Iop_Sub64,
26177                                     mkU64( max_digits ),
26178                                     mkexpr( length ) ),
26179                              mkU64( 4 ) ) );
26180
26181         /* Note ShrV128 gets masked by 127 so a shift of 128 results in
26182          * the value not being shifted.  A shift of 128 sets the register
26183          * zero.  So if length+1 = 128, just set the value to 0.
26184         */
26185         length_neq_128 = mkNOT1( binop( Iop_CmpEQ64,
26186                                         mkexpr( length),
26187                                         mkU64( 0x1F ) ) );
26188
26189         assign( masked_out,
26190                 binop( Iop_AndV128,
26191                        binop( Iop_64HLtoV128,
26192                               unop( Iop_1Sto64, length_neq_128 ),
26193                               unop( Iop_1Sto64, length_neq_128 ) ),
26194                        binop( Iop_ShrV128,
26195                               mkexpr( vB ),
26196                               unop( Iop_64to8,
26197                                     binop( Iop_Mul64,
26198                                            mkU64( 4 ),
26199                                            binop( Iop_Add64,
26200                                                   mkU64( 1 ),
26201                                                   mkexpr( length ) ) ) ) )
26202                        ) );
26203
26204         /* Overflow occurs if any of the left most 31-length digits of vB
26205          * are non-zero.
26206          */
26207         overflow = mkNOT1( BCDstring_zero( mkexpr( masked_out ) ) );
26208
26209         value = binop( Iop_AndV128,
26210                        binop( Iop_64HLtoV128,
26211                               mkU64( 0xFFFFFFFFFFFFFFFF ),
26212                               mkU64( value_mask_low ) ),
26213                        mkexpr( vB ) );
26214
26215
26216         if ( opc2 == 0x101 ) {     // bcdtrunc.
26217            /* Check if all of the non-sign digits are zero */
26218            zero = BCDstring_zero( binop( Iop_AndV128,
26219                                          binop( Iop_64HLtoV128,
26220                                                 mkU64( 0xFFFFFFFFFFFFFFFF ),
26221                                                 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26222                                          value ) );
26223
26224            /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26225             * codes 0xB and 0xD are negative.
26226             */
26227            sign_digit = binop( Iop_And64, mkU64( 0xF ),
26228                                unop( Iop_V128to64, mkexpr( vB ) ) );
26229
26230            sign = mkOR1( binop( Iop_CmpEQ64,
26231                                 sign_digit,
26232                                 mkU64 ( 0xB ) ),
26233                          binop( Iop_CmpEQ64,
26234                                 sign_digit,
26235                                 mkU64 ( 0xD ) ) );
26236            neg = mkAND1( sign, mkNOT1( zero ) );
26237
26238            /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
26239            pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26240
26241            /* Note can't use pos or neg here since they are ANDed with zero,
26242               use sign instead.
26243            */
26244            if (ps == 0) {
26245               new_sign_val = binop( Iop_Or64,
26246                                     unop( Iop_1Uto64, sign ),
26247                                     mkU64( 0xC ) );
26248            } else {
26249               new_sign_val = binop( Iop_Xor64,
26250                                     binop( Iop_Shl64,
26251                                            unop( Iop_1Uto64, sign ),
26252                                            mkU8 ( 1 ) ),
26253                                     mkU64( 0xF ) );
26254            }
26255            valid =
26256               unop( Iop_64to32,
26257                     is_BCDstring128( vbi, /* Signed */True, mkexpr( vB ) ) );
26258
26259         } else {   // bcdutrunc.
26260            /* Check if all of the digits are zero */
26261            zero = BCDstring_zero( value );
26262
26263            /* unsigned value, need to make CC code happy */
26264            neg = mkU1( 0 );
26265
26266            /* Pos position AKA gt = 1 if (not eq zero) */
26267            pos = mkNOT1( zero );
26268            valid =
26269               unop( Iop_64to32,
26270                     is_BCDstring128( vbi, /* Unsigned */False,
26271                                      mkexpr( vB ) ) );
26272         }
26273
26274         /* If vB is not valid, the result is undefined, but we need to
26275          * match the hardware so the output of the test suite will match.
26276          * Hardware sets result to 0x0.
26277          */
26278         result = binop( Iop_AndV128,
26279                         mkV128( 0xFFFF ),
26280                         binop( Iop_ShrV128,
26281                                binop( Iop_ShlV128, value, shift ),
26282                                shift ) );
26283
26284         if ( opc2 == 0x101) {     // bcdtrunc.
26285            putVReg( vRT_addr, binop( Iop_OrV128,
26286                                      binop( Iop_64HLtoV128,
26287                                             mkU64( 0 ),
26288                                             new_sign_val ),
26289                                      result ) );
26290         } else {
26291            putVReg( vRT_addr, result );
26292         }
26293      }
26294      break;
26295
26296   case 0x181:   // bcdctz., bcdctn., bcdcfz., bcdcfn., bcdsetsgn.,
26297                 // bcdcfsq., bcdctsq.
26298      {
26299         UInt inst_select = IFIELD( theInstr, 16, 5);
26300
26301         switch (inst_select) {
26302         case 0:  // bcdctsq.  (Decimal Convert to Signed Quadword VX-form)
26303            {
26304               IRExpr *sign;
26305
26306               /* The instruction takes a 32-bit integer in a vector source
26307                * register and returns the signed packed decimal number
26308                * in a vector register.  The source integer needs to be moved
26309                * from the V128 to an I32 for the Iop.
26310                */
26311
26312               DIP("bcdctsq v%d, v%d\n", vRT_addr, vRB_addr);
26313
26314               putVReg( vRT_addr, unop( Iop_BCD128toI128S, mkexpr( vB ) ) );
26315
26316               sign =  binop( Iop_And64,
26317                              unop( Iop_V128to64, mkexpr( vB ) ),
26318                              mkU64( 0xF ) );
26319               zero = mkAND1( binop( Iop_CmpEQ64,
26320                                     unop( Iop_V128HIto64, mkexpr( vB ) ),
26321                                     mkU64( 0x0 ) ),
26322                              binop( Iop_CmpEQ64,
26323                                     binop( Iop_And64,
26324                                            unop( Iop_V128to64, mkexpr( vB ) ),
26325                                            mkU64( 0xFFFFFFF0 ) ),
26326                                     mkU64( 0x0 ) ) );
26327               pos = mkAND1( mkNOT1( zero ),
26328                             mkOR1( mkOR1( binop( Iop_CmpEQ64,
26329                                                  sign, mkU64( 0xA ) ),
26330                                           binop( Iop_CmpEQ64,
26331                                                  sign, mkU64( 0xC ) ) ),
26332                                    mkOR1( binop( Iop_CmpEQ64,
26333                                                  sign, mkU64( 0xE ) ),
26334                                           binop( Iop_CmpEQ64,
26335                                                  sign, mkU64( 0xF ) ) ) ) );
26336               neg = mkAND1( mkNOT1( zero ),
26337                             mkOR1( binop( Iop_CmpEQ64, sign, mkU64( 0xB ) ),
26338                                    binop( Iop_CmpEQ64, sign, mkU64( 0xD ) ) ) );
26339
26340               /* Check each of the nibbles for a valid digit 0 to 9 */
26341               valid =
26342                  unop( Iop_64to32,
26343                        is_BCDstring128( vbi, /* Signed */True,
26344                                         mkexpr( vB ) ) );
26345               overflow = mkU1( 0 );  // not used
26346            }
26347            break;
26348
26349         case 2:  // bcdcfsq. (Decimal Convert from Signed Quadword VX-form)
26350            {
26351               IRExpr *pos_upper_gt, *pos_upper_eq, *pos_lower_gt;
26352               IRExpr *neg_upper_lt, *neg_upper_eq, *neg_lower_lt;
26353
26354               DIP("bcdcfsq v%d, v%d, %d\n", vRT_addr, vRB_addr, ps);
26355
26356               /* The instruction takes a signed packed decimal number and
26357                * returns the integer value in the vector register.  The Iop
26358                * returns an I32 which needs to be moved to the destination
26359                * vector register.
26360                */
26361               putVReg( vRT_addr,
26362                        binop( Iop_I128StoBCD128, mkexpr( vB ), mkU8( ps ) ) );
26363
26364               zero = mkAND1( binop( Iop_CmpEQ64, mkU64( 0 ),
26365                                     unop( Iop_V128to64, mkexpr( vB ) ) ),
26366                              binop( Iop_CmpEQ64, mkU64( 0 ),
26367                                     unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
26368               pos = mkAND1( mkNOT1 ( zero ),
26369                             binop( Iop_CmpEQ64, mkU64( 0 ),
26370                                    binop( Iop_And64,
26371                                           unop( Iop_V128HIto64,
26372                                                 mkexpr( vB ) ),
26373                                           mkU64( 0x8000000000000000UL ) ) ) );
26374               neg = mkAND1( mkNOT1 ( zero ),
26375                             binop( Iop_CmpEQ64, mkU64( 0x8000000000000000UL ),
26376                                    binop( Iop_And64,
26377                                           unop( Iop_V128HIto64,
26378                                                 mkexpr( vB ) ),
26379                                           mkU64( 0x8000000000000000UL ) ) ) );
26380
26381               /* Overflow occurs if: vB > 10^31-1 OR vB < -10^31-1
26382                * do not have a 128 bit compare.  Will have to compare the
26383                * upper 64 bit and athe lower 64 bits.  If the upper 64-bits
26384                * are equal then overflow if the lower 64 bits of vB is greater
26385                * otherwise if the upper bits of vB is greater then the max
26386                * for the upper 64-bits then overflow
26387                *
26388                *     10^31-1 = 0x7E37BE2022C0914B267FFFFFFF
26389                */
26390               pos_upper_gt = binop( Iop_CmpLT64U,
26391                                     mkU64( 0x7E37BE2022 ),
26392                                     unop( Iop_V128HIto64, mkexpr( vB ) ) );
26393               pos_upper_eq = binop( Iop_CmpEQ64,
26394                                     unop( Iop_V128HIto64, mkexpr( vB ) ),
26395                                     mkU64( 0x7E37BE2022 ) );
26396               pos_lower_gt = binop( Iop_CmpLT64U,
26397                                     mkU64( 0x0914B267FFFFFFF ),
26398                                     unop( Iop_V128to64, mkexpr( vB ) ) );
26399               /* -10^31-1 =  0X81C841DFDD3F6EB4D97FFFFFFF */
26400               neg_upper_lt = binop( Iop_CmpLT64U,
26401                                     mkU64( 0X81C841DFDD ),
26402                                     unop( Iop_V128HIto64, mkexpr( vB ) ) );
26403               neg_upper_eq = binop( Iop_CmpEQ64,
26404                                     unop( Iop_V128HIto64, mkexpr( vB ) ),
26405                                     mkU64( 0X81C841DFDD ) );
26406               neg_lower_lt = binop( Iop_CmpLT64U,
26407                                     mkU64( 0x3F6EB4D97FFFFFFF ),
26408                                     unop( Iop_V128to64, mkexpr( vB ) ) );
26409
26410               /* calculate overflow, masking for positive and negative */
26411               overflow = mkOR1( mkAND1( pos,
26412                                         mkOR1( pos_upper_gt,
26413                                                mkAND1( pos_upper_eq,
26414                                                        pos_lower_gt ) ) ),
26415                                 mkAND1( neg,
26416                                         mkOR1( neg_upper_lt,
26417                                                mkAND1( neg_upper_eq,
26418                                                        neg_lower_lt )
26419                                                ) ) );
26420               valid = mkU32( 1 );
26421            }
26422            break;
26423
26424         case 4:  // bcdctz. (Decimal Convert to Zoned VX-form)
26425            {
26426               IRExpr *ox_flag, *sign, *vrb_nibble30;
26427               int neg_bit_shift;
26428               unsigned int upper_byte, sign_byte;
26429               IRTemp tmp = newTemp( Ity_V128 );
26430
26431               DIP("bcdctz. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
26432
26433               if (ps == 0) {
26434                  upper_byte = 0x30;
26435                  sign_byte = 0x30;
26436                  neg_bit_shift = 4+2;  /* sign byte is in bits [7:4] */
26437               } else {
26438                  upper_byte = 0xF0;
26439                  sign_byte = 0xC0;
26440                  neg_bit_shift = 4+0;
26441               }
26442
26443               /* Grab vB bits[7:4].  It goes into bits [3:0] of the
26444                * result.
26445                */
26446               vrb_nibble30 = binop( Iop_Shr64,
26447                                     binop( Iop_And64,
26448                                            unop( Iop_V128to64, mkexpr( vB ) ),
26449                                            mkU64( 0xF0 ) ),
26450                                     mkU8( 4 ) );
26451
26452               /* Upper 24 hex digits of VB, i.e. hex digits vB[0:23],
26453                * must be zero for the value to be zero.  This goes
26454                * in the overflow position of the condition code register.
26455                */
26456               ox_flag = binop( Iop_CmpEQ64,
26457                                     binop( Iop_And64,
26458                                            unop( Iop_V128to64, mkexpr( vB ) ),
26459                                            mkU64( 0xFFFFFFFFFFFFFFFF ) ),
26460                                mkU64( 0 ) );
26461
26462               /* zero is the same as eq_flag */
26463               zero = mkAND1( binop( Iop_CmpEQ64,
26464                                     binop( Iop_And64,
26465                                            unop( Iop_V128HIto64, mkexpr( vB ) ),
26466                                            mkU64( 0xFFFFFFFFFFFFFFFF ) ),
26467                                     mkU64( 0 ) ),
26468                              binop( Iop_CmpEQ64,
26469                                     binop( Iop_And64,
26470                                            unop( Iop_V128to64, mkexpr( vB ) ),
26471                                            mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26472                                     mkU64( 0 ) ) );
26473
26474               /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26475                * codes 0xB and 0xD are negative.
26476                */
26477               sign_digit = binop( Iop_And64, mkU64( 0xF ),
26478                                   unop( Iop_V128to64, mkexpr( vB ) ) );
26479
26480               /* The negative value goes in the LT bit position of the
26481                * condition code register. Set neg if the sign of vB
26482                * is negative and zero is true.
26483                */
26484               sign = mkOR1( binop( Iop_CmpEQ64,
26485                                    sign_digit,
26486                                    mkU64 ( 0xB ) ),
26487                             binop( Iop_CmpEQ64,
26488                                    sign_digit,
26489                                    mkU64 ( 0xD ) ) );
26490               neg = mkAND1( sign, mkNOT1( zero ) );
26491
26492               /* The positive value goes in the LT bit position of the
26493                * condition code register. Set positive if the sign of the
26494                * value is not negative.
26495                */
26496               pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26497
26498               assign( tmp,
26499                       convert_to_zoned( vbi, mkexpr( vB ),
26500                                         mkU64( upper_byte ) ) );
26501
26502               /* Insert the sign based on ps and sign of vB
26503                * in the lower byte.
26504                */
26505               putVReg( vRT_addr,
26506                        binop( Iop_OrV128,
26507                               binop( Iop_64HLtoV128,
26508                                      mkU64( 0 ),
26509                                      vrb_nibble30 ),
26510                               binop( Iop_OrV128,
26511                                      mkexpr( tmp ),
26512                                      binop( Iop_64HLtoV128,
26513                                             mkU64( 0 ),
26514                                             binop( Iop_Or64,
26515                                                    mkU64( sign_byte ),
26516                                                    binop( Iop_Shl64,
26517                                                           unop( Iop_1Uto64,
26518                                                                 sign ),
26519                                                           mkU8( neg_bit_shift)
26520                               ) ) ) ) ) );
26521
26522               /* A valid number must have a value that is less then or
26523                * equal to 10^16 - 1.  This is checked by making sure
26524                * bytes [31:16] of vB are zero.
26525                */
26526               in_range = binop( Iop_CmpEQ64,
26527                                 binop( Iop_And64,
26528                                        mkU64( 0xFFFFFFFFFFFFFFF0 ),
26529                                        unop( Iop_V128HIto64, mkexpr( vB ) ) ),
26530                                 mkU64( 0 ) );
26531
26532               /* overflow is set if ox_flag or not in_inrange.  Setting is
26533                * ORed with the other condition code values.
26534                */
26535               overflow = mkOR1( ox_flag, mkNOT1( in_range ) );
26536
26537               /* The sign code must be between 0xA and 0xF and all digits are
26538                * between 0x0 and 0x9. The vB must be in range to be valid.
26539                * If not valid, condition code set to 0x0001.
26540                */
26541               valid =
26542                  unop( Iop_64to32,
26543                        is_BCDstring128( vbi, /* Signed */True,
26544                                         mkexpr( vB ) ) );
26545            }
26546            break;
26547
26548         case 5:  // bcdctn. (Decimal Convert to National VX-form)
26549            {
26550               IRExpr *ox_flag, *sign;
26551               IRTemp tmp = newTemp( Ity_V128 );;
26552
26553               DIP("bcdctn. v%d,v%d\n", vRT_addr, vRB_addr);
26554
26555               value = binop( Iop_And64,
26556                              mkU64( 0xFFFFFFFF ),
26557                              unop( Iop_V128to64, mkexpr( vB ) ) );
26558
26559               /* A valid number must have a value that is less then or
26560                * equal to 10^7 - 1.  This is checked by making sure
26561                * bytes [31:8] of vB are zero.
26562                */
26563               in_range = mkAND1( binop( Iop_CmpEQ64,
26564                                         unop( Iop_V128HIto64, mkexpr( vB ) ),
26565                                         mkU64( 0 ) ),
26566                                  binop( Iop_CmpEQ64,
26567                                         binop( Iop_Shr64,
26568                                                unop( Iop_V128to64,
26569                                                      mkexpr( vB ) ),
26570                                                mkU8( 32 ) ),
26571                                         mkU64( 0 ) ) );
26572
26573               /* The sign code must be between 0xA and 0xF and all digits are
26574                *  between 0x0 and 0x9.
26575                */
26576               valid =
26577                  unop( Iop_64to32,
26578                        is_BCDstring128( vbi, /* Signed */True,
26579                                         mkexpr( vB ) ) );
26580
26581               /* Upper 24 hex digits of VB, i.e. hex ditgits vB[0:23],
26582                * must be zero for the ox_flag to be zero.  This goes
26583                * in the LSB position (variable overflow) of the
26584                * condition code register.
26585                */
26586               ox_flag =
26587                  mkNOT1( mkAND1( binop( Iop_CmpEQ64,
26588                                         binop( Iop_And64,
26589                                                unop( Iop_V128HIto64,
26590                                                      mkexpr( vB ) ),
26591                                                mkU64( 0xFFFFFFFFFFFFFFFF ) ),
26592                                         mkU64( 0 ) ),
26593                                  binop( Iop_CmpEQ64,
26594                                         binop( Iop_And64,
26595                                                unop( Iop_V128to64,
26596                                                      mkexpr( vB ) ),
26597                                                mkU64( 0xFFFFFFFF00000000 ) ),
26598                                         mkU64( 0 ) ) ) );
26599
26600               /* Set zero to 1 if all of the bytes in vB are zero.  This is
26601                * used when setting the lt_flag (variable neg) and the gt_flag
26602                * (variable pos).
26603                */
26604               zero = mkAND1( binop( Iop_CmpEQ64,
26605                                     binop( Iop_And64,
26606                                            unop( Iop_V128HIto64,
26607                                                  mkexpr( vB ) ),
26608                                            mkU64( 0xFFFFFFFFFFFFFFFF ) ),
26609                                         mkU64( 0 ) ),
26610                              binop( Iop_CmpEQ64,
26611                                      binop( Iop_And64,
26612                                             unop( Iop_V128to64, mkexpr( vB ) ),
26613                                             mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26614                                      mkU64( 0 ) ) );
26615
26616               /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26617                * codes 0xB and 0xD are negative.
26618                */
26619               sign_digit = binop( Iop_And64, mkU64( 0xF ), value );
26620
26621               /* The negative value goes in the LT bit position of the
26622                * condition code register. Set neg if the sign of the
26623                * value is negative and the value is zero.
26624                */
26625               sign = mkOR1( binop( Iop_CmpEQ64,
26626                                    sign_digit,
26627                                    mkU64 ( 0xB ) ),
26628                             binop( Iop_CmpEQ64,
26629                                    sign_digit,
26630                                    mkU64 ( 0xD ) ) );
26631               neg = mkAND1( sign, mkNOT1( zero ) );
26632
26633               /* The positive value goes in the LT bit position of the
26634                * condition code register. Set neg if the sign of the
26635                * value is not negative and the value is zero.
26636                */
26637               pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26638
26639               assign( tmp,
26640                       convert_to_national( vbi, mkexpr( vB ) ) );
26641
26642               /* If vB is positive insert sign value 0x002B, otherwise
26643                * insert 0x002D for negative. Have to use sign not neg
26644                * because neg has been ANDed with zero.  This is 0x29
26645                * OR'd with (sign << 1 | NOT sign) << 1.
26646                * sign = 1 if vB is negative.
26647                */
26648               putVReg( vRT_addr,
26649                        binop( Iop_OrV128,
26650                               mkexpr( tmp ),
26651                               binop( Iop_64HLtoV128,
26652                                      mkU64( 0 ),
26653                                      binop( Iop_Or64,
26654                                             mkU64( 0x29 ),
26655                                             binop( Iop_Or64,
26656                                                    binop( Iop_Shl64,
26657                                                           unop( Iop_1Uto64,
26658                                                                 sign ),
26659                                                           mkU8( 2 ) ),
26660                                                    binop( Iop_Shl64,
26661                                                           unop( Iop_1Uto64,
26662                                                                 mkNOT1(sign)),
26663                                                           mkU8( 1 ) )
26664                                                    ) ) ) ) );
26665
26666
26667               /* The sign code must be between 0xA and 0xF and all digits are
26668                *  between 0x0 and 0x9. The vB must be in range to be valid.
26669                */
26670               valid =
26671                  unop( Iop_64to32,
26672                        is_BCDstring128( vbi, /* Signed */True,
26673                                         mkexpr( vB ) ) );
26674
26675               overflow = ox_flag;
26676            }
26677            break;
26678
26679         case 6:  // bcdcfz. (Decimal Convert From Zoned VX-form)
26680            {
26681               IRExpr *sign;
26682               IRTemp tmp = newTemp( Ity_V128 );;
26683
26684               DIP("bcdcfz. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
26685
26686               valid = unop( Iop_1Uto32, is_Zoned_decimal( vB, ps ) );
26687
26688               assign( tmp,
26689                       convert_from_zoned( vbi, mkexpr( vB ) ) );
26690
26691               /* If the result of checking the lower 4 bits of each 8-bit
26692                * value is zero, then the "number" was zero.
26693                */
26694               zero =
26695                  binop( Iop_CmpEQ64,
26696                  binop( Iop_Or64,
26697                     binop( Iop_And64,
26698                                          unop( Iop_V128to64, mkexpr( vB ) ),
26699                                          mkU64( 0x0F0F0F0F0F0F0F0FULL ) ),
26700                                   binop( Iop_And64,
26701                                          unop( Iop_V128to64, mkexpr( vB ) ),
26702                  mkU64( 0x0F0F0F0F0F0F0F0FULL ) ) ),
26703                  mkU64( 0 ) );
26704
26705               /* Sign bit is in bit 6 of vB. */
26706               sign_digit = binop( Iop_And64, mkU64( 0xF0 ),
26707                                   unop( Iop_V128to64,  mkexpr( vB ) ) );
26708
26709               if ( ps == 0 ) {
26710                  /* sign will be equal to 0 for positive number */
26711                  sign = binop( Iop_CmpEQ64,
26712                                binop( Iop_And64,
26713                                       sign_digit,
26714                                       mkU64( 0x40 ) ),
26715                                mkU64( 0x40 ) );
26716               } else {
26717                  sign = mkOR1(
26718                               binop( Iop_CmpEQ64, sign_digit, mkU64( 0xB0 ) ),
26719                               binop( Iop_CmpEQ64, sign_digit, mkU64( 0xD0 ) ) );
26720               }
26721
26722               /* The negative value goes in the LT bit position of the
26723                * condition code register. Set neg if the sign of the
26724                * value is negative and the value is zero.
26725                */
26726               neg = mkAND1( sign, mkNOT1( zero ) );
26727
26728               /* The positive value goes in the GT bit position of the
26729                * condition code register. Set neg if the sign of the
26730                * value is not negative and the value is zero.
26731                */
26732               pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26733
26734               /* sign of the result is 0xC for positive, 0xD for negative */
26735               putVReg( vRT_addr,
26736                               binop( Iop_OrV128,
26737                                      mkexpr( tmp ),
26738                                      binop( Iop_64HLtoV128,
26739                                             mkU64( 0 ),
26740                                             binop( Iop_Or64,
26741                                                    mkU64( 0xC ),
26742                                                    unop( Iop_1Uto64, sign )
26743                                                    ) ) ) );
26744               /* For this instructions the LSB position in the CC
26745                * field, the overflow position in the other instructions,
26746                * is given by 0.  There is nothing to or with LT, EQ or GT.
26747                */
26748               overflow = mkU1( 0 );
26749            }
26750            break;
26751
26752         case 7:  // bcdcfn. (Decimal Convert From National VX-form)
26753            {
26754               IRTemp hword_7 = newTemp( Ity_I64 );
26755               IRExpr *sign;
26756               IRTemp tmp = newTemp( Ity_I64 );;
26757
26758               DIP("bcdcfn. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
26759
26760               /* check that the value is valid */
26761               valid = unop( Iop_1Uto32, is_National_decimal( vB ) );
26762
26763               assign( hword_7, binop( Iop_And64,
26764                                       unop( Iop_V128to64, mkexpr( vB ) ),
26765                                       mkU64( 0xFFF ) ) );
26766               /* sign = 1 if vB is negative */
26767               sign = binop( Iop_CmpEQ64, mkexpr( hword_7 ), mkU64( 0x002D ) );
26768
26769               assign( tmp, convert_from_national( vbi, mkexpr( vB ) ) );
26770
26771               /* If the result of checking the lower 4 bits of each 16-bit
26772                * value is zero, then the "number" was zero.
26773                */
26774               zero =
26775                  binop( Iop_CmpEQ64,
26776                         binop( Iop_Or64,
26777                                binop( Iop_And64,
26778                                       unop( Iop_V128HIto64, mkexpr( vB ) ),
26779                                       mkU64( 0x000F000F000F000FULL ) ),
26780                                binop( Iop_And64,
26781                                       unop( Iop_V128to64, mkexpr( vB ) ),
26782                                       mkU64( 0x000F000F000F0000ULL ) ) ),
26783                         mkU64( 0 ) );
26784
26785
26786               /* The negative value goes in the LT bit position of the
26787                * condition code register. Set neg if the sign of the
26788               * value is negative and the value is zero.
26789                */
26790               neg = mkAND1( sign, mkNOT1( zero ) );
26791
26792               /* The positive value goes in the GT bit position of the
26793                * condition code register. Set neg if the sign of the
26794                * value is not negative and the value is zero.
26795                */
26796               pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26797
26798               /* For this instructions the LSB position in the CC
26799                * field, the overflow position in the other instructions,
26800                * is given by invalid.  There is nothing to OR with the valid
26801                * flag.
26802                */
26803               overflow = mkU1( 0 );
26804
26805               /* sign of the result is:
26806                  ( 0b1100 OR neg) OR (ps OR  (ps AND pos) << 1 )
26807               */
26808
26809               putVReg( vRT_addr,
26810                        binop( Iop_64HLtoV128,
26811                               mkU64( 0 ),
26812                               binop( Iop_Or64,
26813                                      binop( Iop_Or64,
26814                                             binop( Iop_Shl64,
26815                                                    binop( Iop_And64,
26816                                                           mkU64( ps ),
26817                                                           unop( Iop_1Uto64,
26818                                                                 mkNOT1(sign))),
26819                                                    mkU8( 1 ) ),
26820                                             mkU64( ps ) ),
26821                                      binop( Iop_Or64,
26822                                             binop( Iop_Or64,
26823                                                    mkU64( 0xC ),
26824                                                    unop( Iop_1Uto64, sign ) ),
26825                                             mkexpr( tmp ) ) ) ) );
26826
26827            }
26828            break;
26829
26830         case 31:  // bcdsetsgn. (BCD set sign)
26831            {
26832               IRExpr *new_sign_val, *sign;
26833
26834               DIP("bcdsetsgn. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
26835
26836               value = binop( Iop_AndV128,
26837                              binop( Iop_64HLtoV128,
26838                                     mkU64( 0xFFFFFFFFFFFFFFFF ),
26839                                     mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26840                              mkexpr( vB ) );
26841               zero = BCDstring_zero( value );
26842
26843               /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26844                * codes 0xB and 0xD are negative.
26845                */
26846               sign_digit = binop( Iop_And64, mkU64( 0xF ),
26847                                   unop( Iop_V128to64, mkexpr( vB ) ) );
26848
26849               sign = mkOR1( binop( Iop_CmpEQ64,
26850                                    sign_digit,
26851                                    mkU64 ( 0xB ) ),
26852                             binop( Iop_CmpEQ64,
26853                                    sign_digit,
26854                                    mkU64 ( 0xD ) ) );
26855               neg = mkAND1( sign, mkNOT1( zero ) );
26856
26857               pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26858
26859               valid =
26860                  unop( Iop_64to32,
26861                        is_BCDstring128( vbi, /* Signed */True,
26862                                         mkexpr( vB ) ) );
26863
26864               /* if PS = 0
26865                     vB positive, sign is C
26866                     vB negative, sign is D
26867                  if PS = 1
26868                     vB positive, sign is F
26869                     vB negative, sign is D
26870                  Note can't use pos or neg here since they are ANDed with
26871                  zero, use sign instead.
26872               */
26873               if (ps == 0) {
26874                  new_sign_val = binop( Iop_Or64,
26875                                        unop( Iop_1Uto64, sign ),
26876                                        mkU64( 0xC ) );
26877
26878               } else {
26879                  new_sign_val = binop( Iop_Xor64,
26880                                        binop( Iop_Shl64,
26881                                               unop( Iop_1Uto64, sign ),
26882                                               mkU8( 1 ) ),
26883                                        mkU64( 0xF ) );
26884               }
26885
26886               putVReg( vRT_addr, binop( Iop_OrV128,
26887                                         binop( Iop_64HLtoV128,
26888                                                mkU64( 0 ),
26889                                                new_sign_val ),
26890                                         value ) );
26891               /* For this instructions the LSB position in the CC
26892                * field, the overflow position in the other instructions,
26893                * is given by invalid.
26894                */
26895               overflow = unop( Iop_32to1, unop( Iop_Not32, valid ) );
26896            }
26897            break;
26898
26899         default:
26900            vex_printf("dis_av_bcd(ppc)(invalid inst_select)\n");
26901            return False;
26902         }
26903      }
26904      break;
26905
26906   default:
26907      vex_printf("dis_av_bcd(ppc)(opc2)\n");
26908      return False;
26909   }
26910
26911   IRTemp valid_mask = newTemp( Ity_I32 );
26912
26913   assign( valid_mask, unop( Iop_1Sto32, unop( Iop_32to1, valid ) ) );
26914
26915   /* set CR field 6 to:
26916    *    0b1000  if vB less then 0, i.e. vB is neg and not zero,
26917    *    0b0100  if vB greter then 0,  i.e. vB is pos and not zero,
26918    *    0b0010  if vB equals 0,
26919    *    0b0001  if vB is invalid  over rules lt, gt, eq
26920    */
26921   assign( eq_lt_gt,
26922           binop( Iop_Or32,
26923                  binop( Iop_Shl32,
26924                         unop( Iop_1Uto32, neg ),
26925                         mkU8( 3 ) ),
26926                  binop( Iop_Or32,
26927                         binop( Iop_Shl32,
26928                                unop( Iop_1Uto32, pos ),
26929                                mkU8( 2 ) ),
26930                         binop( Iop_Shl32,
26931                               unop( Iop_1Uto32, zero ),
26932                                mkU8( 1 ) ) ) ) );
26933   /* valid is 1 if it is a valid number, complement and put in the
26934    * invalid bit location, overriding ls, eq, gt, overflow.
26935    */
26936   putGST_field( PPC_GST_CR,
26937                 binop( Iop_Or32,
26938                        binop( Iop_And32,
26939                               mkexpr( valid_mask ),
26940                               binop( Iop_Or32,
26941                                      mkexpr( eq_lt_gt ),
26942                                      unop( Iop_1Uto32, overflow ) ) ),
26943                        binop( Iop_And32,
26944                               unop( Iop_Not32, mkexpr( valid_mask ) ),
26945                               mkU32( 1 ) ) ),
26946                 6 );
26947   return True;
26948}
26949
26950/*
26951  AltiVec Floating Point Arithmetic Instructions
26952*/
26953static Bool dis_av_fp_arith ( UInt theInstr )
26954{
26955   /* VA-Form */
26956   UChar opc1     = ifieldOPC(theInstr);
26957   UChar vD_addr  = ifieldRegDS(theInstr);
26958   UChar vA_addr  = ifieldRegA(theInstr);
26959   UChar vB_addr  = ifieldRegB(theInstr);
26960   UChar vC_addr  = ifieldRegC(theInstr);
26961   UInt  opc2=0;
26962
26963   IRTemp vA = newTemp(Ity_V128);
26964   IRTemp vB = newTemp(Ity_V128);
26965   IRTemp vC = newTemp(Ity_V128);
26966   assign( vA, getVReg(vA_addr));
26967   assign( vB, getVReg(vB_addr));
26968   assign( vC, getVReg(vC_addr));
26969
26970   if (opc1 != 0x4) {
26971      vex_printf("dis_av_fp_arith(ppc)(instr)\n");
26972      return False;
26973   }
26974
26975   IRTemp rm = newTemp(Ity_I32);
26976   assign(rm, get_IR_roundingmode());
26977
26978   opc2 = IFIELD( theInstr, 0, 6 );
26979   switch (opc2) {
26980   case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
26981      DIP("vmaddfp v%d,v%d,v%d,v%d\n",
26982          vD_addr, vA_addr, vC_addr, vB_addr);
26983      putVReg( vD_addr,
26984               triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
26985                     mkexpr(vB),
26986                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
26987                           mkexpr(vA), mkexpr(vC))) );
26988      return True;
26989
26990   case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
26991      DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
26992          vD_addr, vA_addr, vC_addr, vB_addr);
26993      putVReg( vD_addr,
26994               triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
26995                     mkexpr(vB),
26996                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
26997                           mkexpr(vA), mkexpr(vC))) );
26998      return True;
26999   }
27000
27001   default:
27002     break; // Fall through...
27003   }
27004
27005   opc2 = IFIELD( theInstr, 0, 11 );
27006   switch (opc2) {
27007   case 0x00A: // vaddfp (Add FP, AV p137)
27008      DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
27009      putVReg( vD_addr, triop(Iop_Add32Fx4,
27010                              mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
27011      return True;
27012
27013  case 0x04A: // vsubfp (Subtract FP, AV p261)
27014      DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
27015      putVReg( vD_addr, triop(Iop_Sub32Fx4,
27016                              mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
27017      return True;
27018
27019   case 0x40A: // vmaxfp (Maximum FP, AV p178)
27020      DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
27021      putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
27022      return True;
27023
27024   case 0x44A: // vminfp (Minimum FP, AV p187)
27025      DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
27026      putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
27027      return True;
27028
27029   default:
27030      break; // Fall through...
27031   }
27032
27033
27034   if (vA_addr != 0) {
27035      vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
27036      return False;
27037   }
27038
27039   switch (opc2) {
27040   case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
27041      DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
27042      putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) );
27043      return True;
27044
27045   case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
27046      DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
27047      putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) );
27048      return True;
27049
27050   case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
27051      DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
27052      DIP(" => not implemented\n");
27053      return False;
27054
27055   case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
27056      DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
27057      DIP(" => not implemented\n");
27058      return False;
27059
27060   default:
27061      vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
27062      return False;
27063   }
27064   return True;
27065}
27066
27067/*
27068  AltiVec Floating Point Compare Instructions
27069*/
27070static Bool dis_av_fp_cmp ( UInt theInstr )
27071{
27072   /* VXR-Form */
27073   UChar opc1     = ifieldOPC(theInstr);
27074   UChar vD_addr  = ifieldRegDS(theInstr);
27075   UChar vA_addr  = ifieldRegA(theInstr);
27076   UChar vB_addr  = ifieldRegB(theInstr);
27077   UChar flag_rC  = ifieldBIT10(theInstr);
27078   UInt  opc2     = IFIELD( theInstr, 0, 10 );
27079
27080   Bool cmp_bounds = False;
27081
27082   IRTemp vA = newTemp(Ity_V128);
27083   IRTemp vB = newTemp(Ity_V128);
27084   IRTemp vD = newTemp(Ity_V128);
27085   assign( vA, getVReg(vA_addr));
27086   assign( vB, getVReg(vB_addr));
27087
27088   if (opc1 != 0x4) {
27089      vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
27090      return False;
27091   }
27092
27093   switch (opc2) {
27094   case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
27095      DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
27096                                      vD_addr, vA_addr, vB_addr);
27097      assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
27098      break;
27099
27100   case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
27101      DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
27102                                      vD_addr, vA_addr, vB_addr);
27103      assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
27104      break;
27105
27106   case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
27107      DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
27108                                      vD_addr, vA_addr, vB_addr);
27109      assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
27110      break;
27111
27112   case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
27113      IRTemp gt      = newTemp(Ity_V128);
27114      IRTemp lt      = newTemp(Ity_V128);
27115      IRTemp zeros   = newTemp(Ity_V128);
27116      DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
27117                                     vD_addr, vA_addr, vB_addr);
27118      cmp_bounds = True;
27119      assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
27120
27121      /* Note: making use of fact that the ppc backend for compare insns
27122         return zero'd lanes if either of the corresponding arg lanes is
27123         a nan.
27124
27125         Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
27126         need this for the other compares too (vcmpeqfp etc)...
27127         Better still, tighten down the spec for compare irops.
27128       */
27129      assign( gt, unop(Iop_NotV128,
27130                       binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
27131      assign( lt, unop(Iop_NotV128,
27132                       binop(Iop_CmpGE32Fx4, mkexpr(vA),
27133                             triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
27134                                   mkexpr(zeros),
27135                                   mkexpr(vB)))) );
27136
27137      // finally, just shift gt,lt to correct position
27138      assign( vD, binop(Iop_ShlN32x4,
27139                        binop(Iop_OrV128,
27140                              binop(Iop_AndV128, mkexpr(gt),
27141                                    unop(Iop_Dup32x4, mkU32(0x2))),
27142                              binop(Iop_AndV128, mkexpr(lt),
27143                                    unop(Iop_Dup32x4, mkU32(0x1)))),
27144                        mkU8(30)) );
27145      break;
27146   }
27147
27148   default:
27149      vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
27150      return False;
27151   }
27152
27153   putVReg( vD_addr, mkexpr(vD) );
27154
27155   if (flag_rC) {
27156      set_AV_CR6( mkexpr(vD), !cmp_bounds );
27157   }
27158   return True;
27159}
27160
27161/*
27162  AltiVec Floating Point Convert/Round Instructions
27163*/
27164static Bool dis_av_fp_convert ( UInt theInstr )
27165{
27166   /* VX-Form */
27167   UChar opc1     = ifieldOPC(theInstr);
27168   UChar vD_addr  = ifieldRegDS(theInstr);
27169   UChar UIMM_5   = ifieldRegA(theInstr);
27170   UChar vB_addr  = ifieldRegB(theInstr);
27171   UInt  opc2     = IFIELD( theInstr, 0, 11 );
27172
27173   IRTemp vB        = newTemp(Ity_V128);
27174   IRTemp vScale    = newTemp(Ity_V128);
27175   IRTemp vInvScale = newTemp(Ity_V128);
27176
27177   float scale, inv_scale;
27178
27179   assign( vB, getVReg(vB_addr));
27180
27181   /* scale = 2^UIMM, cast to float, reinterpreted as uint */
27182   scale = (float)( (unsigned int) 1<<UIMM_5 );
27183   assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
27184   inv_scale = 1/scale;
27185   assign( vInvScale,
27186           unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
27187
27188   if (opc1 != 0x4) {
27189      vex_printf("dis_av_fp_convert(ppc)(instr)\n");
27190      return False;
27191   }
27192
27193   switch (opc2) {
27194   case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
27195      DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
27196      putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
27197                              unop(Iop_I32UtoFx4, mkexpr(vB)),
27198                              mkexpr(vInvScale)) );
27199      return True;
27200
27201   case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
27202      DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
27203
27204      putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
27205                              unop(Iop_I32StoFx4, mkexpr(vB)),
27206                              mkexpr(vInvScale)) );
27207      return True;
27208
27209   case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
27210      DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
27211      putVReg( vD_addr,
27212               unop(Iop_QFtoI32Ux4_RZ,
27213                    triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
27214                          mkexpr(vB), mkexpr(vScale))) );
27215      return True;
27216
27217   case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
27218      DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
27219      putVReg( vD_addr,
27220               unop(Iop_QFtoI32Sx4_RZ,
27221                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
27222                           mkexpr(vB), mkexpr(vScale))) );
27223      return True;
27224
27225   default:
27226     break;    // Fall through...
27227   }
27228
27229   if (UIMM_5 != 0) {
27230      vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
27231      return False;
27232   }
27233
27234   switch (opc2) {
27235   case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
27236      DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
27237      putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
27238      break;
27239
27240   case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
27241      DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
27242      putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
27243      break;
27244
27245   case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
27246      DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
27247      putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
27248      break;
27249
27250   case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
27251      DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
27252      putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
27253      break;
27254
27255   default:
27256      vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
27257      return False;
27258   }
27259   return True;
27260}
27261
27262static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
27263                                       const VexAbiInfo* vbi,
27264                                       /*OUT*/DisResult* dres,
27265                                       Bool (*resteerOkFn)(void*,Addr),
27266                                       void* callback_opaque )
27267{
27268   UInt   opc2      = IFIELD( theInstr, 1, 10 );
27269
27270   switch (opc2) {
27271   case 0x28E: {        //tbegin.
27272      /* The current implementation is to just fail the tbegin and execute
27273       * the failure path.  The failure path is assumed to be functionaly
27274       * equivalent to the transactional path with the needed data locking
27275       * to ensure correctness.  The tend is just a noop and shouldn't
27276       * actually get executed.
27277       *   1) set cr0 to 0x2
27278       *   2) Initialize TFHAR to CIA+4
27279       *   3) Initialize TEXASR
27280       *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
27281       *   5) Continue executing at the next instruction.
27282       */
27283      UInt R = IFIELD( theInstr, 21, 1 );
27284
27285      ULong tm_reason;
27286      UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
27287                               * or treclaim.
27288                               */
27289      UInt persistant = 1;    /* set persistant since we are always failing
27290                               * the tbegin.
27291                               */
27292      UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
27293                                 as the reason for failing the trasaction */
27294      UInt tm_exact   = 1;    /* have exact address for failure */
27295
27296      DIP("tbegin. %u\n", R);
27297
27298      /* Set the CR0 field to indicate the tbegin failed.  Then let
27299       * the code do the branch to the failure path.
27300       *
27301       * 000 || 0  Transaction initiation successful,
27302       *           unnested (Transaction state of
27303       *           Non-transactional prior to tbegin.)
27304       * 010 || 0  Transaction initiation successful, nested
27305       *           (Transaction state of Transactional
27306       *           prior to tbegin.)
27307       * 001 || 0  Transaction initiation unsuccessful,
27308       *           (Transaction state of Suspended prior
27309       *           to tbegin.)
27310       */
27311      putCR321( 0, mkU8( 0x2 ) );
27312
27313      tm_reason = generate_TMreason( failure_code, persistant,
27314                                     nest_overflow, tm_exact );
27315
27316      storeTMfailure( guest_CIA_curr_instr, tm_reason,
27317                      guest_CIA_curr_instr+4 );
27318
27319      return True;
27320
27321      break;
27322   }
27323
27324   case 0x2AE: {        //tend.
27325      /* The tend. is just a noop.  Do nothing */
27326      UInt A = IFIELD( theInstr, 25, 1 );
27327
27328      DIP("tend. %u\n", A);
27329      break;
27330   }
27331
27332   case 0x2EE: {        //tsr.
27333      /* The tsr. is just a noop.  Do nothing */
27334      UInt L = IFIELD( theInstr, 21, 1 );
27335
27336      DIP("tsr. %u\n", L);
27337      break;
27338   }
27339
27340   case 0x2CE: {        //tcheck.
27341      /* The tcheck. is just a noop.  Do nothing */
27342      UInt BF = IFIELD( theInstr, 25, 1 );
27343
27344      DIP("tcheck. %u\n", BF);
27345      break;
27346   }
27347
27348   case 0x30E: {        //tbortwc.
27349      /* The tabortwc. is just a noop.  Do nothing */
27350      UInt TO = IFIELD( theInstr, 25, 1 );
27351      UInt RA = IFIELD( theInstr, 16, 5 );
27352      UInt RB = IFIELD( theInstr, 11, 5 );
27353
27354      DIP("tabortwc. %u,%u,%u\n", TO, RA, RB);
27355      break;
27356   }
27357
27358   case 0x32E: {        //tbortdc.
27359      /* The tabortdc. is just a noop.  Do nothing */
27360      UInt TO = IFIELD( theInstr, 25, 1 );
27361      UInt RA = IFIELD( theInstr, 16, 5 );
27362      UInt RB = IFIELD( theInstr, 11, 5 );
27363
27364      DIP("tabortdc. %u,%u,%u\n", TO, RA, RB);
27365      break;
27366   }
27367
27368   case 0x34E: {        //tbortwci.
27369      /* The tabortwci. is just a noop.  Do nothing */
27370      UInt TO = IFIELD( theInstr, 25, 1 );
27371      UInt RA = IFIELD( theInstr, 16, 5 );
27372      UInt SI = IFIELD( theInstr, 11, 5 );
27373
27374      DIP("tabortwci. %u,%u,%u\n", TO, RA, SI);
27375      break;
27376   }
27377
27378   case 0x36E: {        //tbortdci.
27379      /* The tabortdci. is just a noop.  Do nothing */
27380      UInt TO = IFIELD( theInstr, 25, 1 );
27381      UInt RA = IFIELD( theInstr, 16, 5 );
27382      UInt SI = IFIELD( theInstr, 11, 5 );
27383
27384      DIP("tabortdci. %u,%u,%u\n", TO, RA, SI);
27385      break;
27386   }
27387
27388   case 0x38E: {        //tbort.
27389      /* The tabort. is just a noop.  Do nothing */
27390      UInt RA = IFIELD( theInstr, 16, 5 );
27391
27392      DIP("tabort. %u\n", RA);
27393      break;
27394   }
27395
27396   case 0x3AE: {        //treclaim.
27397      /* The treclaim. is just a noop.  Do nothing */
27398      UInt RA = IFIELD( theInstr, 16, 5 );
27399
27400      DIP("treclaim. %u\n", RA);
27401      break;
27402   }
27403
27404   case 0x3EE: {        //trechkpt.
27405      /* The trechkpt. is just a noop.  Do nothing */
27406      DIP("trechkpt.\n");
27407      break;
27408   }
27409
27410   default:
27411      vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
27412      return False;
27413   }
27414
27415   return True;
27416}
27417
27418
27419/* The 0x3C primary opcode (VSX category) uses several different forms of
27420 * extended opcodes:
27421 *   o XX2-form:
27422 *      - [10:2] (IBM notation [21:29])
27423 *   o XX3-form variants:
27424 *       - variant 1: [10:3] (IBM notation [21:28])
27425 *       - variant 2: [9:3] (IBM notation [22:28])
27426 *       - variant 3: [7:3] (IBM notation [24:28])
27427 *   o XX-4 form:
27428 *      - [10:6] (IBM notation [21:25])
27429 *
27430 * The XX2-form needs bit 0 masked from the standard extended opcode
27431 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
27432 * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
27433 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
27434 * front end since their encoding does not begin at bit 21 like the standard
27435 * format.
27436 *
27437 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
27438 * secondary opcode for such VSX instructions.
27439 *
27440*/
27441
27442
27443struct vsx_insn {
27444   UInt opcode;
27445   const HChar * name;
27446};
27447
27448//  ATTENTION:  Keep this array sorted on the opcocde!!!
27449static struct vsx_insn vsx_xx2[] = {
27450      { 0x14, "xsrsqrtesp" },
27451      { 0x16, "xssqrtsp" },
27452      { 0x18, "xxsel" },
27453      { 0x34, "xsresp" },
27454      { 0x90, "xscvdpuxws" },
27455      { 0x92, "xsrdpi" },
27456      { 0x94, "xsrsqrtedp" },
27457      { 0x96, "xssqrtdp" },
27458      { 0xb0, "xscvdpsxws" },
27459      { 0xb2, "xsrdpiz" },
27460      { 0xb4, "xsredp" },
27461      { 0xd2, "xsrdpip" },
27462      { 0xd4, "xstsqrtdp" },
27463      { 0xd6, "xsrdpic" },
27464      { 0xf2, "xsrdpim" },
27465      { 0x112, "xvrspi" },
27466      { 0x116, "xvsqrtsp" },
27467      { 0x130, "xvcvspsxws" },
27468      { 0x132, "xvrspiz" },
27469      { 0x134, "xvresp" },
27470      { 0x148, "xxspltw" },
27471      { 0x14A, "xxextractuw" },
27472      { 0x150, "xvcvuxwsp" },
27473      { 0x152, "xvrspip" },
27474      { 0x154, "xvtsqrtsp" },
27475      { 0x156, "xvrspic" },
27476      { 0x16A, "xxinsertw" },
27477      { 0x170, "xvcvsxwsp" },
27478      { 0x172, "xvrspim" },
27479      { 0x190, "xvcvdpuxws" },
27480      { 0x192, "xvrdpi" },
27481      { 0x194, "xvrsqrtedp" },
27482      { 0x196, "xvsqrtdp" },
27483      { 0x1b0, "xvcvdpsxws" },
27484      { 0x1b2, "xvrdpiz" },
27485      { 0x1b4, "xvredp" },
27486      { 0x1d0, "xvcvuxwdp" },
27487      { 0x1d2, "xvrdpip" },
27488      { 0x1d4, "xvtsqrtdp" },
27489      { 0x1d6, "xvrdpic" },
27490      { 0x1f0, "xvcvsxwdp" },
27491      { 0x1f2, "xvrdpim" },
27492      { 0x212, "xscvdpsp" },
27493      { 0x216, "xscvdpspn" },
27494      { 0x232, "xxrsp" },
27495      { 0x250, "xscvuxdsp" },
27496      { 0x254, "xststdcsp" },
27497      { 0x270, "xscvsxdsp" },
27498      { 0x290, "xscvdpuxds" },
27499      { 0x292, "xscvspdp" },
27500      { 0x296, "xscvspdpn" },
27501      { 0x2b0, "xscvdpsxds" },
27502      { 0x2b2, "xsabsdp" },
27503      { 0x2b6, "xsxexpdp_xsxigdp" },
27504      { 0x2d0, "xscvuxddp" },
27505      { 0x2d2, "xsnabsdp" },
27506      { 0x2d4, "xststdcdp" },
27507      { 0x2e4, "xsnmsubmdp" },
27508      { 0x2f0, "xscvsxddp" },
27509      { 0x2f2, "xsnegdp" },
27510      { 0x310, "xvcvspuxds" },
27511      { 0x312, "xvcvdpsp" },
27512      { 0x330, "xvcvspsxds" },
27513      { 0x332, "xvabssp" },
27514      { 0x350, "xvcvuxdsp" },
27515      { 0x352, "xvnabssp" },
27516      { 0x370, "xvcvsxdsp" },
27517      { 0x372, "xvnegsp" },
27518      { 0x390, "xvcvdpuxds" },
27519      { 0x392, "xvcvspdp" },
27520      { 0x3b0, "xvcvdpsxds" },
27521      { 0x3b2, "xvabsdp" },
27522      { 0x3b6, "xxbr[h|w|d|q]|xvxexpdp|xvxexpsp|xvxsigdp|xvxsigsp|xvcvhpsp|xvcvsphp|xscvdphp|xscvhpdp" },
27523      { 0x3d0, "xvcvuxddp" },
27524      { 0x3d2, "xvnabsdp" },
27525      { 0x3f2, "xvnegdp" }
27526};
27527#define VSX_XX2_LEN (sizeof vsx_xx2 / sizeof *vsx_xx2)
27528
27529//  ATTENTION:  Keep this array sorted on the opcocde!!!
27530static struct vsx_insn vsx_xx3[] = {
27531      { 0x0,  "xsaddsp" },
27532      { 0x4,  "xsmaddasp" },
27533      { 0x9,  "xsmaddmsp" },
27534      { 0x20, "xssubsp" },
27535      { 0x24, "xsmaddmsp" },
27536      { 0x3A, "xxpermr" },
27537      { 0x40, "xsmulsp" },
27538      { 0x44, "xsmsubasp" },
27539      { 0x48, "xxmrghw" },
27540      { 0x60, "xsdivsp" },
27541      { 0x64, "xsmsubmsp" },
27542      { 0x68, "xxperm" },
27543      { 0x80, "xsadddp" },
27544      { 0x84, "xsmaddadp" },
27545      { 0x8c, "xscmpudp" },
27546      { 0xa0, "xssubdp" },
27547      { 0xa4, "xsmaddmdp" },
27548      { 0xac, "xscmpodp" },
27549      { 0xc0, "xsmuldp" },
27550      { 0xc4, "xsmsubadp" },
27551      { 0xc8, "xxmrglw" },
27552      { 0xd4, "xstsqrtdp" },
27553      { 0xe0, "xsdivdp" },
27554      { 0xe4, "xsmsubmdp" },
27555      { 0xe8, "xxpermr" },
27556      { 0xeC, "xscmpexpdp" },
27557      { 0xf4, "xstdivdp" },
27558      { 0x100, "xvaddsp" },
27559      { 0x104, "xvmaddasp" },
27560      { 0x10C, "xvcmpeqsp" },
27561      { 0x110, "xvcvspuxws" },
27562      { 0x114, "xvrsqrtesp" },
27563      { 0x120, "xvsubsp" },
27564      { 0x124, "xvmaddmsp" },
27565      { 0x130, "xvcvspsxws" },
27566      { 0x140, "xvmulsp" },
27567      { 0x144, "xvmsubasp" },
27568      { 0x14C, "xvcmpgesp", },
27569      { 0x160, "xvdivsp" },
27570      { 0x164, "xvmsubmsp" },
27571      { 0x174, "xvtdivsp" },
27572      { 0x180, "xvadddp" },
27573      { 0x184, "xvmaddadp" },
27574      { 0x18C, "xvcmpeqdp" },
27575      { 0x1a0, "xvsubdp" },
27576      { 0x1a4, "xvmaddmdp" },
27577      { 0x1aC, "xvcmpgtdp" },
27578      { 0x1c0, "xvmuldp" },
27579      { 0x1c4, "xvmsubadp" },
27580      { 0x1cc, "xvcmpgedp" },
27581      { 0x1e0, "xvdivdp" },
27582      { 0x1e4, "xvmsubmdp" },
27583      { 0x1f4, "xvtdivdp" },
27584      { 0x204, "xsnmaddasp" },
27585      { 0x208, "xxland" },
27586      { 0x224, "xsnmaddmsp" },
27587      { 0x228, "xxlandc" },
27588      { 0x244, "xsnmsubasp" },
27589      { 0x248, "xxlor" },
27590      { 0x264, "xsnmsubmsp" },
27591      { 0x268, "xxlxor" },
27592      { 0x280, "xsmaxdp" },
27593      { 0x284, "xsnmaddadp" },
27594      { 0x288, "xxlnor" },
27595      { 0x2a0, "xsmindp" },
27596      { 0x2a4, "xsnmaddmdp" },
27597      { 0x2a8, "xxlorc" },
27598      { 0x2c0, "xscpsgndp" },
27599      { 0x2c4, "xsnmsubadp" },
27600      { 0x2c8, "xxlnand" },
27601      { 0x2e4, "xsnmsubmdp" },
27602      { 0x2e8, "xxleqv" },
27603      { 0x300, "xvmaxsp" },
27604      { 0x304, "xvnmaddasp" },
27605      { 0x320, "xvminsp" },
27606      { 0x324, "xvnmaddmsp" },
27607      { 0x340, "xvcpsgnsp" },
27608      { 0x344, "xvnmsubasp" },
27609      { 0x360, "xviexpsp" },
27610      { 0x364, "xvnmsubmsp" },
27611      { 0x380, "xvmaxdp" },
27612      { 0x384, "xvnmaddadp" },
27613      { 0x3a0, "xvmindp" },
27614      { 0x3a4, "xvnmaddmdp" },
27615      { 0x3c0, "xvcpsgndp" },
27616      { 0x3c4, "xvnmsubadp" },
27617      { 0x3e0, "xviexpdp" },
27618      { 0x3e4, "xvnmsubmdp" },
27619      { 0x3f0, "xvcvsxddp" },
27620};
27621#define VSX_XX3_LEN (sizeof vsx_xx3 / sizeof *vsx_xx3)
27622
27623
27624/* ATTENTION: These search functions assumes vsx_xx2 and vsx_xx3 arrays
27625 * are sorted.
27626 */
27627static Int findVSXextOpCode_xx2(UInt opcode)
27628{
27629   Int low, mid, high;
27630   low = 0;
27631   high = VSX_XX2_LEN - 1;
27632   while (low <= high) {
27633      mid = (low + high)/2;
27634      if (opcode < vsx_xx2[mid].opcode)
27635         high = mid - 1;
27636      else if (opcode > vsx_xx2[mid].opcode)
27637         low = mid + 1;
27638      else
27639         return mid;
27640   }
27641   return -1;
27642}
27643
27644static Int findVSXextOpCode_xx3(UInt opcode)
27645{
27646   Int low, mid, high;
27647   low = 0;
27648   high = VSX_XX3_LEN - 1;
27649   while (low <= high) {
27650      mid = (low + high)/2;
27651      if (opcode < vsx_xx3[mid].opcode)
27652         high = mid - 1;
27653      else if (opcode > vsx_xx3[mid].opcode)
27654         low = mid + 1;
27655      else
27656         return mid;
27657   }
27658   return -1;
27659}
27660
27661
27662/* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
27663 * passed, and we then try to match it up with one of the VSX forms
27664 * below.
27665 */
27666static UInt get_VSX60_opc2(UInt opc2_full, UInt theInstr)
27667{
27668#define XX2_1_MASK 0x000003FF    // xsiexpdp specific
27669#define XX2_2_MASK 0x000003FE
27670#define XX3_1_MASK 0x000003FC
27671#define XX3_2_MASK 0x000001FC
27672#define XX3_4_MASK 0x0000027C
27673#define XX3_5_MASK 0x000003DC
27674#define XX4_MASK   0x00000018
27675
27676   Int ret;
27677   UInt vsxExtOpcode = 0;
27678
27679   if (( ret = findVSXextOpCode_xx2(opc2_full & XX2_2_MASK)) >= 0)
27680      return vsx_xx2[ret].opcode;
27681   else if ((opc2_full & XX2_1_MASK) == 0x396 )   // xsiexpdp
27682      return 0x396;
27683   else if (( ret = findVSXextOpCode_xx3(opc2_full & XX3_1_MASK)) >= 0)
27684      return vsx_xx3[ret].opcode;
27685   else {
27686
27687      /* There are only a few codes in each of these cases it is
27688       * probably faster to check for the codes then do the array lookups.
27689       */
27690      vsxExtOpcode = opc2_full & XX3_2_MASK;
27691
27692      switch (vsxExtOpcode) {
27693      case 0x10C: return vsxExtOpcode;   // xvcmpeqsp
27694      case 0x12C: return vsxExtOpcode;   // xvcmpgtsp, xvcmpgtsp.
27695      case 0x14C: return vsxExtOpcode;   // xvcmpgesp, xvcmpgesp.
27696      case 0x18C: return vsxExtOpcode;   // xvcmpeqdp, xvcmpeqdp.
27697      case 0x1AC: return vsxExtOpcode;   // xvcmpgtdp, xvcmpgtdp.
27698      case 0x1CC: return vsxExtOpcode;   // xvcmpgedp, xvcmpgedp.
27699      default:  break;
27700      }
27701
27702      vsxExtOpcode = opc2_full & XX3_4_MASK;
27703
27704      switch (vsxExtOpcode) {
27705      case 0x8:   return vsxExtOpcode;   // xxsldwi
27706      case 0x28:  return vsxExtOpcode;   // xxpermdi
27707      default:  break;
27708      }
27709
27710      vsxExtOpcode = opc2_full & XX3_5_MASK;
27711
27712      switch (vsxExtOpcode) {
27713      case 0x354:  return vsxExtOpcode;   // xvtstdcsp
27714      case 0x3D4:  return vsxExtOpcode;   // xvtstdcdp
27715      default:  break;
27716      }
27717
27718      if (( opc2_full & XX4_MASK ) == XX4_MASK ) {   // xxsel
27719         vsxExtOpcode = 0x18;
27720         return vsxExtOpcode;
27721      }
27722   }
27723
27724   vex_printf( "Error: undefined opcode 0x %x, the instruction = 0x %x\n",
27725               opc2_full, theInstr );
27726   vpanic( "ERROR: get_VSX60_opc2()\n" );
27727   return 0;
27728}
27729
27730/*------------------------------------------------------------*/
27731/*--- Disassemble a single instruction                     ---*/
27732/*------------------------------------------------------------*/
27733
27734/* Disassemble a single instruction into IR.  The instruction
27735   is located in host memory at &guest_code[delta]. */
27736
27737static
27738DisResult disInstr_PPC_WRK (
27739             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr ),
27740             Bool         resteerCisOk,
27741             void*        callback_opaque,
27742             Long         delta64,
27743             const VexArchInfo* archinfo,
27744             const VexAbiInfo*  abiinfo,
27745             Bool         sigill_diag
27746          )
27747{
27748   UChar     opc1;
27749   UInt      opc2;
27750   DisResult dres;
27751   UInt      theInstr;
27752   IRType    ty = mode64 ? Ity_I64 : Ity_I32;
27753   UInt      hwcaps = archinfo->hwcaps;
27754   Long      delta;
27755   Bool      allow_F  = False;
27756   Bool      allow_V  = False;
27757   Bool      allow_FX = False;
27758   Bool      allow_GX = False;
27759   Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
27760   Bool      allow_DFP = False;
27761   Bool      allow_isa_2_07 = False;
27762   Bool      allow_isa_3_0  = False;
27763
27764   /* What insn variants are we supporting today? */
27765   if (mode64) {
27766      allow_F  = True;
27767      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
27768      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
27769      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
27770      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
27771      allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
27772      allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
27773      allow_isa_3_0  = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA3_0));
27774   } else {
27775      allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
27776      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
27777      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
27778      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
27779      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
27780      allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
27781      allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
27782      allow_isa_3_0  = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA3_0));
27783   }
27784
27785   /* Enable writting the OV32 and CA32 bits added with ISA3.0 */
27786   OV32_CA32_supported = allow_isa_3_0;
27787
27788   /* The running delta */
27789   delta = (Long)mkSzAddr(ty, (ULong)delta64);
27790
27791   /* Set result defaults. */
27792   dres.whatNext    = Dis_Continue;
27793   dres.len         = 0;
27794   dres.continueAt  = 0;
27795   dres.jk_StopHere = Ijk_INVALID;
27796   dres.hint        = Dis_HintNone;
27797
27798   /* At least this is simple on PPC32: insns are all 4 bytes long, and
27799      4-aligned.  So just fish the whole thing out of memory right now
27800      and have done. */
27801   theInstr = getUIntPPCendianly( &guest_code[delta] );
27802
27803   if (0) vex_printf("insn: 0x%x\n", theInstr);
27804
27805   DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
27806
27807   /* Spot "Special" instructions (see comment at top of file). */
27808   {
27809      const UChar* code = guest_code + delta;
27810      /* Spot the 16-byte preamble:
27811         32-bit mode:
27812            5400183E  rlwinm 0,0,3,0,31
27813            5400683E  rlwinm 0,0,13,0,31
27814            5400E83E  rlwinm 0,0,29,0,31
27815            5400983E  rlwinm 0,0,19,0,31
27816         64-bit mode:
27817            78001800  rotldi 0,0,3
27818            78006800  rotldi 0,0,13
27819            7800E802  rotldi 0,0,61
27820            78009802  rotldi 0,0,51
27821      */
27822      UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
27823      UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
27824      UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
27825      UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
27826      Bool is_special_preamble = False;
27827      if (getUIntPPCendianly(code+ 0) == word1 &&
27828          getUIntPPCendianly(code+ 4) == word2 &&
27829          getUIntPPCendianly(code+ 8) == word3 &&
27830          getUIntPPCendianly(code+12) == word4) {
27831         is_special_preamble = True;
27832      } else if (! mode64 &&
27833                 getUIntPPCendianly(code+ 0) == 0x54001800 &&
27834                 getUIntPPCendianly(code+ 4) == 0x54006800 &&
27835                 getUIntPPCendianly(code+ 8) == 0x5400E800 &&
27836                 getUIntPPCendianly(code+12) == 0x54009800) {
27837         static Bool reported = False;
27838         if (!reported) {
27839            vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
27840            vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
27841            reported = True;
27842         }
27843         is_special_preamble = True;
27844      }
27845      if (is_special_preamble) {
27846         /* Got a "Special" instruction preamble.  Which one is it? */
27847         if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
27848            /* %R3 = client_request ( %R4 ) */
27849            DIP("r3 = client_request ( %%r4 )\n");
27850            delta += 20;
27851            putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
27852            dres.jk_StopHere = Ijk_ClientReq;
27853            dres.whatNext    = Dis_StopHere;
27854            goto decode_success;
27855         }
27856         else
27857         if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
27858            /* %R3 = guest_NRADDR */
27859            DIP("r3 = guest_NRADDR\n");
27860            delta += 20;
27861            dres.len = 20;
27862            putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
27863            goto decode_success;
27864         }
27865         else
27866         if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
27867            delta += 20;
27868            if (host_endness == VexEndnessLE) {
27869                /*  branch-and-link-to-noredir %R12 */
27870                DIP("branch-and-link-to-noredir r12\n");
27871                putGST( PPC_GST_LR,
27872                        mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
27873                putGST( PPC_GST_CIA, getIReg(12));
27874            } else {
27875                /*  branch-and-link-to-noredir %R11 */
27876                DIP("branch-and-link-to-noredir r11\n");
27877                putGST( PPC_GST_LR,
27878                        mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
27879                putGST( PPC_GST_CIA, getIReg(11));
27880            }
27881            dres.jk_StopHere = Ijk_NoRedir;
27882            dres.whatNext    = Dis_StopHere;
27883            goto decode_success;
27884         }
27885         else
27886         if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
27887            /* %R3 = guest_NRADDR_GPR2 */
27888            DIP("r3 = guest_NRADDR_GPR2\n");
27889            delta += 20;
27890            dres.len = 20;
27891            putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
27892            goto decode_success;
27893         }
27894         else
27895         if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
27896            DIP("IR injection\n");
27897            if (host_endness == VexEndnessBE)
27898               vex_inject_ir(irsb, Iend_BE);
27899            else
27900               vex_inject_ir(irsb, Iend_LE);
27901
27902            delta += 20;
27903            dres.len = 20;
27904
27905            // Invalidate the current insn. The reason is that the IRop we're
27906            // injecting here can change. In which case the translation has to
27907            // be redone. For ease of handling, we simply invalidate all the
27908            // time.
27909
27910            stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
27911            stmt(IRStmt_Put(OFFB_CMLEN,   mkSzImm(ty, 20)));
27912
27913            putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
27914            dres.whatNext    = Dis_StopHere;
27915            dres.jk_StopHere = Ijk_InvalICache;
27916            goto decode_success;
27917         }
27918         /* We don't know what it is.  Set opc1/opc2 so decode_failure
27919            can print the insn following the Special-insn preamble. */
27920         theInstr = getUIntPPCendianly(code+16);
27921         opc1     = ifieldOPC(theInstr);
27922         opc2     = ifieldOPClo10(theInstr);
27923         goto decode_failure;
27924         /*NOTREACHED*/
27925      }
27926   }
27927
27928   opc1 = ifieldOPC(theInstr);
27929   opc2 = ifieldOPClo10(theInstr);
27930
27931   // Note: all 'reserved' bits must be cleared, else invalid
27932   switch (opc1) {
27933
27934   /* Integer Arithmetic Instructions */
27935   case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
27936   case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
27937      if (dis_int_arith( theInstr )) goto decode_success;
27938      goto decode_failure;
27939
27940   /* Integer Compare Instructions */
27941   case 0x0B: case 0x0A: // cmpi, cmpli
27942      if (dis_int_cmp( theInstr )) goto decode_success;
27943      goto decode_failure;
27944
27945   /* Integer Logical Instructions */
27946   case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
27947   case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
27948      if (dis_int_logic( theInstr )) goto decode_success;
27949      goto decode_failure;
27950
27951   /* Integer Rotate Instructions */
27952   case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
27953      if (dis_int_rot( theInstr )) goto decode_success;
27954      goto decode_failure;
27955
27956   /* 64bit Integer Rotate Instructions */
27957   case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
27958      if (!mode64) goto decode_failure;
27959      if (dis_int_rot( theInstr )) goto decode_success;
27960      goto decode_failure;
27961
27962   /* Integer Load Instructions */
27963   case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
27964   case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
27965   case 0x20: case 0x21:            // lwz,  lwzu
27966      if (dis_int_load( theInstr )) goto decode_success;
27967      goto decode_failure;
27968
27969   /* Integer Store Instructions */
27970   case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
27971   case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
27972      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
27973      goto decode_failure;
27974
27975   /* Integer Load and Store Multiple Instructions */
27976   case 0x2E: case 0x2F: // lmw, stmw
27977      if (dis_int_ldst_mult( theInstr )) goto decode_success;
27978      goto decode_failure;
27979
27980   /* Branch Instructions */
27981   case 0x12: case 0x10: // b, bc
27982      if (dis_branch(theInstr, abiinfo, &dres,
27983                               resteerOkFn, callback_opaque))
27984         goto decode_success;
27985      goto decode_failure;
27986
27987   /* System Linkage Instructions */
27988   case 0x11: // sc
27989      if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
27990      goto decode_failure;
27991
27992   /* Trap Instructions */
27993   case 0x02:    // tdi
27994      if (!mode64) goto decode_failure;
27995      if (dis_trapi(theInstr, &dres)) goto decode_success;
27996      goto decode_failure;
27997
27998   case 0x03:   // twi
27999      if (dis_trapi(theInstr, &dres)) goto decode_success;
28000      goto decode_failure;
28001
28002   /* Floating Point Load Instructions */
28003   case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
28004   case 0x33:                       // lfdu
28005      if (!allow_F) goto decode_noF;
28006      if (dis_fp_load( theInstr )) goto decode_success;
28007      goto decode_failure;
28008
28009   /* Floating Point Store Instructions */
28010   case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
28011   case 0x37:                       // stfdux
28012      if (!allow_F) goto decode_noF;
28013      if (dis_fp_store( theInstr )) goto decode_success;
28014      goto decode_failure;
28015
28016      /* Floating Point Load Double Pair Instructions */
28017   case 0x39: case 0x3D:    // lfdp, lxsd, lxssp, lxv
28018                            // stfdp, stxsd, stxssp, stxv
28019      if (!allow_F) goto decode_noF;
28020      if (dis_fp_pair( theInstr )) goto decode_success;
28021      goto decode_failure;
28022
28023   /* 128-bit Integer Load */
28024   case 0x38:  // lq
28025      if (dis_int_load( theInstr )) goto decode_success;
28026      goto decode_failure;
28027
28028   /* 64bit Integer Loads */
28029   case 0x3A:  // ld, ldu, lwa
28030      if (!mode64) goto decode_failure;
28031      if (dis_int_load( theInstr )) goto decode_success;
28032      goto decode_failure;
28033
28034   case 0x3B:
28035      if (!allow_F) goto decode_noF;
28036      opc2 = ifieldOPClo10(theInstr);
28037
28038      switch (opc2) {
28039         case 0x2:    // dadd - DFP Add
28040         case 0x202:  // dsub - DFP Subtract
28041         case 0x22:   // dmul - DFP Mult
28042         case 0x222:  // ddiv - DFP Divide
28043            if (!allow_DFP) goto decode_noDFP;
28044            if (dis_dfp_arith( theInstr ))
28045               goto decode_success;
28046         case 0x82:   // dcmpo, DFP comparison ordered instruction
28047         case 0x282:  // dcmpu, DFP comparison unordered instruction
28048            if (!allow_DFP) goto decode_noDFP;
28049            if (dis_dfp_compare( theInstr ) )
28050               goto decode_success;
28051            goto decode_failure;
28052         case 0x102: // dctdp  - DFP convert to DFP long
28053         case 0x302: // drsp   - DFP round to dfp short
28054         case 0x122: // dctfix - DFP convert to fixed
28055            if (!allow_DFP) goto decode_noDFP;
28056            if (dis_dfp_fmt_conv( theInstr ))
28057               goto decode_success;
28058            goto decode_failure;
28059         case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
28060            if (!allow_VX)
28061               goto decode_failure;
28062            if (!allow_DFP) goto decode_noDFP;
28063            if (dis_dfp_fmt_conv( theInstr ))
28064               goto decode_success;
28065            goto decode_failure;
28066         case 0x2A2: // dtstsf  - DFP number of significant digits
28067         case 0x2A3: // dtstsfi - DFP number of significant digits Immediate
28068            if (!allow_DFP) goto decode_noDFP;
28069            if (dis_dfp_significant_digits(theInstr))
28070               goto decode_success;
28071            goto decode_failure;
28072         case 0x142: // ddedpd   DFP Decode DPD to BCD
28073         case 0x342: // denbcd   DFP Encode BCD to DPD
28074            if (!allow_DFP) goto decode_noDFP;
28075            if (dis_dfp_bcd(theInstr))
28076               goto decode_success;
28077            goto decode_failure;
28078         case 0x162:  // dxex - Extract exponent
28079         case 0x362:  // diex - Insert exponent
28080            if (!allow_DFP) goto decode_noDFP;
28081            if (dis_dfp_extract_insert( theInstr ) )
28082               goto decode_success;
28083            goto decode_failure;
28084         case 0x3CE: // fcfidus (implemented as native insn)
28085            if (!allow_VX)
28086               goto decode_noVX;
28087            if (dis_fp_round( theInstr ))
28088               goto decode_success;
28089            goto decode_failure;
28090         case 0x34E: // fcfids
28091            if (dis_fp_round( theInstr ))
28092               goto decode_success;
28093            goto decode_failure;
28094      }
28095
28096      opc2 = ifieldOPClo9( theInstr );
28097      switch (opc2) {
28098      case 0x42: // dscli, DFP shift left
28099      case 0x62: // dscri, DFP shift right
28100         if (!allow_DFP) goto decode_noDFP;
28101         if (dis_dfp_shift( theInstr ))
28102            goto decode_success;
28103         goto decode_failure;
28104      case 0xc2:  // dtstdc, DFP test data class
28105      case 0xe2:  // dtstdg, DFP test data group
28106         if (!allow_DFP) goto decode_noDFP;
28107         if (dis_dfp_class_test( theInstr ))
28108            goto decode_success;
28109         goto decode_failure;
28110      }
28111
28112      opc2 = ifieldOPClo8( theInstr );
28113      switch (opc2) {
28114      case 0x3:   // dqua  - DFP Quantize
28115      case 0x23:  // drrnd - DFP Reround
28116      case 0x43:  // dquai - DFP Quantize immediate
28117         if (!allow_DFP) goto decode_noDFP;
28118         if (dis_dfp_quantize_sig_rrnd( theInstr ) )
28119            goto decode_success;
28120         goto decode_failure;
28121      case 0xA2: // dtstex - DFP Test exponent
28122         if (!allow_DFP) goto decode_noDFP;
28123         if (dis_dfp_exponent_test( theInstr ) )
28124            goto decode_success;
28125         goto decode_failure;
28126      case 0x63: // drintx - Round to an integer value
28127      case 0xE3: // drintn - Round to an integer value
28128         if (!allow_DFP) goto decode_noDFP;
28129         if (dis_dfp_round( theInstr ) ) {
28130            goto decode_success;
28131         }
28132         goto decode_failure;
28133      default:
28134         break;  /* fall through to next opc2 check */
28135      }
28136
28137      opc2 = IFIELD(theInstr, 1, 5);
28138      switch (opc2) {
28139      /* Floating Point Arith Instructions */
28140      case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
28141      case 0x19:                       // fmuls
28142         if (dis_fp_arith(theInstr)) goto decode_success;
28143         goto decode_failure;
28144      case 0x16:                       // fsqrts
28145         if (!allow_FX) goto decode_noFX;
28146         if (dis_fp_arith(theInstr)) goto decode_success;
28147         goto decode_failure;
28148      case 0x18:                       // fres
28149         if (!allow_GX) goto decode_noGX;
28150         if (dis_fp_arith(theInstr)) goto decode_success;
28151         goto decode_failure;
28152
28153      /* Floating Point Mult-Add Instructions */
28154      case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
28155      case 0x1F:                       // fnmadds
28156         if (dis_fp_multadd(theInstr)) goto decode_success;
28157         goto decode_failure;
28158
28159      case 0x1A:                       // frsqrtes
28160         if (!allow_GX) goto decode_noGX;
28161         if (dis_fp_arith(theInstr)) goto decode_success;
28162         goto decode_failure;
28163
28164      default:
28165         goto decode_failure;
28166      }
28167      break;
28168
28169   case 0x3C: // VSX instructions (except load/store)
28170   {
28171      // All of these VSX instructions use some VMX facilities, so
28172      // if allow_V is not set, we'll skip trying to decode.
28173      if (!allow_V) goto decode_noVX;
28174      /* The xvtstdcdp and xvtstdcsp instructions do not have a
28175         contiguous opc2 field.  The following vsxOpc2 = get_VSX60_opc2()
28176         doesn't correctly match these instructions for dc != 0.  So,
28177         we will explicitly look for the two instructions. */
28178      opc2 = ifieldOPClo10(theInstr);
28179      UInt opc2hi = IFIELD(theInstr, 7, 4);
28180      UInt opc2lo = IFIELD(theInstr, 3, 3);
28181      UInt vsxOpc2;
28182
28183      if (( opc2hi == 13 ) && ( opc2lo == 5)) { //xvtstdcsp
28184         if (dis_vxs_misc(theInstr, 0x354, allow_isa_3_0))
28185            goto decode_success;
28186         goto decode_failure;
28187      }
28188
28189      if (( opc2hi == 15 ) && ( opc2lo == 5)) { //xvtstdcdp
28190         if (dis_vxs_misc(theInstr, 0x3D4, allow_isa_3_0))
28191               goto decode_success;
28192            goto decode_failure;
28193      }
28194
28195      /* The vsxOpc2 returned is the "normalized" value, representing the
28196       * instructions secondary opcode as taken from the standard secondary
28197       * opcode field [21:30] (IBM notatition), even if the actual field
28198       * is non-standard.  These normalized values are given in the opcode
28199       * appendices of the ISA 2.06 document.
28200       */
28201      if ( ( opc2 == 0x168 ) && ( IFIELD( theInstr, 19, 2 ) == 0 ) )// xxspltib
28202      {
28203         /* This is a special case of the XX1 form where the  RA, RB
28204          * fields hold an immediate value.
28205          */
28206         if (dis_vxs_misc(theInstr, opc2, allow_isa_3_0)) goto decode_success;
28207         goto decode_failure;
28208      }
28209
28210      vsxOpc2 = get_VSX60_opc2(opc2, theInstr);
28211
28212      switch (vsxOpc2) {
28213         case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
28214         case 0x068: case 0xE8:  // xxperm, xxpermr
28215         case 0x018: case 0x148: // xxsel, xxspltw
28216            if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
28217            goto decode_failure;
28218         case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
28219         case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc
28220         case 0x2C8: case 0x2E8: // xxlnand, xxleqv
28221            if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
28222            goto decode_failure;
28223         case 0x0ec:             // xscmpexpdp
28224         case 0x14A: case 0x16A: // xxextractuw, xxinsertw
28225         case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
28226         case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
28227         case 0x280: case 0x2A0: // xsmaxdp, xsmindp
28228         case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
28229         case 0x034: case 0x014: // xsresp, xsrsqrtesp
28230         case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
28231         case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
28232         case 0x092: case 0x232: // xsrdpi, xsrsp
28233         case 0x3B6:             // xxbrh, xvxexpdp, xvxexpsp, xvxsigdp
28234                                 // xvxsigsp, xvcvhpsp
28235         case 0x2b6:             // xsxexpdp, xsxsigdp
28236         case 0x254: case 0x2d4: // xststdcsp, xststdcdp
28237         case 0x354:             // xvtstdcsp
28238         case 0x360:case 0x396:  // xviexpsp, xsiexpdp
28239         case 0x3D4: case 0x3E0: // xvtstdcdp, xviexpdp
28240            if (dis_vxs_misc(theInstr, vsxOpc2, allow_isa_3_0))
28241               goto decode_success;
28242            goto decode_failure;
28243         case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
28244            if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
28245            goto decode_failure;
28246         case 0x0:   case 0x020: // xsaddsp, xssubsp
28247         case 0x080:             // xsadddp
28248         case 0x060: case 0x0E0: // xsdivsp, xsdivdp
28249         case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
28250         case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
28251         case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
28252         case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
28253         case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
28254         case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
28255         case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
28256         case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
28257         case 0x040: case 0x0C0: // xsmulsp, xsmuldp
28258         case 0x0A0:             // xssubdp
28259         case 0x016: case 0x096: // xssqrtsp,xssqrtdp
28260         case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
28261            if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
28262            goto decode_failure;
28263         case 0x180: // xvadddp
28264         case 0x1E0: // xvdivdp
28265         case 0x1C0: // xvmuldp
28266         case 0x1A0: // xvsubdp
28267         case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
28268         case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
28269         case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
28270         case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
28271         case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
28272         case 0x196: // xvsqrtdp
28273            if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
28274            goto decode_failure;
28275         case 0x100: // xvaddsp
28276         case 0x160: // xvdivsp
28277         case 0x140: // xvmulsp
28278         case 0x120: // xvsubsp
28279         case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
28280         case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
28281         case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
28282         case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
28283         case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
28284         case 0x116: // xvsqrtsp
28285            if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
28286            goto decode_failure;
28287
28288         case 0x250:             // xscvuxdsp
28289         case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
28290         case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
28291         case 0x090: // xscvdpuxws
28292            // The above VSX conversion instructions employ some ISA 2.06
28293            // floating point conversion instructions under the covers,
28294            // so if allow_VX (which means "supports ISA 2.06") is not set,
28295            // we'll skip the decode.
28296            if (!allow_VX) goto decode_noVX;
28297            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
28298            goto decode_failure;
28299
28300         case 0x2B0: // xscvdpsxds
28301         case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
28302         case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
28303         case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
28304         case 0x212: case 0x216: // xscvdpsp, xscvdpspn
28305         case 0x292: case 0x296: // xscvspdp, xscvspdpn
28306         case 0x312: // xvcvdpsp
28307         case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
28308         case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
28309         case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
28310         case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
28311         case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
28312         case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
28313            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
28314            goto decode_failure;
28315
28316         case 0x18C:             // xvcmpeqdp[.]
28317         case 0x10C:             // xvcmpeqsp[.]
28318         case 0x14C:             // xvcmpgesp[.]
28319         case 0x12C:             // xvcmpgtsp[.]
28320         case 0x1CC:             // xvcmpgedp[.]
28321         case 0x1AC:             // xvcmpgtdp[.]
28322             if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
28323             goto decode_failure;
28324
28325         case 0x134:  // xvresp
28326         case 0x1B4:  // xvredp
28327         case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
28328         case 0x380: case 0x3A0: // xvmaxdp, xvmindp
28329         case 0x300: case 0x320: // xvmaxsp, xvminsp
28330         case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
28331         case 0x3B2: case 0x332: // xvabsdp, xvabssp
28332         case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
28333         case 0x192: case 0x1D6: // xvrdpi, xvrdpic
28334         case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
28335         case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
28336         case 0x112: case 0x156: // xvrspi, xvrspic
28337         case 0x172: case 0x152: // xvrspim, xvrspip
28338         case 0x132: // xvrspiz
28339            if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
28340            goto decode_failure;
28341
28342         default:
28343            goto decode_failure;
28344      }
28345      break;
28346   }
28347
28348   /* 64bit Integer Stores */
28349   case 0x3E:  // std, stdu, stq
28350      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
28351      goto decode_failure;
28352
28353   case 0x3F:
28354      if (!allow_F) goto decode_noF;
28355      /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
28356         so we can simply fall through the first switch statement */
28357
28358      opc2 = IFIELD(theInstr, 1, 5);
28359      switch (opc2) {
28360      /* Floating Point Arith Instructions */
28361      case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
28362      case 0x19:                       // fmul
28363         if (dis_fp_arith(theInstr)) goto decode_success;
28364         goto decode_failure;
28365      case 0x16:                       // fsqrt
28366         if (!allow_FX) goto decode_noFX;
28367         if (dis_fp_arith(theInstr)) goto decode_success;
28368         goto decode_failure;
28369      case 0x17: case 0x1A:            // fsel, frsqrte
28370         if (!allow_GX) goto decode_noGX;
28371         if (dis_fp_arith(theInstr)) goto decode_success;
28372         goto decode_failure;
28373
28374      /* Floating Point Mult-Add Instructions */
28375      case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
28376      case 0x1F:                       // fnmadd
28377         if (dis_fp_multadd(theInstr)) goto decode_success;
28378         goto decode_failure;
28379
28380      case 0x18:                       // fre
28381         if (!allow_GX) goto decode_noGX;
28382         if (dis_fp_arith(theInstr)) goto decode_success;
28383         goto decode_failure;
28384
28385      default:
28386         break; // Fall through
28387      }
28388
28389      opc2 = IFIELD(theInstr, 1, 8);
28390      switch (opc2) {
28391      case 0x5: // xsrqpi, xsrqpix
28392      case 0x25: // xsrqpxp
28393         if ( !mode64 || !allow_isa_3_0 ) goto decode_failure;
28394         if ( dis_vx_Scalar_Round_to_quad_integer( theInstr ) )
28395            goto decode_success;
28396         goto decode_failure;
28397      default:
28398         break; // Fall through
28399      }
28400
28401      opc2 = IFIELD(theInstr, 1, 10);
28402      UInt inst_select = IFIELD( theInstr, 16, 5 );
28403
28404      switch (opc2) {
28405      /* 128-bit DFP instructions */
28406      case 0x2:    // daddq - DFP Add
28407      case 0x202:  // dsubq - DFP Subtract
28408      case 0x22:   // dmulq - DFP Mult
28409      case 0x222:  // ddivq - DFP Divide
28410         if (!allow_DFP) goto decode_noDFP;
28411         if (dis_dfp_arithq( theInstr ))
28412            goto decode_success;
28413         goto decode_failure;
28414      case 0x162:  // dxexq - DFP Extract exponent
28415      case 0x362:  // diexq - DFP Insert exponent
28416         if (!allow_DFP) goto decode_noDFP;
28417         if (dis_dfp_extract_insertq( theInstr ))
28418            goto decode_success;
28419         goto decode_failure;
28420
28421      case 0x82:   // dcmpoq, DFP comparison ordered instruction
28422      case 0x282:  // dcmpuq, DFP comparison unordered instruction
28423         if (!allow_DFP) goto decode_noDFP;
28424         if (dis_dfp_compare( theInstr ) )
28425            goto decode_success;
28426         goto decode_failure;
28427
28428      case 0x102: // dctqpq  - DFP convert to DFP extended
28429      case 0x302: // drdpq   - DFP round to dfp Long
28430      case 0x122: // dctfixq - DFP convert to fixed quad
28431      case 0x322: // dcffixq - DFP convert from fixed quad
28432         if (!allow_DFP) goto decode_noDFP;
28433         if (dis_dfp_fmt_convq( theInstr ))
28434            goto decode_success;
28435         goto decode_failure;
28436
28437      case 0x2A2: // dtstsfq  - DFP number of significant digits
28438      case 0x2A3: // dtstsfiq - DFP number of significant digits Immediate
28439         if (!allow_DFP) goto decode_noDFP;
28440         if (dis_dfp_significant_digits(theInstr))
28441            goto decode_success;
28442         goto decode_failure;
28443
28444      case 0x142: // ddedpdq   DFP Decode DPD to BCD
28445      case 0x342: // denbcdq   DFP Encode BCD to DPD
28446         if (!allow_DFP) goto decode_noDFP;
28447         if (dis_dfp_bcdq(theInstr))
28448            goto decode_success;
28449         goto decode_failure;
28450
28451      /* Floating Point Compare Instructions */
28452      case 0x000: // fcmpu
28453      case 0x020: // fcmpo
28454         if (dis_fp_cmp(theInstr)) goto decode_success;
28455         goto decode_failure;
28456
28457      case 0x080: // ftdiv
28458      case 0x0A0: // ftsqrt
28459         if (dis_fp_tests(theInstr)) goto decode_success;
28460         goto decode_failure;
28461
28462      /* Floating Point Rounding/Conversion Instructions */
28463      case 0x00C: // frsp
28464      case 0x00E: // fctiw
28465      case 0x00F: // fctiwz
28466      case 0x32E: // fctid
28467      case 0x32F: // fctidz
28468      case 0x34E: // fcfid
28469         if (dis_fp_round(theInstr)) goto decode_success;
28470         goto decode_failure;
28471      case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
28472      case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
28473         if (!allow_VX) goto decode_noVX;
28474         if (dis_fp_round(theInstr)) goto decode_success;
28475         goto decode_failure;
28476
28477      /* Power6 rounding stuff */
28478      case 0x1E8: // frim
28479      case 0x1C8: // frip
28480      case 0x188: // frin
28481      case 0x1A8: // friz
28482         /* A hack to check for P6 capability . . . */
28483         if ((allow_F && allow_V && allow_FX && allow_GX) &&
28484             (dis_fp_round(theInstr)))
28485            goto decode_success;
28486         goto decode_failure;
28487
28488      /* Floating Point Move Instructions */
28489      case 0x008: // fcpsgn
28490      case 0x028: // fneg
28491      case 0x048: // fmr
28492      case 0x088: // fnabs
28493      case 0x108: // fabs
28494         if (dis_fp_move( theInstr )) goto decode_success;
28495         goto decode_failure;
28496
28497      case 0x3c6: case 0x346:          // fmrgew, fmrgow
28498         if (dis_fp_merge( theInstr )) goto decode_success;
28499         goto decode_failure;
28500
28501      /* Floating Point Status/Control Register Instructions */
28502      case 0x026: // mtfsb1
28503      case 0x040: // mcrfs
28504      case 0x046: // mtfsb0
28505      case 0x086: // mtfsfi
28506      case 0x247: // mffs, mmfs., mffsce, mffscdrn, mffscdrni,
28507                  // mffscrn, mffscrn, mffscri, mffsl
28508      case 0x2C7: // mtfsf
28509         // Some of the above instructions need to know more about the
28510         // ISA level supported by the host.
28511         if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
28512         goto decode_failure;
28513
28514      case 0x324: // xsabsqp, xsxexpqp,xsnabsqp, xsnegqp, xsxsigqp
28515         if ( inst_select == 27 ) {    // xssqrtqp
28516            if ( dis_vx_Floating_Point_Arithmetic_quad_precision( theInstr ) )
28517               goto decode_success;
28518         }
28519
28520         /* Instructions implemented with Pre ISA 3.0 Iops */
28521         /* VSX Scalar Quad-Precision instructions */
28522      case 0x064: // xscpsgnqp
28523      case 0x0A4: // xscmpexpqp
28524      case 0x084: // xscmpoqp
28525      case 0x284: // xscmpuqp
28526      case 0x2C4: // xststdcqp
28527      case 0x364: // xsiexpqp
28528         if (dis_vx_scalar_quad_precision( theInstr )) goto decode_success;
28529         goto decode_failure;
28530
28531      /* Instructions implemented using ISA 3.0 instructions */
28532                  // xsaddqpo (VSX Scalar Add Quad-Precision [using round to ODD]
28533      case 0x004: // xsaddqp  (VSX Scalar Add Quad-Precision [using RN mode]
28534                  // xsmulqpo (VSX Scalar Multiply Quad-Precision [using round to ODD]
28535      case 0x024: // xsmulqp  (VSX Scalar Multiply Quad-Precision [using RN mode]
28536                  // xsmaddqpo (VSX Scalar Multiply Add Quad-Precision [using round to ODD]
28537      case 0x184: // xsmaddqp  (VSX Scalar Multiply Add Quad-Precision [using RN mode]
28538                  // xsmsubqpo (VSX Scalar Multiply Sub Quad-Precision [using round to ODD]
28539      case 0x1A4: // xsmsubqp  (VSX Scalar Multiply Sub Quad-Precision [using RN mode]
28540                  // xsnmaddqpo (VSX Scalar Negative Multiply Add Quad-Precision [using round to ODD]
28541      case 0x1C4: // xsnmaddqp  (VSX Scalar Negative Multiply Add Quad-Precision [using RN mode]
28542                  // xsnmsubqpo (VSX Scalar Negative Multiply Sub Quad-Precision [using round to ODD]
28543      case 0x1E4: // xsnmsubqp  (VSX Scalar Negative Multiply Sub Quad-Precision [usin RN mode]
28544                  // xssubqpo (VSX Scalar Subrtact Quad-Precision [using round to ODD]
28545      case 0x204: // xssubqp  (VSX Scalar Subrtact Quad-Precision [using RN mode]
28546                  // xsdivqpo (VSX Scalar Divde Quad-Precision [using round to ODD]
28547      case 0x224: // xsdivqp  (VSX Scalar Divde Quad-Precision [using RN mode]
28548      case 0x344: // xscvudqp, xscvsdqp, xscvqpdp, xscvqpdpo, xsvqpdp
28549                  // xscvqpswz, xscvqpuwz, xscvqpudz, xscvqpsdz
28550         if ( !mode64 || !allow_isa_3_0 ) goto decode_failure;
28551         if ( dis_vx_Floating_Point_Arithmetic_quad_precision( theInstr ) )
28552            goto decode_success;
28553         goto decode_failure;
28554
28555      default:
28556         break; // Fall through...
28557      }
28558
28559      opc2 = ifieldOPClo9( theInstr );
28560      switch (opc2) {
28561      case 0x42: // dscli, DFP shift left
28562      case 0x62: // dscri, DFP shift right
28563         if (!allow_DFP) goto decode_noDFP;
28564         if (dis_dfp_shiftq( theInstr ))
28565            goto decode_success;
28566         goto decode_failure;
28567      case 0xc2:  // dtstdc, DFP test data class
28568      case 0xe2:  // dtstdg, DFP test data group
28569         if (!allow_DFP) goto decode_noDFP;
28570         if (dis_dfp_class_test( theInstr ))
28571            goto decode_success;
28572         goto decode_failure;
28573      default:
28574         break;
28575      }
28576
28577      opc2 = ifieldOPClo8( theInstr );
28578      switch (opc2) {
28579      case 0x3:   // dquaq  - DFP Quantize Quad
28580      case 0x23:  // drrndq - DFP Reround Quad
28581      case 0x43:  // dquaiq - DFP Quantize immediate Quad
28582         if (!allow_DFP) goto decode_noDFP;
28583         if (dis_dfp_quantize_sig_rrndq( theInstr ))
28584            goto decode_success;
28585         goto decode_failure;
28586      case 0xA2: // dtstexq - DFP Test exponent Quad
28587         if (!allow_DFP) goto decode_noDFP;
28588         if (dis_dfp_exponent_test( theInstr ) )
28589            goto decode_success;
28590         goto decode_failure;
28591      case 0x63:  // drintxq - DFP Round to an integer value
28592      case 0xE3:  // drintnq - DFP Round to an integer value
28593         if (!allow_DFP) goto decode_noDFP;
28594         if (dis_dfp_roundq( theInstr ))
28595            goto decode_success;
28596         goto decode_failure;
28597
28598      default:
28599         goto decode_failure;
28600      }
28601      break;
28602
28603   case 0x13:
28604
28605      opc2 = ifieldOPClo5(theInstr);
28606      switch (opc2) {
28607
28608      /* PC relative load/store */
28609      case 0x002:       // addpcis
28610         if (dis_pc_relative(theInstr)) goto decode_success;
28611         goto decode_failure;
28612
28613      /* fall through to the next opc2 field size */
28614      }
28615
28616      opc2 = ifieldOPClo10(theInstr);
28617      switch (opc2) {
28618
28619      /* Condition Register Logical Instructions */
28620      case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
28621      case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
28622      case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
28623         if (dis_cond_logic( theInstr )) goto decode_success;
28624         goto decode_failure;
28625
28626      /* Branch Instructions */
28627      case 0x210: case 0x010: // bcctr, bclr
28628         if (dis_branch(theInstr, abiinfo, &dres,
28629                                  resteerOkFn, callback_opaque))
28630            goto decode_success;
28631         goto decode_failure;
28632
28633      /* Memory Synchronization Instructions */
28634      case 0x096: // isync
28635         if (dis_memsync( theInstr )) goto decode_success;
28636         goto decode_failure;
28637
28638      default:
28639         goto decode_failure;
28640      }
28641      break;
28642
28643
28644   case 0x1F:
28645
28646      /* For arith instns, bit10 is the OE flag (overflow enable) */
28647
28648      opc2 = IFIELD(theInstr, 1, 9);
28649      switch (opc2) {
28650      /* Integer Arithmetic Instructions */
28651      case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
28652      case 0x0AA:                         // addex
28653      case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
28654      case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
28655      case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
28656      case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
28657      case 0x0C8: // subfze
28658         if (dis_int_arith( theInstr )) goto decode_success;
28659         goto decode_failure;
28660
28661      case 0x18B: // divweu (implemented as native insn)
28662      case 0x1AB: // divwe (implemented as native insn)
28663         if (!allow_VX) goto decode_noVX;
28664         if (dis_int_arith( theInstr )) goto decode_success;
28665         goto decode_failure;
28666
28667      /* 64bit Integer Arithmetic */
28668      case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
28669      case 0x1C9: case 0x1E9: // divdu, divd
28670         if (!mode64) goto decode_failure;
28671         if (dis_int_arith( theInstr )) goto decode_success;
28672         goto decode_failure;
28673
28674      case 0x1A9: //  divde (implemented as native insn)
28675      case 0x189: //  divdeuo (implemented as native insn)
28676         if (!allow_VX) goto decode_noVX;
28677         if (!mode64) goto decode_failure;
28678         if (dis_int_arith( theInstr )) goto decode_success;
28679         goto decode_failure;
28680
28681      case 0x1FC:                         // cmpb
28682         if (dis_int_logic( theInstr )) goto decode_success;
28683         goto decode_failure;
28684
28685      default:
28686         break;  // Fall through...
28687      }
28688
28689      /* All remaining opcodes use full 10 bits. */
28690
28691      opc2 = IFIELD(theInstr, 1, 10);
28692      switch (opc2) {
28693
28694      /* Integer miscellaneous instructions */
28695      case 0x01E:  // wait  RFC 2500
28696         if (dis_int_misc( theInstr )) goto decode_success;
28697         goto decode_failure;
28698
28699
28700      /* Integer Compare Instructions  */
28701      case 0x000: case 0x020: case 0x080: // cmp, cmpl, setb
28702         if (dis_int_cmp( theInstr )) goto decode_success;
28703         goto decode_failure;
28704
28705      case 0x0C0: case 0x0E0:   // cmprb, cmpeqb
28706         if (dis_byte_cmp( theInstr )) goto decode_success;
28707         goto decode_failure;
28708
28709      case 0x10B: case 0x30B: // moduw, modsw
28710      case 0x109: case 0x309: // modsd, modud
28711      case 0x21A: case 0x23A: // cnttzw, cnttzd
28712         if (dis_modulo_int( theInstr )) goto decode_success;
28713         goto decode_failure;
28714
28715      /* Integer Logical Instructions */
28716      case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
28717      case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
28718      case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
28719      case 0x19C: case 0x13C:             // orc,  xor
28720      case 0x2DF: case 0x25F:            // mftgpr, mffgpr
28721         if (dis_int_logic( theInstr )) goto decode_success;
28722         goto decode_failure;
28723
28724      case 0x28E: case 0x2AE:             // tbegin., tend.
28725      case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
28726      case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
28727      case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
28728      if (dis_transactional_memory( theInstr,
28729                                    getUIntPPCendianly( &guest_code[delta + 4]),
28730                                    abiinfo, &dres,
28731                                    resteerOkFn, callback_opaque))
28732            goto decode_success;
28733         goto decode_failure;
28734
28735      /* 64bit Integer Logical Instructions */
28736      case 0x3DA: case 0x03A: // extsw, cntlzd
28737         if (!mode64) goto decode_failure;
28738         if (dis_int_logic( theInstr )) goto decode_success;
28739         goto decode_failure;
28740
28741         /* 64bit Integer Parity Instructions */
28742      case 0xba: // prtyd
28743         if (!mode64) goto decode_failure;
28744         if (dis_int_parity( theInstr )) goto decode_success;
28745         goto decode_failure;
28746
28747      case 0x9a: // prtyw
28748         if (dis_int_parity( theInstr )) goto decode_success;
28749         goto decode_failure;
28750
28751      /* Integer Shift Instructions */
28752      case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
28753      case 0x218:                         // srw
28754         if (dis_int_shift( theInstr )) goto decode_success;
28755         goto decode_failure;
28756
28757      /* 64bit Integer Shift Instructions */
28758      case 0x01B: case 0x31A: // sld, srad
28759      case 0x33A: case 0x33B: // sradi
28760      case 0x21B:             // srd
28761         if (!mode64) goto decode_failure;
28762         if (dis_int_shift( theInstr )) goto decode_success;
28763         goto decode_failure;
28764
28765      /* Integer Load Instructions */
28766      case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
28767      case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
28768      case 0x017: case 0x037:             // lwzx,  lwzux
28769         if (dis_int_load( theInstr )) goto decode_success;
28770         goto decode_failure;
28771
28772      /* 64bit Integer Load Instructions */
28773      case 0x035: case 0x015:             // ldux,  ldx
28774      case 0x175: case 0x155:             // lwaux, lwax
28775         if (!mode64) goto decode_failure;
28776         if (dis_int_load( theInstr )) goto decode_success;
28777         goto decode_failure;
28778
28779      /* Integer Store Instructions */
28780      case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
28781      case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
28782         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
28783         goto decode_failure;
28784
28785      /* 64bit Integer Store Instructions */
28786      case 0x0B5: case 0x095: // stdux, stdx
28787         if (!mode64) goto decode_failure;
28788         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
28789         goto decode_failure;
28790
28791      /* Integer Load and Store with Byte Reverse Instructions */
28792      case 0x214: case 0x294: // ldbrx, stdbrx
28793         if (!mode64) goto decode_failure;
28794         if (dis_int_ldst_rev( theInstr )) goto decode_success;
28795         goto decode_failure;
28796
28797      case 0x216: case 0x316: case 0x296:    // lwbrx, lhbrx, stwbrx
28798      case 0x396:                            // sthbrx
28799         if (dis_int_ldst_rev( theInstr )) goto decode_success;
28800         goto decode_failure;
28801
28802      /* Integer Load and Store String Instructions */
28803      case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
28804      case 0x295: {                       // stswx
28805         Bool stopHere = False;
28806         Bool ok = dis_int_ldst_str( theInstr, &stopHere );
28807         if (!ok) goto decode_failure;
28808         if (stopHere) {
28809            putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
28810            dres.jk_StopHere = Ijk_Boring;
28811            dres.whatNext    = Dis_StopHere;
28812         }
28813         goto decode_success;
28814      }
28815
28816      /* Memory Synchronization Instructions */
28817      case 0x034: case 0x074:             // lbarx, lharx
28818      case 0x2B6: case 0x2D6:             // stbcx, sthcx
28819         if (!allow_isa_2_07) goto decode_noP8;
28820         if (dis_memsync( theInstr )) goto decode_success;
28821         goto decode_failure;
28822
28823      case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
28824      case 0x256:                         // sync
28825         if (dis_memsync( theInstr )) goto decode_success;
28826         goto decode_failure;
28827
28828      /* 64bit Memory Synchronization Instructions */
28829      case 0x054: case 0x0D6: // ldarx, stdcx.
28830         if (!mode64) goto decode_failure;
28831         if (dis_memsync( theInstr )) goto decode_success;
28832         goto decode_failure;
28833
28834      case 0x114: case 0x0B6: // lqarx, stqcx.
28835         if (dis_memsync( theInstr )) goto decode_success;
28836         goto decode_failure;
28837
28838      /* Processor Control Instructions */
28839      case 0x33:  case 0x73: // mfvsrd, mfvsrwz
28840      case 0xB3:  case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
28841      case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
28842      case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
28843      case 0x220:                         // mcrxrt
28844         if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
28845         goto decode_failure;
28846
28847      /* Cache Management Instructions */
28848      case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
28849      case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
28850      case 0x3D6:                         // icbi
28851         if (dis_cache_manage( theInstr, &dres, archinfo ))
28852            goto decode_success;
28853         goto decode_failure;
28854
28855//zz       /* External Control Instructions */
28856//zz       case 0x136: case 0x1B6: // eciwx, ecowx
28857//zz          DIP("external control op => not implemented\n");
28858//zz          goto decode_failure;
28859
28860      /* Trap Instructions */
28861      case 0x004:             // tw
28862         if (dis_trap(theInstr, &dres)) goto decode_success;
28863         goto decode_failure;
28864
28865      case 0x044:             // td
28866         if (!mode64) goto decode_failure;
28867         if (dis_trap(theInstr, &dres)) goto decode_success;
28868         goto decode_failure;
28869
28870      /* Floating Point Load Instructions */
28871      case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
28872      case 0x277:                         // lfdux
28873         if (!allow_F) goto decode_noF;
28874         if (dis_fp_load( theInstr )) goto decode_success;
28875         goto decode_failure;
28876
28877      /* Floating Point Store Instructions */
28878      case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
28879      case 0x2F7:                         // stfdu, stfiwx
28880         if (!allow_F) goto decode_noF;
28881         if (dis_fp_store( theInstr )) goto decode_success;
28882         goto decode_failure;
28883      case 0x3D7:                         // stfiwx
28884         if (!allow_F) goto decode_noF;
28885         if (!allow_GX) goto decode_noGX;
28886         if (dis_fp_store( theInstr )) goto decode_success;
28887         goto decode_failure;
28888
28889         /* Floating Point Double Pair Indexed Instructions */
28890      case 0x317: // lfdpx (Power6)
28891      case 0x397: // stfdpx (Power6)
28892         if (!allow_F) goto decode_noF;
28893         if (dis_fp_pair(theInstr)) goto decode_success;
28894         goto decode_failure;
28895
28896      case 0x357:                         // lfiwax
28897         if (!allow_F) goto decode_noF;
28898         if (dis_fp_load( theInstr )) goto decode_success;
28899         goto decode_failure;
28900
28901      case 0x377:                         // lfiwzx
28902         if (!allow_F) goto decode_noF;
28903         if (dis_fp_load( theInstr )) goto decode_success;
28904         goto decode_failure;
28905
28906      /* AltiVec instructions */
28907
28908      /* AV Cache Control - Data streams */
28909      case 0x156: case 0x176: case 0x336: // dst, dstst, dss
28910         if (!allow_V) goto decode_noV;
28911         if (dis_av_datastream( theInstr )) goto decode_success;
28912         goto decode_failure;
28913
28914      /* AV Load */
28915      case 0x006: case 0x026:             // lvsl, lvsr
28916      case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
28917      case 0x067: case 0x167:             // lvx, lvxl
28918         if (!allow_V) goto decode_noV;
28919         if (dis_av_load( abiinfo, theInstr )) goto decode_success;
28920         goto decode_failure;
28921
28922      /* AV Store */
28923      case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
28924      case 0x0E7: case 0x1E7:             // stvx, stvxl
28925         if (!allow_V) goto decode_noV;
28926         if (dis_av_store( theInstr )) goto decode_success;
28927         goto decode_failure;
28928
28929      /* VSX Load */
28930      case 0x00C: // lxsiwzx
28931      case 0x04C: // lxsiwax
28932      case 0x10C: // lxvx
28933      case 0x10D: // lxvl
28934      case 0x12D: // lxvll
28935      case 0x16C: // lxvwsx
28936      case 0x20C: // lxsspx
28937      case 0x24C: // lxsdx
28938      case 0x32C: // lxvh8x
28939      case 0x30D: // lxsibzx
28940      case 0x32D: // lxsihzx
28941      case 0x34C: // lxvd2x
28942      case 0x36C: // lxvb16x
28943      case 0x14C: // lxvdsx
28944      case 0x30C: // lxvw4x
28945        // All of these VSX load instructions use some VMX facilities, so
28946        // if allow_V is not set, we'll skip trying to decode.
28947        if (!allow_V) goto decode_noV;
28948
28949	if (dis_vx_load( theInstr )) goto decode_success;
28950          goto decode_failure;
28951
28952      /* VSX Store */
28953      case 0x08C: // stxsiwx
28954      case 0x18C: // stxvx
28955      case 0x18D: // stxvl
28956      case 0x1AD: // stxvll
28957      case 0x28C: // stxsspx
28958      case 0x2CC: // stxsdx
28959      case 0x38C: // stxvw4x
28960      case 0x3CC: // stxvd2x
28961      case 0x38D: // stxsibx
28962      case 0x3AD: // stxsihx
28963      case 0x3AC: // stxvh8x
28964      case 0x3EC: // stxvb16x
28965        // All of these VSX store instructions use some VMX facilities, so
28966        // if allow_V is not set, we'll skip trying to decode.
28967        if (!allow_V) goto decode_noV;
28968
28969	if (dis_vx_store( theInstr )) goto decode_success;
28970    	  goto decode_failure;
28971
28972      case 0x133: case 0x193: case 0x1B3:  // mfvsrld, mfvsrdd, mtvsrws
28973        // The move from/to VSX instructions use some VMX facilities, so
28974        // if allow_V is not set, we'll skip trying to decode.
28975        if (!allow_V) goto decode_noV;
28976        if (dis_vx_move( theInstr )) goto decode_success;
28977        goto decode_failure;
28978
28979      /* Miscellaneous ISA 2.06 instructions */
28980      case 0x1FA: // popcntd
28981      case 0x17A: // popcntw
28982      case 0x7A:  // popcntb
28983	  if (dis_int_logic( theInstr )) goto decode_success;
28984    	  goto decode_failure;
28985
28986      case 0x0FC: // bpermd
28987         if (!mode64) goto decode_failure;
28988         if (dis_int_logic( theInstr )) goto decode_success;
28989         goto decode_failure;
28990
28991      default:
28992         /* Deal with some other cases that we would otherwise have
28993            punted on. */
28994         /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
28995         /* only decode this insn when reserved bit 0 (31 in IBM's
28996            notation) is zero */
28997         if (IFIELD(theInstr, 0, 6) == (15<<1)) {
28998            UInt rT = ifieldRegDS( theInstr );
28999            UInt rA = ifieldRegA( theInstr );
29000            UInt rB = ifieldRegB( theInstr );
29001            UInt bi = ifieldRegC( theInstr );
29002            putIReg(
29003               rT,
29004               IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
29005                           rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
29006                                   : getIReg(rA),
29007                           getIReg(rB))
29008
29009            );
29010            DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
29011            goto decode_success;
29012         }
29013      }
29014
29015      opc2 = IFIELD(theInstr, 2, 9);
29016      switch (opc2) {
29017      case 0x1BD:
29018         if (!mode64) goto decode_failure;
29019         if (dis_int_logic( theInstr )) goto decode_success;
29020         goto decode_failure;
29021
29022      default:
29023         goto decode_failure;
29024      }
29025      break;
29026
29027
29028   case 0x04:
29029      /* AltiVec instructions */
29030
29031      opc2 = IFIELD(theInstr, 0, 6);
29032      switch (opc2) {
29033      /* AV Mult-Add, Mult-Sum */
29034      case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
29035      case 0x23:                       // vmsumudm
29036      case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
29037      case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
29038         if (!allow_V) goto decode_noV;
29039         if (dis_av_multarith( theInstr )) goto decode_success;
29040         goto decode_failure;
29041
29042      case 0x30: case 0x31: case 0x33: // maddhd, madhdu, maddld
29043         if (!mode64) goto decode_failure;
29044         if (dis_int_mult_add( theInstr )) goto decode_success;
29045         goto decode_failure;
29046
29047      /* AV Permutations */
29048      case 0x2A:                       // vsel
29049      case 0x2B:                       // vperm
29050      case 0x2C:                       // vsldoi
29051         if (!allow_V) goto decode_noV;
29052         if (dis_av_permute( theInstr )) goto decode_success;
29053         goto decode_failure;
29054
29055      case 0x2D:                       // vpermxor
29056      case 0x3B:                       // vpermr
29057         if (!allow_isa_2_07) goto decode_noP8;
29058         if (dis_av_permute( theInstr )) goto decode_success;
29059         goto decode_failure;
29060
29061      /* AV Floating Point Mult-Add/Sub */
29062      case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
29063         if (!allow_V) goto decode_noV;
29064         if (dis_av_fp_arith( theInstr )) goto decode_success;
29065         goto decode_failure;
29066
29067      case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
29068      case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
29069         if (!allow_V) goto decode_noV;
29070         if (dis_av_quad( theInstr)) goto decode_success;
29071         goto decode_failure;
29072
29073      default:
29074         break;  // Fall through...
29075      }
29076
29077      opc2 = IFIELD(theInstr, 0, 9);
29078      if (IFIELD(theInstr, 10, 1) == 1) {
29079         /* The following instructions have bit 21 set and a PS bit (bit 22)
29080          * Bit 21 distinquishes them from instructions with an 11 bit opc2
29081          * field.
29082          */
29083         switch (opc2) {
29084            /* BCD arithmetic */
29085            case 0x001: case 0x041:             // bcdadd, bcdsub
29086            case 0x101: case 0x141:             // bcdtrunc., bcdutrunc.
29087            case 0x081: case 0x0C1: case 0x1C1: // bcdus., bcds., bcdsr.
29088            case 0x181:                         // bcdcfn., bcdcfz.
29089                                                // bcdctz., bcdcfsq., bcdctsq.
29090               if (!allow_isa_2_07) goto decode_noP8;
29091               if (dis_av_bcd( theInstr, abiinfo )) goto decode_success;
29092              goto decode_failure;
29093         default:
29094              break;  // Fall through...
29095            }
29096      }
29097
29098      opc2 = IFIELD(theInstr, 0, 11);
29099      switch (opc2) {
29100      /* BCD manipulation */
29101      case 0x341:                  // bcdcpsgn
29102
29103         if (!allow_isa_2_07) goto decode_noP8;
29104         if (dis_av_bcd_misc( theInstr, abiinfo )) goto decode_success;
29105         goto decode_failure;
29106
29107
29108      /* AV Arithmetic */
29109      case 0x180:                         // vaddcuw
29110      case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
29111      case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
29112      case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
29113      case 0x580:                         // vsubcuw
29114      case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
29115      case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
29116      case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
29117      case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
29118      case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
29119      case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
29120      case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
29121      case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
29122      case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
29123      case 0x008: case 0x048:             // vmuloub, vmulouh
29124      case 0x108: case 0x148:             // vmulosb, vmulosh
29125      case 0x208: case 0x248:             // vmuleub, vmuleuh
29126      case 0x308: case 0x348:             // vmulesb, vmulesh
29127      case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
29128      case 0x688: case 0x788:             // vsum2sws, vsumsws
29129         if (!allow_V) goto decode_noV;
29130         if (dis_av_arith( theInstr )) goto decode_success;
29131         goto decode_failure;
29132
29133      case 0x088: case 0x089:             // vmulouw, vmuluwm
29134      case 0x0C0: case 0x0C2:             // vaddudm, vmaxud
29135      case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
29136      case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
29137      case 0x4C0:                         // vsubudm
29138         if (!allow_isa_2_07) goto decode_noP8;
29139         if (dis_av_arith( theInstr )) goto decode_success;
29140         goto decode_failure;
29141
29142      /* AV Polynomial Vector Multiply Add */
29143      case 0x408: case 0x448:            // vpmsumb, vpmsumd
29144      case 0x488: case 0x4C8:            // vpmsumw, vpmsumh
29145         if (!allow_isa_2_07) goto decode_noP8;
29146         if (dis_av_polymultarith( theInstr )) goto decode_success;
29147         goto decode_failure;
29148
29149      /* AV Rotate, Shift */
29150      case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
29151      case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
29152      case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
29153      case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
29154      case 0x1C4: case 0x2C4:             // vsl, vsr
29155      case 0x40C: case 0x44C:             // vslo, vsro
29156         if (!allow_V) goto decode_noV;
29157         if (dis_av_shift( theInstr )) goto decode_success;
29158         goto decode_failure;
29159
29160      case 0x0C4:                         // vrld
29161      case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
29162          if (!allow_isa_2_07) goto decode_noP8;
29163          if (dis_av_shift( theInstr )) goto decode_success;
29164          goto decode_failure;
29165
29166      /* AV Logic */
29167      case 0x404: case 0x444: case 0x484: // vand, vandc, vor
29168      case 0x4C4: case 0x504:             // vxor, vnor
29169         if (!allow_V) goto decode_noV;
29170         if (dis_av_logic( theInstr )) goto decode_success;
29171         goto decode_failure;
29172
29173      case 0x544:                         // vorc
29174      case 0x584: case 0x684:             // vnand, veqv
29175         if (!allow_isa_2_07) goto decode_noP8;
29176         if (dis_av_logic( theInstr )) goto decode_success;
29177         goto decode_failure;
29178
29179      /* AV Rotate */
29180      case 0x085: case 0x185:             // vrlwmi, vrlwnm
29181      case 0x0C5: case 0x1C5:             // vrldmi, vrldnm
29182         if (!allow_V) goto decode_noV;
29183         if (dis_av_rotate( theInstr )) goto decode_success;
29184         goto decode_failure;
29185
29186      /* AV Processor Control */
29187      case 0x604: case 0x644:             // mfvscr, mtvscr
29188         if (!allow_V) goto decode_noV;
29189         if (dis_av_procctl( theInstr )) goto decode_success;
29190         goto decode_failure;
29191
29192      /* AV Vector Extract Element instructions */
29193      case 0x60D: case 0x64D: case 0x68D:   // vextublx, vextuhlx, vextuwlx
29194      case 0x70D: case 0x74D: case 0x78D:   // vextubrx, vextuhrx, vextuwrx
29195         if (!allow_V) goto decode_noV;
29196         if (dis_av_extract_element( theInstr )) goto decode_success;
29197         goto decode_failure;
29198
29199
29200      /* AV Floating Point Arithmetic */
29201      case 0x00A: case 0x04A:             // vaddfp, vsubfp
29202      case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
29203      case 0x1CA:                         // vlogefp
29204      case 0x40A: case 0x44A:             // vmaxfp, vminfp
29205         if (!allow_V) goto decode_noV;
29206         if (dis_av_fp_arith( theInstr )) goto decode_success;
29207         goto decode_failure;
29208
29209      /* AV Floating Point Round/Convert */
29210      case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
29211      case 0x2CA:                         // vrfim
29212      case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
29213      case 0x3CA:                         // vctsxs
29214         if (!allow_V) goto decode_noV;
29215         if (dis_av_fp_convert( theInstr )) goto decode_success;
29216         goto decode_failure;
29217
29218      /* AV Merge, Splat, Extract, Insert */
29219      case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
29220      case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
29221      case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
29222      case 0x20D: case 0x24D:             // vextractub, vextractuh,
29223      case 0x28D: case 0x2CD:             // vextractuw, vextractd,
29224      case 0x30D: case 0x34D:             // vinsertb, vinserth
29225      case 0x38D: case 0x3CD:             // vinsertw, vinsertd
29226      case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
29227         if (!allow_V) goto decode_noV;
29228         if (dis_av_permute( theInstr )) goto decode_success;
29229         goto decode_failure;
29230
29231      case 0x68C: case 0x78C:             // vmrgow, vmrgew
29232          if (!allow_isa_2_07) goto decode_noP8;
29233          if (dis_av_permute( theInstr )) goto decode_success;
29234          goto decode_failure;
29235
29236      /* AltiVec 128 bit integer multiply by 10 Instructions */
29237      case 0x201: case 0x001:               //vmul10uq, vmul10cuq
29238      case 0x241: case 0x041:               //vmul10euq, vmul10ceuq
29239          if (!allow_V) goto decode_noV;
29240          if (!allow_isa_3_0) goto decode_noP9;
29241          if (dis_av_mult10( theInstr )) goto decode_success;
29242          goto decode_failure;
29243
29244      /* AV Pack, Unpack */
29245      case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
29246      case 0x0CE:                         // vpkuwus
29247      case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
29248      case 0x1CE:                         // vpkswss
29249      case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
29250      case 0x2CE:                         // vupklsh
29251      case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
29252          if (!allow_V) goto decode_noV;
29253          if (dis_av_pack( theInstr )) goto decode_success;
29254          goto decode_failure;
29255
29256      case 0x403: case 0x443: case 0x483:  // vabsdub, vabsduh, vabsduw
29257          if (!allow_V) goto decode_noV;
29258          if (dis_abs_diff( theInstr )) goto decode_success;
29259          goto decode_failure;
29260
29261      case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
29262      case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
29263         if (!allow_isa_2_07) goto decode_noP8;
29264         if (dis_av_pack( theInstr )) goto decode_success;
29265         goto decode_failure;
29266
29267      case 0x508: case 0x509:             // vcipher, vcipherlast
29268      case 0x548: case 0x549:             // vncipher, vncipherlast
29269      case 0x5C8:                         // vsbox
29270         if (!allow_isa_2_07) goto decode_noP8;
29271         if (dis_av_cipher( theInstr )) goto decode_success;
29272         goto decode_failure;
29273
29274     /* AV Vector Extend Sign Instructions and
29275      * Vector Count Leading/Trailing zero Least-Significant bits Byte.
29276      * Vector Integer Negate Instructions
29277      */
29278      case 0x602:   // vextsb2w, vextsh2w, vextsb2d, vextsh2d, vextsw2d
29279                    // vclzlsbb and vctzlsbb
29280                    // vnegw, vnegd
29281                    // vprtybw, vprtybd, vprtybq
29282                    // vctzb, vctzh, vctzw, vctzd
29283         if (!allow_V) goto decode_noV;
29284         if (dis_av_extend_sign_count_zero( theInstr, allow_isa_3_0 ))
29285            goto decode_success;
29286         goto decode_failure;
29287
29288      case 0x6C2: case 0x682:             // vshasigmaw, vshasigmad
29289         if (!allow_isa_2_07) goto decode_noP8;
29290         if (dis_av_hash( theInstr )) goto decode_success;
29291         goto decode_failure;
29292
29293      case 0x702: case 0x742:             // vclzb, vclzh
29294      case 0x782: case 0x7c2:             // vclzw, vclzd
29295         if (!allow_isa_2_07) goto decode_noP8;
29296         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
29297         goto decode_failure;
29298
29299      case 0x703: case 0x743:             // vpopcntb, vpopcnth
29300      case 0x783: case 0x7c3:             // vpopcntw, vpopcntd
29301         if (!allow_isa_2_07) goto decode_noP8;
29302         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
29303         goto decode_failure;
29304
29305      case 0x50c:                         // vgbbd
29306      case 0x5cc:                         // vbpermd
29307         if (!allow_isa_2_07) goto decode_noP8;
29308         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
29309         goto decode_failure;
29310
29311      case 0x140: case 0x100:             // vaddcuq, vadduqm
29312      case 0x540: case 0x500:             // vsubcuq, vsubuqm
29313      case 0x54C:                         // vbpermq
29314         if (!allow_V) goto decode_noV;
29315         if (dis_av_quad( theInstr)) goto decode_success;
29316         goto decode_failure;
29317
29318      default:
29319         break;  // Fall through...
29320      }
29321
29322      opc2 = IFIELD(theInstr, 0, 10);
29323      switch (opc2) {
29324
29325      /* AV Compare */
29326      case 0x006: case 0x007: case 0x107: // vcmpequb, vcmpneb, vcmpnezb
29327      case 0x046: case 0x047: case 0x147: // vcmpequh, vcmpneh, vcmpnezh
29328      case 0x086: case 0x087: case 0x187: // vcmpequw, vcmpnew, vcmpnezw
29329      case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
29330      case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
29331         if (!allow_V) goto decode_noV;
29332         if (dis_av_cmp( theInstr )) goto decode_success;
29333         goto decode_failure;
29334
29335      case 0x0C7:                         // vcmpequd
29336      case 0x2C7:                         // vcmpgtud
29337      case 0x3C7:                         // vcmpgtsd
29338          if (!allow_isa_2_07) goto decode_noP8;
29339          if (dis_av_cmp( theInstr )) goto decode_success;
29340          goto decode_failure;
29341
29342      /* AV Floating Point Compare */
29343      case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
29344      case 0x3C6:                         // vcmpbfp
29345         if (!allow_V) goto decode_noV;
29346         if (dis_av_fp_cmp( theInstr )) goto decode_success;
29347         goto decode_failure;
29348
29349      default:
29350         goto decode_failure;
29351      }
29352      break;
29353
29354   default:
29355      goto decode_failure;
29356
29357   decode_noF:
29358      vassert(!allow_F);
29359      vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
29360		 "can't be handled by Valgrind on this host.  This instruction\n"
29361		 "requires a host that supports Floating Point instructions.\n",
29362		 theInstr);
29363      goto not_supported;
29364   decode_noV:
29365      vassert(!allow_V);
29366      vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
29367		 "that can't be handled by Valgrind.  If this instruction is an\n"
29368		 "Altivec instruction, Valgrind must be run on a host that supports"
29369		 "AltiVec instructions.  If the application was compiled for e500, then\n"
29370		 "unfortunately Valgrind does not yet support e500 instructions.\n",
29371		 theInstr);
29372      goto not_supported;
29373   decode_noVX:
29374      vassert(!allow_VX);
29375      vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
29376		 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
29377		 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
29378		 theInstr);
29379      goto not_supported;
29380   decode_noFX:
29381      vassert(!allow_FX);
29382      vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
29383		 "that can't be handled by Valgrind on this host. This instruction\n"
29384		 "requires a host that supports the General Purpose-Optional instructions.\n",
29385		 theInstr);
29386      goto not_supported;
29387   decode_noGX:
29388      vassert(!allow_GX);
29389      vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
29390		 "that can't be handled by Valgrind on this host. This instruction\n"
29391		 "requires a host that supports the Graphic-Optional instructions.\n",
29392		 theInstr);
29393      goto not_supported;
29394   decode_noDFP:
29395      vassert(!allow_DFP);
29396      vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
29397		 "that can't be handled by Valgrind on this host.  This instruction\n"
29398		 "requires a host that supports DFP instructions.\n",
29399		 theInstr);
29400      goto not_supported;
29401   decode_noP8:
29402      vassert(!allow_isa_2_07);
29403      vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
29404		 "by Valgrind on this host.  This instruction requires a host that\n"
29405		 "supports Power 8 instructions.\n",
29406		 theInstr);
29407      goto not_supported;
29408
29409   decode_noP9:
29410      vassert(!allow_isa_3_0);
29411      vex_printf("disInstr(ppc): found the Power 9 instruction 0x%x that can't be handled\n"
29412                 "by Valgrind on this host.  This instruction requires a host that\n"
29413		 "supports Power 9 instructions.\n",
29414		 theInstr);
29415      goto not_supported;
29416
29417   decode_failure:
29418   /* All decode failures end up here. */
29419   opc2 = (theInstr) & 0x7FF;
29420   if (sigill_diag) {
29421      vex_printf("disInstr(ppc): unhandled instruction: "
29422                 "0x%x\n", theInstr);
29423      vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
29424                 opc1, opc1, opc2, opc2);
29425   }
29426
29427   not_supported:
29428   /* Tell the dispatcher that this insn cannot be decoded, and so has
29429      not been executed, and (is currently) the next to be executed.
29430      CIA should be up-to-date since it made so at the start of each
29431      insn, but nevertheless be paranoid and update it again right
29432      now. */
29433   putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
29434   dres.len         = 0;
29435   dres.whatNext    = Dis_StopHere;
29436   dres.jk_StopHere = Ijk_NoDecode;
29437   dres.continueAt  = 0;
29438   return dres;
29439   } /* switch (opc) for the main (primary) opcode switch. */
29440
29441  decode_success:
29442   /* All decode successes end up here. */
29443   switch (dres.whatNext) {
29444      case Dis_Continue:
29445         putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
29446         break;
29447      case Dis_ResteerU:
29448      case Dis_ResteerC:
29449         putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
29450         break;
29451      case Dis_StopHere:
29452         break;
29453      default:
29454         vassert(0);
29455   }
29456   DIP("\n");
29457
29458   if (dres.len == 0) {
29459      dres.len = 4;
29460   } else {
29461      vassert(dres.len == 20);
29462   }
29463   return dres;
29464}
29465
29466#undef DIP
29467#undef DIS
29468
29469
29470/*------------------------------------------------------------*/
29471/*--- Top-level fn                                         ---*/
29472/*------------------------------------------------------------*/
29473
29474/* Disassemble a single instruction into IR.  The instruction
29475   is located in host memory at &guest_code[delta]. */
29476
29477DisResult disInstr_PPC ( IRSB*        irsb_IN,
29478                         Bool         (*resteerOkFn) ( void*, Addr ),
29479                         Bool         resteerCisOk,
29480                         void*        callback_opaque,
29481                         const UChar* guest_code_IN,
29482                         Long         delta,
29483                         Addr         guest_IP,
29484                         VexArch      guest_arch,
29485                         const VexArchInfo* archinfo,
29486                         const VexAbiInfo*  abiinfo,
29487                         VexEndness   host_endness_IN,
29488                         Bool         sigill_diag_IN )
29489{
29490   IRType     ty;
29491   DisResult  dres;
29492   UInt       mask32, mask64;
29493   UInt hwcaps_guest = archinfo->hwcaps;
29494
29495   vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
29496
29497   /* global -- ick */
29498   mode64 = guest_arch == VexArchPPC64;
29499   ty = mode64 ? Ity_I64 : Ity_I32;
29500   if (!mode64 && (host_endness_IN == VexEndnessLE)) {
29501      vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
29502      dres.len         = 0;
29503      dres.whatNext    = Dis_StopHere;
29504      dres.jk_StopHere = Ijk_NoDecode;
29505      dres.continueAt   = 0;
29506      dres.hint        = Dis_HintNone;
29507      return dres;
29508   }
29509
29510   /* do some sanity checks */
29511   mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
29512            | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
29513            | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
29514
29515   mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
29516            | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
29517            | VEX_HWCAPS_PPC64_ISA2_07 | VEX_HWCAPS_PPC64_ISA3_0;
29518
29519   if (mode64) {
29520      vassert((hwcaps_guest & mask32) == 0);
29521   } else {
29522      vassert((hwcaps_guest & mask64) == 0);
29523   }
29524
29525   /* Set globals (see top of this file) */
29526   guest_code           = guest_code_IN;
29527   irsb                 = irsb_IN;
29528   host_endness         = host_endness_IN;
29529
29530   guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
29531   guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
29532
29533   dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
29534                             delta, archinfo, abiinfo, sigill_diag_IN);
29535
29536   return dres;
29537}
29538
29539
29540/*------------------------------------------------------------*/
29541/*--- Unused stuff                                         ---*/
29542/*------------------------------------------------------------*/
29543
29544///* A potentially more memcheck-friendly implementation of Clz32, with
29545//   the boundary case Clz32(0) = 32, which is what ppc requires. */
29546//
29547//static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
29548//{
29549//   /* Welcome ... to SSA R Us. */
29550//   IRTemp n1  = newTemp(Ity_I32);
29551//   IRTemp n2  = newTemp(Ity_I32);
29552//   IRTemp n3  = newTemp(Ity_I32);
29553//   IRTemp n4  = newTemp(Ity_I32);
29554//   IRTemp n5  = newTemp(Ity_I32);
29555//   IRTemp n6  = newTemp(Ity_I32);
29556//   IRTemp n7  = newTemp(Ity_I32);
29557//   IRTemp n8  = newTemp(Ity_I32);
29558//   IRTemp n9  = newTemp(Ity_I32);
29559//   IRTemp n10 = newTemp(Ity_I32);
29560//   IRTemp n11 = newTemp(Ity_I32);
29561//   IRTemp n12 = newTemp(Ity_I32);
29562//
29563//   /* First, propagate the most significant 1-bit into all lower
29564//      positions in the word. */
29565//   /* unsigned int clz ( unsigned int n )
29566//      {
29567//         n |= (n >> 1);
29568//         n |= (n >> 2);
29569//         n |= (n >> 4);
29570//         n |= (n >> 8);
29571//         n |= (n >> 16);
29572//         return bitcount(~n);
29573//      }
29574//   */
29575//   assign(n1, mkexpr(arg));
29576//   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
29577//   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
29578//   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
29579//   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
29580//   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
29581//   /* This gives a word of the form 0---01---1.  Now invert it, giving
29582//      a word of the form 1---10---0, then do a population-count idiom
29583//      (to count the 1s, which is the number of leading zeroes, or 32
29584//      if the original word was 0. */
29585//   assign(n7, unop(Iop_Not32, mkexpr(n6)));
29586//
29587//   /* unsigned int bitcount ( unsigned int n )
29588//      {
29589//         n = n - ((n >> 1) & 0x55555555);
29590//         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
29591//         n = (n + (n >> 4)) & 0x0F0F0F0F;
29592//         n = n + (n >> 8);
29593//         n = (n + (n >> 16)) & 0x3F;
29594//         return n;
29595//      }
29596//   */
29597//   assign(n8,
29598//          binop(Iop_Sub32,
29599//                mkexpr(n7),
29600//                binop(Iop_And32,
29601//                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
29602//                      mkU32(0x55555555))));
29603//   assign(n9,
29604//          binop(Iop_Add32,
29605//                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
29606//                binop(Iop_And32,
29607//                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
29608//                      mkU32(0x33333333))));
29609//   assign(n10,
29610//          binop(Iop_And32,
29611//                binop(Iop_Add32,
29612//                      mkexpr(n9),
29613//                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
29614//                mkU32(0x0F0F0F0F)));
29615//   assign(n11,
29616//          binop(Iop_Add32,
29617//                mkexpr(n10),
29618//                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
29619//   assign(n12,
29620//          binop(Iop_Add32,
29621//                mkexpr(n11),
29622//                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
29623//   return
29624//      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
29625//}
29626
29627/*--------------------------------------------------------------------*/
29628/*--- end                                         guest_ppc_toIR.c ---*/
29629/*--------------------------------------------------------------------*/
29630