1
2
3/*--------------------------------------------------------------------*/
4/*--- begin                                       guest_ppc_toIR.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
10
11   Copyright (C) 2004-2013 OpenWorks LLP
12      info@open-works.net
13
14   This program is free software; you can redistribute it and/or
15   modify it under the terms of the GNU General Public License as
16   published by the Free Software Foundation; either version 2 of the
17   License, or (at your option) any later version.
18
19   This program is distributed in the hope that it will be useful, but
20   WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22   General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, write to the Free Software
26   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27   02110-1301, USA.
28
29   The GNU General Public License is contained in the file COPYING.
30
31   Neither the names of the U.S. Department of Energy nor the
32   University of California nor the names of its contributors may be
33   used to endorse or promote products derived from this software
34   without prior written permission.
35*/
36
37/* TODO 18/Nov/05:
38
39   Spot rld... cases which are simply left/right shifts and emit
40   Shl64/Shr64 accordingly.
41
42   Altivec
43   - datastream insns
44   - lvxl,stvxl: load/store with 'least recently used' hint
45   - vexptefp, vlogefp
46
47   LIMITATIONS:
48
49   Various, including:
50
51   - Some invalid forms of lswi and lswx are accepted when they should
52     not be.
53
54   - Floating Point:
55     - All exceptions disabled in FPSCR
56     - condition codes not set in FPSCR
57
58   - Altivec floating point:
59     - vmaddfp, vnmsubfp
60       Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
61       system default of Non-Java mode, we get some small errors
62       (lowest bit only).
63       This is because Non-Java mode brutally hacks denormalised results
64       to zero, whereas we keep maximum accuracy.  However, using
65       Non-Java mode would give us more inaccuracy, as our intermediate
66       results would then be zeroed, too.
67
68   - AbiHints for the stack red zone are only emitted for
69       unconditional calls and returns (bl, blr).  They should also be
70       emitted for conditional calls and returns, but we don't have a
71       way to express that right now.  Ah well.
72
73   - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c)
74       ignores the rounding mode, and generates code that assumes
75       round-to-nearest.  This means V will compute incorrect results
76       for uses of these IROps when the rounding mode (first) arg is
77       not mkU32(Irrm_NEAREST).
78*/
79
80/* "Special" instructions.
81
82   This instruction decoder can decode four special instructions
83   which mean nothing natively (are no-ops as far as regs/mem are
84   concerned) but have meaning for supporting Valgrind.  A special
85   instruction is flagged by a 16-byte preamble:
86
87      32-bit mode: 5400183E 5400683E 5400E83E 5400983E
88                   (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31;
89                    rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31)
90
91      64-bit mode: 78001800 78006800 7800E802 78009802
92                   (rotldi 0,0,3; rotldi 0,0,13;
93                    rotldi 0,0,61; rotldi 0,0,51)
94
95   Following that, one of the following 3 are allowed
96   (standard interpretation in parentheses):
97
98      7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
99      7C421378 (or 2,2,2)   %R3 = guest_NRADDR
100      7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11
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
111/* Translates PPC32/64 code to IR. */
112
113/* References
114
115#define PPC32
116   "PowerPC Microprocessor Family:
117    The Programming Environments Manual for 32-Bit Microprocessors"
118    02/21/2000
119    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
120
121#define PPC64
122   "PowerPC Microprocessor Family:
123    Programming Environments Manual for 64-Bit Microprocessors"
124    06/10/2003
125   http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
126
127#define AV
128   "PowerPC Microprocessor Family:
129    AltiVec(TM) Technology Programming Environments Manual"
130    07/10/2003
131   http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
132*/
133
134#include "libvex_basictypes.h"
135#include "libvex_ir.h"
136#include "libvex.h"
137#include "libvex_emnote.h"
138#include "libvex_guest_ppc32.h"
139#include "libvex_guest_ppc64.h"
140
141#include "main_util.h"
142#include "main_globals.h"
143#include "guest_generic_bb_to_IR.h"
144#include "guest_ppc_defs.h"
145
146
147/*------------------------------------------------------------*/
148/*--- Globals                                              ---*/
149/*------------------------------------------------------------*/
150
151/* These are set at the start of the translation of an insn, right
152   down in disInstr_PPC, so that we don't have to pass them around
153   endlessly.  They are all constant during the translation of any
154   given insn. */
155
156/* We need to know this to do sub-register accesses correctly. */
157static Bool host_is_bigendian;
158
159/* Pointer to the guest code area. */
160static UChar* guest_code;
161
162/* The guest address corresponding to guest_code[0]. */
163static Addr64 guest_CIA_bbstart;
164
165/* The guest address for the instruction currently being
166   translated. */
167static Addr64 guest_CIA_curr_instr;
168
169/* The IRSB* into which we're generating code. */
170static IRSB* irsb;
171
172/* Is our guest binary 32 or 64bit?  Set at each call to
173   disInstr_PPC below. */
174static Bool mode64 = False;
175
176// Given a pointer to a function as obtained by "& functionname" in C,
177// produce a pointer to the actual entry point for the function.  For
178// most platforms it's the identity function.  Unfortunately, on
179// ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and
180// ppc64-aix5.
181static void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f )
182{
183   if (vbi->host_ppc_calls_use_fndescrs) {
184      /* f is a pointer to a 3-word function descriptor, of which the
185         first word is the entry address. */
186      /* note, this is correct even with cross-jitting, since this is
187         purely a host issue, not a guest one. */
188      HWord* fdescr = (HWord*)f;
189      return (void*)(fdescr[0]);
190   } else {
191      /* Simple; "& f" points directly at the code for f. */
192      return f;
193   }
194}
195
196#define SIGN_BIT  0x8000000000000000ULL
197#define SIGN_MASK 0x7fffffffffffffffULL
198#define SIGN_BIT32  0x80000000
199#define SIGN_MASK32 0x7fffffff
200
201
202/*------------------------------------------------------------*/
203/*--- Debugging output                                     ---*/
204/*------------------------------------------------------------*/
205
206#define DIP(format, args...)           \
207   if (vex_traceflags & VEX_TRACE_FE)  \
208      vex_printf(format, ## args)
209
210#define DIS(buf, format, args...)      \
211   if (vex_traceflags & VEX_TRACE_FE)  \
212      vex_sprintf(buf, format, ## args)
213
214
215/*------------------------------------------------------------*/
216/*--- Offsets of various parts of the ppc32/64 guest state ---*/
217/*------------------------------------------------------------*/
218
219#define offsetofPPCGuestState(_x) \
220   (mode64 ? offsetof(VexGuestPPC64State, _x) : \
221             offsetof(VexGuestPPC32State, _x))
222
223#define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
224#define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
225#define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
226#define OFFB_LR          offsetofPPCGuestState(guest_LR)
227#define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
228#define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
229#define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
230#define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
231#define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
232#define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
233#define OFFB_DFPROUND    offsetofPPCGuestState(guest_DFPROUND)
234#define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
235#define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
236#define OFFB_EMNOTE      offsetofPPCGuestState(guest_EMNOTE)
237#define OFFB_CMSTART     offsetofPPCGuestState(guest_CMSTART)
238#define OFFB_CMLEN       offsetofPPCGuestState(guest_CMLEN)
239#define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
240#define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
241#define OFFB_TFHAR       offsetofPPCGuestState(guest_TFHAR)
242#define OFFB_TEXASR      offsetofPPCGuestState(guest_TEXASR)
243#define OFFB_TFIAR       offsetofPPCGuestState(guest_TFIAR)
244
245
246/*------------------------------------------------------------*/
247/*--- Extract instruction fields                          --- */
248/*------------------------------------------------------------*/
249
250/* Extract field from insn, given idx (zero = lsb) and field length */
251#define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
252
253/* Extract primary opcode, instr[31:26] */
254static UChar ifieldOPC( UInt instr ) {
255   return toUChar( IFIELD( instr, 26, 6 ) );
256}
257
258/* Extract 10-bit secondary opcode, instr[10:1] */
259static UInt ifieldOPClo10 ( UInt instr) {
260   return IFIELD( instr, 1, 10 );
261}
262
263/* Extract 9-bit secondary opcode, instr[9:1] */
264static UInt ifieldOPClo9 ( UInt instr) {
265   return IFIELD( instr, 1, 9 );
266}
267
268/* Extract 8-bit secondary opcode, instr[8:1] */
269static UInt ifieldOPClo8 ( UInt instr) {
270   return IFIELD( instr, 1, 8 );
271}
272
273/* Extract 5-bit secondary opcode, instr[5:1] */
274static UInt ifieldOPClo5 ( UInt instr) {
275   return IFIELD( instr, 1, 5 );
276}
277
278/* Extract RD (destination register) field, instr[25:21] */
279static UChar ifieldRegDS( UInt instr ) {
280   return toUChar( IFIELD( instr, 21, 5 ) );
281}
282
283/* Extract XT (destination register) field, instr[0,25:21] */
284static UChar ifieldRegXT ( UInt instr )
285{
286  UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
287  UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
288  return (upper_bit << 5) | lower_bits;
289}
290
291/* Extract XS (store source register) field, instr[0,25:21] */
292static inline UChar ifieldRegXS ( UInt instr )
293{
294  return ifieldRegXT ( instr );
295}
296
297/* Extract RA (1st source register) field, instr[20:16] */
298static UChar ifieldRegA ( UInt instr ) {
299   return toUChar( IFIELD( instr, 16, 5 ) );
300}
301
302/* Extract XA (1st source register) field, instr[2,20:16] */
303static UChar ifieldRegXA ( UInt instr )
304{
305  UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
306  UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
307  return (upper_bit << 5) | lower_bits;
308}
309
310/* Extract RB (2nd source register) field, instr[15:11] */
311static UChar ifieldRegB ( UInt instr ) {
312   return toUChar( IFIELD( instr, 11, 5 ) );
313}
314
315/* Extract XB (2nd source register) field, instr[1,15:11] */
316static UChar ifieldRegXB ( UInt instr )
317{
318  UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
319  UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
320  return (upper_bit << 5) | lower_bits;
321}
322
323/* Extract RC (3rd source register) field, instr[10:6] */
324static UChar ifieldRegC ( UInt instr ) {
325   return toUChar( IFIELD( instr, 6, 5 ) );
326}
327
328/* Extract XC (3rd source register) field, instr[3,10:6] */
329static UChar ifieldRegXC ( UInt instr )
330{
331  UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
332  UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
333  return (upper_bit << 5) | lower_bits;
334}
335
336/* Extract bit 10, instr[10] */
337static UChar ifieldBIT10 ( UInt instr ) {
338   return toUChar( IFIELD( instr, 10, 1 ) );
339}
340
341/* Extract 2nd lowest bit, instr[1] */
342static UChar ifieldBIT1 ( UInt instr ) {
343   return toUChar( IFIELD( instr, 1, 1 ) );
344}
345
346/* Extract lowest bit, instr[0] */
347static UChar ifieldBIT0 ( UInt instr ) {
348   return toUChar( instr & 0x1 );
349}
350
351/* Extract unsigned bottom half, instr[15:0] */
352static UInt ifieldUIMM16 ( UInt instr ) {
353   return instr & 0xFFFF;
354}
355
356/* Extract unsigned bottom 26 bits, instr[25:0] */
357static UInt ifieldUIMM26 ( UInt instr ) {
358   return instr & 0x3FFFFFF;
359}
360
361/* Extract DM field, instr[9:8] */
362static UChar ifieldDM ( UInt instr ) {
363   return toUChar( IFIELD( instr, 8, 2 ) );
364}
365
366/* Extract SHW field, instr[9:8] */
367static inline UChar ifieldSHW ( UInt instr )
368{
369  return ifieldDM ( instr );
370}
371
372/*------------------------------------------------------------*/
373/*--- Guest-state identifiers                              ---*/
374/*------------------------------------------------------------*/
375
376typedef enum {
377    PPC_GST_CIA,    // Current Instruction Address
378    PPC_GST_LR,     // Link Register
379    PPC_GST_CTR,    // Count Register
380    PPC_GST_XER,    // Overflow, carry flags, byte count
381    PPC_GST_CR,     // Condition Register
382    PPC_GST_FPSCR,  // Floating Point Status/Control Register
383    PPC_GST_VRSAVE, // Vector Save/Restore Register
384    PPC_GST_VSCR,   // Vector Status and Control Register
385    PPC_GST_EMWARN, // Emulation warnings
386    PPC_GST_CMSTART,// For icbi: start of area to invalidate
387    PPC_GST_CMLEN,  // For icbi: length of area to invalidate
388    PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
389    PPC_GST_SPRG3_RO, // SPRG3
390    PPC_GST_TFHAR,  // Transactional Failure Handler Address Register
391    PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
392    PPC_GST_TEXASR, // Transactional EXception And Summary Register
393    PPC_GST_MAX
394} PPC_GST;
395
396#define MASK_FPSCR_RN   0x3ULL  // Binary floating point rounding mode
397#define MASK_FPSCR_DRN  0x700000000ULL // Decimal floating point rounding mode
398#define MASK_VSCR_VALID 0x00010001
399
400
401/*------------------------------------------------------------*/
402/*---  FP Helpers                                          ---*/
403/*------------------------------------------------------------*/
404
405/* Produce the 32-bit pattern corresponding to the supplied
406   float. */
407static UInt float_to_bits ( Float f )
408{
409   union { UInt i; Float f; } u;
410   vassert(4 == sizeof(UInt));
411   vassert(4 == sizeof(Float));
412   vassert(4 == sizeof(u));
413   u.f = f;
414   return u.i;
415}
416
417
418/*------------------------------------------------------------*/
419/*--- Misc Helpers                                         ---*/
420/*------------------------------------------------------------*/
421
422/* Generate mask with 1's from 'begin' through 'end',
423   wrapping if begin > end.
424   begin->end works from right to left, 0=lsb
425*/
426static UInt MASK32( UInt begin, UInt end )
427{
428   UInt m1, m2, mask;
429   vassert(begin < 32);
430   vassert(end < 32);
431   m1   = ((UInt)(-1)) << begin;
432   m2   = ((UInt)(-1)) << end << 1;
433   mask = m1 ^ m2;
434   if (begin > end) mask = ~mask;  // wrap mask
435   return mask;
436}
437
438static ULong MASK64( UInt begin, UInt end )
439{
440   ULong m1, m2, mask;
441   vassert(begin < 64);
442   vassert(end < 64);
443   m1   = ((ULong)(-1)) << begin;
444   m2   = ((ULong)(-1)) << end << 1;
445   mask = m1 ^ m2;
446   if (begin > end) mask = ~mask;  // wrap mask
447   return mask;
448}
449
450static Addr64 nextInsnAddr( void )
451{
452   return guest_CIA_curr_instr + 4;
453}
454
455
456/*------------------------------------------------------------*/
457/*--- Helper bits and pieces for deconstructing the        ---*/
458/*--- ppc32/64 insn stream.                                ---*/
459/*------------------------------------------------------------*/
460
461/* Add a statement to the list held by "irsb". */
462static void stmt ( IRStmt* st )
463{
464   addStmtToIRSB( irsb, st );
465}
466
467/* Generate a new temporary of the given type. */
468static IRTemp newTemp ( IRType ty )
469{
470   vassert(isPlausibleIRType(ty));
471   return newIRTemp( irsb->tyenv, ty );
472}
473
474/* Various simple conversions */
475
476static UChar extend_s_5to8 ( UChar x )
477{
478   return toUChar((((Int)x) << 27) >> 27);
479}
480
481static UInt extend_s_8to32( UChar x )
482{
483   return (UInt)((((Int)x) << 24) >> 24);
484}
485
486static UInt extend_s_16to32 ( UInt x )
487{
488   return (UInt)((((Int)x) << 16) >> 16);
489}
490
491static ULong extend_s_16to64 ( UInt x )
492{
493   return (ULong)((((Long)x) << 48) >> 48);
494}
495
496static ULong extend_s_26to64 ( UInt x )
497{
498   return (ULong)((((Long)x) << 38) >> 38);
499}
500
501static ULong extend_s_32to64 ( UInt x )
502{
503   return (ULong)((((Long)x) << 32) >> 32);
504}
505
506/* Do a big-endian load of a 32-bit word, regardless of the endianness
507   of the underlying host. */
508static UInt getUIntBigendianly ( UChar* p )
509{
510   UInt w = 0;
511   w = (w << 8) | p[0];
512   w = (w << 8) | p[1];
513   w = (w << 8) | p[2];
514   w = (w << 8) | p[3];
515   return w;
516}
517
518
519/*------------------------------------------------------------*/
520/*--- Helpers for constructing IR.                         ---*/
521/*------------------------------------------------------------*/
522
523static void assign ( IRTemp dst, IRExpr* e )
524{
525   stmt( IRStmt_WrTmp(dst, e) );
526}
527
528/* This generates a normal (non store-conditional) store. */
529static void storeBE ( IRExpr* addr, IRExpr* data )
530{
531   IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
532   vassert(tyA == Ity_I32 || tyA == Ity_I64);
533   stmt( IRStmt_Store(Iend_BE, addr, data) );
534}
535
536static IRExpr* unop ( IROp op, IRExpr* a )
537{
538   return IRExpr_Unop(op, a);
539}
540
541static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
542{
543   return IRExpr_Binop(op, a1, a2);
544}
545
546static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
547{
548   return IRExpr_Triop(op, a1, a2, a3);
549}
550
551static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
552                              IRExpr* a3, IRExpr* a4 )
553{
554   return IRExpr_Qop(op, a1, a2, a3, a4);
555}
556
557static IRExpr* mkexpr ( IRTemp tmp )
558{
559   return IRExpr_RdTmp(tmp);
560}
561
562static IRExpr* mkU8 ( UChar i )
563{
564   return IRExpr_Const(IRConst_U8(i));
565}
566
567static IRExpr* mkU16 ( UInt i )
568{
569   return IRExpr_Const(IRConst_U16(i));
570}
571
572static IRExpr* mkU32 ( UInt i )
573{
574   return IRExpr_Const(IRConst_U32(i));
575}
576
577static IRExpr* mkU64 ( ULong i )
578{
579   return IRExpr_Const(IRConst_U64(i));
580}
581
582static IRExpr* mkV128 ( UShort i )
583{
584   vassert(i == 0 || i == 0xffff);
585   return IRExpr_Const(IRConst_V128(i));
586}
587
588/* This generates a normal (non load-linked) load. */
589static IRExpr* loadBE ( IRType ty, IRExpr* addr )
590{
591   return IRExpr_Load(Iend_BE, ty, addr);
592}
593
594static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
595{
596   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
597   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
598   return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
599                                          unop(Iop_1Uto32, arg2)));
600}
601
602static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
603{
604   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
605   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
606   return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
607                                           unop(Iop_1Uto32, arg2)));
608}
609
610/* expand V128_8Ux16 to 2x V128_16Ux8's */
611static void expand8Ux16( IRExpr* vIn,
612                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
613{
614   IRTemp ones8x16 = newTemp(Ity_V128);
615
616   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
617   vassert(vEvn && *vEvn == IRTemp_INVALID);
618   vassert(vOdd && *vOdd == IRTemp_INVALID);
619   *vEvn = newTemp(Ity_V128);
620   *vOdd = newTemp(Ity_V128);
621
622   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
623   assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
624   assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
625                        binop(Iop_ShrV128, vIn, mkU8(8))) );
626}
627
628/* expand V128_8Sx16 to 2x V128_16Sx8's */
629static void expand8Sx16( IRExpr* vIn,
630                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
631{
632   IRTemp ones8x16 = newTemp(Ity_V128);
633
634   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
635   vassert(vEvn && *vEvn == IRTemp_INVALID);
636   vassert(vOdd && *vOdd == IRTemp_INVALID);
637   *vEvn = newTemp(Ity_V128);
638   *vOdd = newTemp(Ity_V128);
639
640   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
641   assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
642   assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
643                        binop(Iop_ShrV128, vIn, mkU8(8))) );
644}
645
646/* expand V128_16Uto8 to 2x V128_32Ux4's */
647static void expand16Ux8( IRExpr* vIn,
648                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
649{
650   IRTemp ones16x8 = newTemp(Ity_V128);
651
652   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
653   vassert(vEvn && *vEvn == IRTemp_INVALID);
654   vassert(vOdd && *vOdd == IRTemp_INVALID);
655   *vEvn = newTemp(Ity_V128);
656   *vOdd = newTemp(Ity_V128);
657
658   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
659   assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
660   assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
661                        binop(Iop_ShrV128, vIn, mkU8(16))) );
662}
663
664/* expand V128_16Sto8 to 2x V128_32Sx4's */
665static void expand16Sx8( IRExpr* vIn,
666                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
667{
668   IRTemp ones16x8 = newTemp(Ity_V128);
669
670   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
671   vassert(vEvn && *vEvn == IRTemp_INVALID);
672   vassert(vOdd && *vOdd == IRTemp_INVALID);
673   *vEvn = newTemp(Ity_V128);
674   *vOdd = newTemp(Ity_V128);
675
676   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
677   assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
678   assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
679                       binop(Iop_ShrV128, vIn, mkU8(16))) );
680}
681
682/* break V128 to 4xF64's*/
683static void breakV128to4xF64( IRExpr* t128,
684                              /*OUTs*/
685                              IRTemp* t3, IRTemp* t2,
686                              IRTemp* t1, IRTemp* t0 )
687{
688   IRTemp hi64 = newTemp(Ity_I64);
689   IRTemp lo64 = newTemp(Ity_I64);
690
691   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
692   vassert(t0 && *t0 == IRTemp_INVALID);
693   vassert(t1 && *t1 == IRTemp_INVALID);
694   vassert(t2 && *t2 == IRTemp_INVALID);
695   vassert(t3 && *t3 == IRTemp_INVALID);
696   *t0 = newTemp(Ity_F64);
697   *t1 = newTemp(Ity_F64);
698   *t2 = newTemp(Ity_F64);
699   *t3 = newTemp(Ity_F64);
700
701   assign( hi64, unop(Iop_V128HIto64, t128) );
702   assign( lo64, unop(Iop_V128to64,   t128) );
703   assign( *t3,
704           unop( Iop_F32toF64,
705                 unop( Iop_ReinterpI32asF32,
706                       unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
707   assign( *t2,
708           unop( Iop_F32toF64,
709                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
710   assign( *t1,
711           unop( Iop_F32toF64,
712                 unop( Iop_ReinterpI32asF32,
713                       unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
714   assign( *t0,
715           unop( Iop_F32toF64,
716                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
717}
718
719
720/* break V128 to 4xI32's, then sign-extend to I64's */
721static void breakV128to4x64S( IRExpr* t128,
722                              /*OUTs*/
723                              IRTemp* t3, IRTemp* t2,
724                              IRTemp* t1, IRTemp* t0 )
725{
726   IRTemp hi64 = newTemp(Ity_I64);
727   IRTemp lo64 = newTemp(Ity_I64);
728
729   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
730   vassert(t0 && *t0 == IRTemp_INVALID);
731   vassert(t1 && *t1 == IRTemp_INVALID);
732   vassert(t2 && *t2 == IRTemp_INVALID);
733   vassert(t3 && *t3 == IRTemp_INVALID);
734   *t0 = newTemp(Ity_I64);
735   *t1 = newTemp(Ity_I64);
736   *t2 = newTemp(Ity_I64);
737   *t3 = newTemp(Ity_I64);
738
739   assign( hi64, unop(Iop_V128HIto64, t128) );
740   assign( lo64, unop(Iop_V128to64,   t128) );
741   assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
742   assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
743   assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
744   assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
745}
746
747/* break V128 to 4xI32's, then zero-extend to I64's */
748static void breakV128to4x64U ( IRExpr* t128,
749                               /*OUTs*/
750                               IRTemp* t3, IRTemp* t2,
751                               IRTemp* t1, IRTemp* t0 )
752{
753   IRTemp hi64 = newTemp(Ity_I64);
754   IRTemp lo64 = newTemp(Ity_I64);
755
756   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
757   vassert(t0 && *t0 == IRTemp_INVALID);
758   vassert(t1 && *t1 == IRTemp_INVALID);
759   vassert(t2 && *t2 == IRTemp_INVALID);
760   vassert(t3 && *t3 == IRTemp_INVALID);
761   *t0 = newTemp(Ity_I64);
762   *t1 = newTemp(Ity_I64);
763   *t2 = newTemp(Ity_I64);
764   *t3 = newTemp(Ity_I64);
765
766   assign( hi64, unop(Iop_V128HIto64, t128) );
767   assign( lo64, unop(Iop_V128to64,   t128) );
768   assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
769   assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
770   assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
771   assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
772}
773
774static void breakV128to4x32( IRExpr* t128,
775                              /*OUTs*/
776                              IRTemp* t3, IRTemp* t2,
777                              IRTemp* t1, IRTemp* t0 )
778{
779   IRTemp hi64 = newTemp(Ity_I64);
780   IRTemp lo64 = newTemp(Ity_I64);
781
782   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
783   vassert(t0 && *t0 == IRTemp_INVALID);
784   vassert(t1 && *t1 == IRTemp_INVALID);
785   vassert(t2 && *t2 == IRTemp_INVALID);
786   vassert(t3 && *t3 == IRTemp_INVALID);
787   *t0 = newTemp(Ity_I32);
788   *t1 = newTemp(Ity_I32);
789   *t2 = newTemp(Ity_I32);
790   *t3 = newTemp(Ity_I32);
791
792   assign( hi64, unop(Iop_V128HIto64, t128) );
793   assign( lo64, unop(Iop_V128to64,   t128) );
794   assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
795   assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
796   assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
797   assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
798}
799
800static IRExpr* mkV128from32( IRTemp t3, IRTemp t2,
801                               IRTemp t1, IRTemp t0 )
802{
803   return
804      binop( Iop_64HLtoV128,
805             binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
806             binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
807   );
808}
809
810
811/* Signed saturating narrow 64S to 32 */
812static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
813{
814   IRTemp hi32 = newTemp(Ity_I32);
815   IRTemp lo32 = newTemp(Ity_I32);
816
817   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
818
819   assign( hi32, unop(Iop_64HIto32, t64));
820   assign( lo32, unop(Iop_64to32,   t64));
821
822   return IRExpr_ITE(
823             /* if (hi32 == (lo32 >>s 31)) */
824             binop(Iop_CmpEQ32, mkexpr(hi32),
825                   binop( Iop_Sar32, mkexpr(lo32), mkU8(31))),
826             /* then: within signed-32 range: lo half good enough */
827             mkexpr(lo32),
828             /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
829             binop(Iop_Add32, mkU32(0x7FFFFFFF),
830                   binop(Iop_Shr32, mkexpr(hi32), mkU8(31))));
831}
832
833/* Unsigned saturating narrow 64S to 32 */
834static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
835{
836   IRTemp hi32 = newTemp(Ity_I32);
837   IRTemp lo32 = newTemp(Ity_I32);
838
839   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
840
841   assign( hi32, unop(Iop_64HIto32, t64));
842   assign( lo32, unop(Iop_64to32,   t64));
843
844   return IRExpr_ITE(
845            /* if (top 32 bits of t64 are 0) */
846            binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)),
847            /* then: within unsigned-32 range: lo half good enough */
848            mkexpr(lo32),
849            /* else: positive saturate -> 0xFFFFFFFF */
850            mkU32(0xFFFFFFFF));
851}
852
853/* Signed saturate narrow 64->32, combining to V128 */
854static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
855                                 IRExpr* t1, IRExpr* t0 )
856{
857   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
858   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
859   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
860   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
861   return binop(Iop_64HLtoV128,
862                binop(Iop_32HLto64,
863                      mkQNarrow64Sto32( t3 ),
864                      mkQNarrow64Sto32( t2 )),
865                binop(Iop_32HLto64,
866                      mkQNarrow64Sto32( t1 ),
867                      mkQNarrow64Sto32( t0 )));
868}
869
870/* Unsigned saturate narrow 64->32, combining to V128 */
871static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
872                                 IRExpr* t1, IRExpr* t0 )
873{
874   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
875   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
876   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
877   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
878   return binop(Iop_64HLtoV128,
879                binop(Iop_32HLto64,
880                      mkQNarrow64Uto32( t3 ),
881                      mkQNarrow64Uto32( t2 )),
882                binop(Iop_32HLto64,
883                      mkQNarrow64Uto32( t1 ),
884                      mkQNarrow64Uto32( t0 )));
885}
886
887/* Simulate irops Iop_MullOdd*, since we don't have them  */
888#define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
889      binop(Iop_MullEven8Ux16, \
890            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
891            binop(Iop_ShrV128, expr_vB, mkU8(8)))
892
893#define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
894      binop(Iop_MullEven8Sx16, \
895            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
896            binop(Iop_ShrV128, expr_vB, mkU8(8)))
897
898#define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
899      binop(Iop_MullEven16Ux8, \
900            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
901            binop(Iop_ShrV128, expr_vB, mkU8(16)))
902
903#define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
904      binop(Iop_MullEven32Ux4, \
905            binop(Iop_ShrV128, expr_vA, mkU8(32)), \
906            binop(Iop_ShrV128, expr_vB, mkU8(32)))
907
908#define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
909      binop(Iop_MullEven16Sx8, \
910            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
911            binop(Iop_ShrV128, expr_vB, mkU8(16)))
912
913#define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
914      binop(Iop_MullEven32Sx4, \
915            binop(Iop_ShrV128, expr_vA, mkU8(32)), \
916            binop(Iop_ShrV128, expr_vB, mkU8(32)))
917
918
919static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
920{
921   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
922   return unop(Iop_32Sto64, unop(Iop_64to32, src));
923}
924
925static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
926{
927   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
928   return unop(Iop_32Uto64, unop(Iop_64to32, src));
929}
930
931static IROp mkSzOp ( IRType ty, IROp op8 )
932{
933   Int adj;
934   vassert(ty == Ity_I8  || ty == Ity_I16 ||
935           ty == Ity_I32 || ty == Ity_I64);
936   vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
937           op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
938           op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
939           op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
940           op8 == Iop_Not8 );
941   adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
942   return adj + op8;
943}
944
945/* Make sure we get valid 32 and 64bit addresses */
946static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
947{
948   vassert(ty == Ity_I32 || ty == Ity_I64);
949   return ( ty == Ity_I64 ?
950            (Addr64)addr :
951            (Addr64)extend_s_32to64( toUInt(addr) ) );
952}
953
954/* sz, ULong -> IRExpr */
955static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
956{
957   vassert(ty == Ity_I32 || ty == Ity_I64);
958   return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
959}
960
961/* sz, ULong -> IRConst */
962static IRConst* mkSzConst ( IRType ty, ULong imm64 )
963{
964   vassert(ty == Ity_I32 || ty == Ity_I64);
965   return ( ty == Ity_I64 ?
966            IRConst_U64(imm64) :
967            IRConst_U32((UInt)imm64) );
968}
969
970/* Sign extend imm16 -> IRExpr* */
971static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
972{
973   vassert(ty == Ity_I32 || ty == Ity_I64);
974   return ( ty == Ity_I64 ?
975            mkU64(extend_s_16to64(imm16)) :
976            mkU32(extend_s_16to32(imm16)) );
977}
978
979/* Sign extend imm32 -> IRExpr* */
980static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
981{
982   vassert(ty == Ity_I32 || ty == Ity_I64);
983   return ( ty == Ity_I64 ?
984            mkU64(extend_s_32to64(imm32)) :
985            mkU32(imm32) );
986}
987
988/* IR narrows I32/I64 -> I8/I16/I32 */
989static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
990{
991   vassert(ty == Ity_I32 || ty == Ity_I64);
992   return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
993}
994
995static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
996{
997   vassert(ty == Ity_I32 || ty == Ity_I64);
998   return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
999}
1000
1001static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
1002{
1003   vassert(ty == Ity_I32 || ty == Ity_I64);
1004   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
1005}
1006
1007/* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
1008static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
1009{
1010   IROp op;
1011   vassert(ty == Ity_I32 || ty == Ity_I64);
1012   if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
1013   else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
1014   return unop(op, src);
1015}
1016
1017static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
1018{
1019   IROp op;
1020   vassert(ty == Ity_I32 || ty == Ity_I64);
1021   if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
1022   else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
1023   return unop(op, src);
1024}
1025
1026static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
1027{
1028   vassert(ty == Ity_I32 || ty == Ity_I64);
1029   if (ty == Ity_I32)
1030      return src;
1031   return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
1032}
1033
1034
1035static Int integerGuestRegOffset ( UInt archreg )
1036{
1037   vassert(archreg < 32);
1038
1039   // jrs: probably not necessary; only matters if we reference sub-parts
1040   // of the ppc registers, but that isn't the case
1041   // later: this might affect Altivec though?
1042   vassert(host_is_bigendian);
1043
1044   switch (archreg) {
1045   case  0: return offsetofPPCGuestState(guest_GPR0);
1046   case  1: return offsetofPPCGuestState(guest_GPR1);
1047   case  2: return offsetofPPCGuestState(guest_GPR2);
1048   case  3: return offsetofPPCGuestState(guest_GPR3);
1049   case  4: return offsetofPPCGuestState(guest_GPR4);
1050   case  5: return offsetofPPCGuestState(guest_GPR5);
1051   case  6: return offsetofPPCGuestState(guest_GPR6);
1052   case  7: return offsetofPPCGuestState(guest_GPR7);
1053   case  8: return offsetofPPCGuestState(guest_GPR8);
1054   case  9: return offsetofPPCGuestState(guest_GPR9);
1055   case 10: return offsetofPPCGuestState(guest_GPR10);
1056   case 11: return offsetofPPCGuestState(guest_GPR11);
1057   case 12: return offsetofPPCGuestState(guest_GPR12);
1058   case 13: return offsetofPPCGuestState(guest_GPR13);
1059   case 14: return offsetofPPCGuestState(guest_GPR14);
1060   case 15: return offsetofPPCGuestState(guest_GPR15);
1061   case 16: return offsetofPPCGuestState(guest_GPR16);
1062   case 17: return offsetofPPCGuestState(guest_GPR17);
1063   case 18: return offsetofPPCGuestState(guest_GPR18);
1064   case 19: return offsetofPPCGuestState(guest_GPR19);
1065   case 20: return offsetofPPCGuestState(guest_GPR20);
1066   case 21: return offsetofPPCGuestState(guest_GPR21);
1067   case 22: return offsetofPPCGuestState(guest_GPR22);
1068   case 23: return offsetofPPCGuestState(guest_GPR23);
1069   case 24: return offsetofPPCGuestState(guest_GPR24);
1070   case 25: return offsetofPPCGuestState(guest_GPR25);
1071   case 26: return offsetofPPCGuestState(guest_GPR26);
1072   case 27: return offsetofPPCGuestState(guest_GPR27);
1073   case 28: return offsetofPPCGuestState(guest_GPR28);
1074   case 29: return offsetofPPCGuestState(guest_GPR29);
1075   case 30: return offsetofPPCGuestState(guest_GPR30);
1076   case 31: return offsetofPPCGuestState(guest_GPR31);
1077   default: break;
1078   }
1079   vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1080}
1081
1082static IRExpr* getIReg ( UInt archreg )
1083{
1084   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1085   vassert(archreg < 32);
1086   return IRExpr_Get( integerGuestRegOffset(archreg), ty );
1087}
1088
1089/* Ditto, but write to a reg instead. */
1090static void putIReg ( UInt archreg, IRExpr* e )
1091{
1092   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1093   vassert(archreg < 32);
1094   vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
1095   stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
1096}
1097
1098
1099/* Floating point egisters are mapped to VSX registers[0..31]. */
1100static Int floatGuestRegOffset ( UInt archreg )
1101{
1102   vassert(archreg < 32);
1103
1104   switch (archreg) {
1105   case  0: return offsetofPPCGuestState(guest_VSR0);
1106   case  1: return offsetofPPCGuestState(guest_VSR1);
1107   case  2: return offsetofPPCGuestState(guest_VSR2);
1108   case  3: return offsetofPPCGuestState(guest_VSR3);
1109   case  4: return offsetofPPCGuestState(guest_VSR4);
1110   case  5: return offsetofPPCGuestState(guest_VSR5);
1111   case  6: return offsetofPPCGuestState(guest_VSR6);
1112   case  7: return offsetofPPCGuestState(guest_VSR7);
1113   case  8: return offsetofPPCGuestState(guest_VSR8);
1114   case  9: return offsetofPPCGuestState(guest_VSR9);
1115   case 10: return offsetofPPCGuestState(guest_VSR10);
1116   case 11: return offsetofPPCGuestState(guest_VSR11);
1117   case 12: return offsetofPPCGuestState(guest_VSR12);
1118   case 13: return offsetofPPCGuestState(guest_VSR13);
1119   case 14: return offsetofPPCGuestState(guest_VSR14);
1120   case 15: return offsetofPPCGuestState(guest_VSR15);
1121   case 16: return offsetofPPCGuestState(guest_VSR16);
1122   case 17: return offsetofPPCGuestState(guest_VSR17);
1123   case 18: return offsetofPPCGuestState(guest_VSR18);
1124   case 19: return offsetofPPCGuestState(guest_VSR19);
1125   case 20: return offsetofPPCGuestState(guest_VSR20);
1126   case 21: return offsetofPPCGuestState(guest_VSR21);
1127   case 22: return offsetofPPCGuestState(guest_VSR22);
1128   case 23: return offsetofPPCGuestState(guest_VSR23);
1129   case 24: return offsetofPPCGuestState(guest_VSR24);
1130   case 25: return offsetofPPCGuestState(guest_VSR25);
1131   case 26: return offsetofPPCGuestState(guest_VSR26);
1132   case 27: return offsetofPPCGuestState(guest_VSR27);
1133   case 28: return offsetofPPCGuestState(guest_VSR28);
1134   case 29: return offsetofPPCGuestState(guest_VSR29);
1135   case 30: return offsetofPPCGuestState(guest_VSR30);
1136   case 31: return offsetofPPCGuestState(guest_VSR31);
1137   default: break;
1138   }
1139   vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1140}
1141
1142static IRExpr* getFReg ( UInt archreg )
1143{
1144   vassert(archreg < 32);
1145   return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1146}
1147
1148/* Ditto, but write to a reg instead. */
1149static void putFReg ( UInt archreg, IRExpr* e )
1150{
1151   vassert(archreg < 32);
1152   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1153   stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1154}
1155
1156/* get Decimal float value.  Note, they share floating point register file. */
1157static IRExpr* getDReg(UInt archreg) {
1158   IRExpr *e;
1159   vassert( archreg < 32 );
1160   e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
1161   return e;
1162}
1163static IRExpr* getDReg32(UInt archreg) {
1164   IRExpr *e;
1165   vassert( archreg < 32 );
1166   e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
1167   return e;
1168}
1169
1170/* Read a floating point register pair and combine their contents into a
1171 128-bit value */
1172static IRExpr *getDReg_pair(UInt archreg) {
1173   IRExpr *high = getDReg( archreg );
1174   IRExpr *low = getDReg( archreg + 1 );
1175
1176   return binop( Iop_D64HLtoD128, high, low );
1177}
1178
1179/* Ditto, but write to a reg instead. */
1180static void putDReg32(UInt archreg, IRExpr* e) {
1181   vassert( archreg < 32 );
1182   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
1183   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1184}
1185
1186static void putDReg(UInt archreg, IRExpr* e) {
1187   vassert( archreg < 32 );
1188   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
1189   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1190}
1191
1192/* Write a 128-bit floating point value into a register pair. */
1193static void putDReg_pair(UInt archreg, IRExpr *e) {
1194   IRTemp low = newTemp( Ity_D64 );
1195   IRTemp high = newTemp( Ity_D64 );
1196
1197   vassert( archreg < 32 );
1198   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
1199
1200   assign( low, unop( Iop_D128LOtoD64, e ) );
1201   assign( high, unop( Iop_D128HItoD64, e ) );
1202
1203   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
1204   stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
1205}
1206
1207static Int vsxGuestRegOffset ( UInt archreg )
1208{
1209   vassert(archreg < 64);
1210   switch (archreg) {
1211   case  0: return offsetofPPCGuestState(guest_VSR0);
1212   case  1: return offsetofPPCGuestState(guest_VSR1);
1213   case  2: return offsetofPPCGuestState(guest_VSR2);
1214   case  3: return offsetofPPCGuestState(guest_VSR3);
1215   case  4: return offsetofPPCGuestState(guest_VSR4);
1216   case  5: return offsetofPPCGuestState(guest_VSR5);
1217   case  6: return offsetofPPCGuestState(guest_VSR6);
1218   case  7: return offsetofPPCGuestState(guest_VSR7);
1219   case  8: return offsetofPPCGuestState(guest_VSR8);
1220   case  9: return offsetofPPCGuestState(guest_VSR9);
1221   case 10: return offsetofPPCGuestState(guest_VSR10);
1222   case 11: return offsetofPPCGuestState(guest_VSR11);
1223   case 12: return offsetofPPCGuestState(guest_VSR12);
1224   case 13: return offsetofPPCGuestState(guest_VSR13);
1225   case 14: return offsetofPPCGuestState(guest_VSR14);
1226   case 15: return offsetofPPCGuestState(guest_VSR15);
1227   case 16: return offsetofPPCGuestState(guest_VSR16);
1228   case 17: return offsetofPPCGuestState(guest_VSR17);
1229   case 18: return offsetofPPCGuestState(guest_VSR18);
1230   case 19: return offsetofPPCGuestState(guest_VSR19);
1231   case 20: return offsetofPPCGuestState(guest_VSR20);
1232   case 21: return offsetofPPCGuestState(guest_VSR21);
1233   case 22: return offsetofPPCGuestState(guest_VSR22);
1234   case 23: return offsetofPPCGuestState(guest_VSR23);
1235   case 24: return offsetofPPCGuestState(guest_VSR24);
1236   case 25: return offsetofPPCGuestState(guest_VSR25);
1237   case 26: return offsetofPPCGuestState(guest_VSR26);
1238   case 27: return offsetofPPCGuestState(guest_VSR27);
1239   case 28: return offsetofPPCGuestState(guest_VSR28);
1240   case 29: return offsetofPPCGuestState(guest_VSR29);
1241   case 30: return offsetofPPCGuestState(guest_VSR30);
1242   case 31: return offsetofPPCGuestState(guest_VSR31);
1243   case 32: return offsetofPPCGuestState(guest_VSR32);
1244   case 33: return offsetofPPCGuestState(guest_VSR33);
1245   case 34: return offsetofPPCGuestState(guest_VSR34);
1246   case 35: return offsetofPPCGuestState(guest_VSR35);
1247   case 36: return offsetofPPCGuestState(guest_VSR36);
1248   case 37: return offsetofPPCGuestState(guest_VSR37);
1249   case 38: return offsetofPPCGuestState(guest_VSR38);
1250   case 39: return offsetofPPCGuestState(guest_VSR39);
1251   case 40: return offsetofPPCGuestState(guest_VSR40);
1252   case 41: return offsetofPPCGuestState(guest_VSR41);
1253   case 42: return offsetofPPCGuestState(guest_VSR42);
1254   case 43: return offsetofPPCGuestState(guest_VSR43);
1255   case 44: return offsetofPPCGuestState(guest_VSR44);
1256   case 45: return offsetofPPCGuestState(guest_VSR45);
1257   case 46: return offsetofPPCGuestState(guest_VSR46);
1258   case 47: return offsetofPPCGuestState(guest_VSR47);
1259   case 48: return offsetofPPCGuestState(guest_VSR48);
1260   case 49: return offsetofPPCGuestState(guest_VSR49);
1261   case 50: return offsetofPPCGuestState(guest_VSR50);
1262   case 51: return offsetofPPCGuestState(guest_VSR51);
1263   case 52: return offsetofPPCGuestState(guest_VSR52);
1264   case 53: return offsetofPPCGuestState(guest_VSR53);
1265   case 54: return offsetofPPCGuestState(guest_VSR54);
1266   case 55: return offsetofPPCGuestState(guest_VSR55);
1267   case 56: return offsetofPPCGuestState(guest_VSR56);
1268   case 57: return offsetofPPCGuestState(guest_VSR57);
1269   case 58: return offsetofPPCGuestState(guest_VSR58);
1270   case 59: return offsetofPPCGuestState(guest_VSR59);
1271   case 60: return offsetofPPCGuestState(guest_VSR60);
1272   case 61: return offsetofPPCGuestState(guest_VSR61);
1273   case 62: return offsetofPPCGuestState(guest_VSR62);
1274   case 63: return offsetofPPCGuestState(guest_VSR63);
1275   default: break;
1276   }
1277   vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1278}
1279
1280/* Vector registers are mapped to VSX registers[32..63]. */
1281static Int vectorGuestRegOffset ( UInt archreg )
1282{
1283   vassert(archreg < 32);
1284
1285   switch (archreg) {
1286   case  0: return offsetofPPCGuestState(guest_VSR32);
1287   case  1: return offsetofPPCGuestState(guest_VSR33);
1288   case  2: return offsetofPPCGuestState(guest_VSR34);
1289   case  3: return offsetofPPCGuestState(guest_VSR35);
1290   case  4: return offsetofPPCGuestState(guest_VSR36);
1291   case  5: return offsetofPPCGuestState(guest_VSR37);
1292   case  6: return offsetofPPCGuestState(guest_VSR38);
1293   case  7: return offsetofPPCGuestState(guest_VSR39);
1294   case  8: return offsetofPPCGuestState(guest_VSR40);
1295   case  9: return offsetofPPCGuestState(guest_VSR41);
1296   case 10: return offsetofPPCGuestState(guest_VSR42);
1297   case 11: return offsetofPPCGuestState(guest_VSR43);
1298   case 12: return offsetofPPCGuestState(guest_VSR44);
1299   case 13: return offsetofPPCGuestState(guest_VSR45);
1300   case 14: return offsetofPPCGuestState(guest_VSR46);
1301   case 15: return offsetofPPCGuestState(guest_VSR47);
1302   case 16: return offsetofPPCGuestState(guest_VSR48);
1303   case 17: return offsetofPPCGuestState(guest_VSR49);
1304   case 18: return offsetofPPCGuestState(guest_VSR50);
1305   case 19: return offsetofPPCGuestState(guest_VSR51);
1306   case 20: return offsetofPPCGuestState(guest_VSR52);
1307   case 21: return offsetofPPCGuestState(guest_VSR53);
1308   case 22: return offsetofPPCGuestState(guest_VSR54);
1309   case 23: return offsetofPPCGuestState(guest_VSR55);
1310   case 24: return offsetofPPCGuestState(guest_VSR56);
1311   case 25: return offsetofPPCGuestState(guest_VSR57);
1312   case 26: return offsetofPPCGuestState(guest_VSR58);
1313   case 27: return offsetofPPCGuestState(guest_VSR59);
1314   case 28: return offsetofPPCGuestState(guest_VSR60);
1315   case 29: return offsetofPPCGuestState(guest_VSR61);
1316   case 30: return offsetofPPCGuestState(guest_VSR62);
1317   case 31: return offsetofPPCGuestState(guest_VSR63);
1318   default: break;
1319   }
1320   vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1321}
1322
1323static IRExpr* getVReg ( UInt archreg )
1324{
1325   vassert(archreg < 32);
1326   return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1327}
1328
1329/* Ditto, but write to a reg instead. */
1330static void putVReg ( UInt archreg, IRExpr* e )
1331{
1332   vassert(archreg < 32);
1333   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1334   stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1335}
1336
1337/* Get contents of VSX guest register */
1338static IRExpr* getVSReg ( UInt archreg )
1339{
1340   vassert(archreg < 64);
1341   return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
1342}
1343
1344/* Ditto, but write to a VSX reg instead. */
1345static void putVSReg ( UInt archreg, IRExpr* e )
1346{
1347   vassert(archreg < 64);
1348   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1349   stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
1350}
1351
1352
1353static Int guestCR321offset ( UInt cr )
1354{
1355   switch (cr) {
1356   case 0: return offsetofPPCGuestState(guest_CR0_321 );
1357   case 1: return offsetofPPCGuestState(guest_CR1_321 );
1358   case 2: return offsetofPPCGuestState(guest_CR2_321 );
1359   case 3: return offsetofPPCGuestState(guest_CR3_321 );
1360   case 4: return offsetofPPCGuestState(guest_CR4_321 );
1361   case 5: return offsetofPPCGuestState(guest_CR5_321 );
1362   case 6: return offsetofPPCGuestState(guest_CR6_321 );
1363   case 7: return offsetofPPCGuestState(guest_CR7_321 );
1364   default: vpanic("guestCR321offset(ppc)");
1365   }
1366}
1367
1368static Int guestCR0offset ( UInt cr )
1369{
1370   switch (cr) {
1371   case 0: return offsetofPPCGuestState(guest_CR0_0 );
1372   case 1: return offsetofPPCGuestState(guest_CR1_0 );
1373   case 2: return offsetofPPCGuestState(guest_CR2_0 );
1374   case 3: return offsetofPPCGuestState(guest_CR3_0 );
1375   case 4: return offsetofPPCGuestState(guest_CR4_0 );
1376   case 5: return offsetofPPCGuestState(guest_CR5_0 );
1377   case 6: return offsetofPPCGuestState(guest_CR6_0 );
1378   case 7: return offsetofPPCGuestState(guest_CR7_0 );
1379   default: vpanic("guestCR3offset(ppc)");
1380   }
1381}
1382
1383typedef enum {
1384   _placeholder0,
1385   _placeholder1,
1386   _placeholder2,
1387   BYTE,
1388   HWORD,
1389   WORD,
1390   DWORD
1391} _popcount_data_type;
1392
1393/* Generate an IR sequence to do a popcount operation on the supplied
1394   IRTemp, and return a new IRTemp holding the result.  'ty' may be
1395   Ity_I32 or Ity_I64 only. */
1396static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type )
1397{
1398  /* Do count across 2^data_type bits,
1399     byte:        data_type = 3
1400     half word:   data_type = 4
1401     word:        data_type = 5
1402     double word: data_type = 6  (not supported for 32-bit type)
1403    */
1404   Int shift[6];
1405   _popcount_data_type idx, i;
1406   IRTemp mask[6];
1407   IRTemp old = IRTemp_INVALID;
1408   IRTemp nyu = IRTemp_INVALID;
1409
1410   vassert(ty == Ity_I64 || ty == Ity_I32);
1411
1412   if (ty == Ity_I32) {
1413
1414      for (idx = 0; idx < WORD; idx++) {
1415         mask[idx]  = newTemp(ty);
1416         shift[idx] = 1 << idx;
1417      }
1418      assign(mask[0], mkU32(0x55555555));
1419      assign(mask[1], mkU32(0x33333333));
1420      assign(mask[2], mkU32(0x0F0F0F0F));
1421      assign(mask[3], mkU32(0x00FF00FF));
1422      assign(mask[4], mkU32(0x0000FFFF));
1423      old = src;
1424      for (i = 0; i < data_type; i++) {
1425         nyu = newTemp(ty);
1426         assign(nyu,
1427                binop(Iop_Add32,
1428                      binop(Iop_And32,
1429                            mkexpr(old),
1430                            mkexpr(mask[i])),
1431                      binop(Iop_And32,
1432                            binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1433                            mkexpr(mask[i]))));
1434         old = nyu;
1435      }
1436      return nyu;
1437   }
1438
1439// else, ty == Ity_I64
1440   vassert(mode64);
1441
1442   for (i = 0; i < DWORD; i++) {
1443      mask[i] = newTemp( Ity_I64 );
1444      shift[i] = 1 << i;
1445   }
1446   assign( mask[0], mkU64( 0x5555555555555555ULL ) );
1447   assign( mask[1], mkU64( 0x3333333333333333ULL ) );
1448   assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
1449   assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
1450   assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
1451   assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
1452   old = src;
1453   for (i = 0; i < data_type; i++) {
1454      nyu = newTemp( Ity_I64 );
1455      assign( nyu,
1456              binop( Iop_Add64,
1457                     binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
1458                     binop( Iop_And64,
1459                            binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
1460                            mkexpr( mask[i] ) ) ) );
1461      old = nyu;
1462   }
1463   return nyu;
1464}
1465
1466/* Special purpose population count function for
1467 * vpopcntd in 32-bit mode.
1468 */
1469static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 )
1470{
1471   Int i, shift[6];
1472   IRTemp mask[6];
1473   IRTemp old = IRTemp_INVALID;
1474   IRTemp nyu1 = IRTemp_INVALID;
1475   IRTemp nyu2 = IRTemp_INVALID;
1476   IRTemp retval = newTemp(Ity_I64);
1477
1478   vassert(!mode64);
1479
1480   for (i = 0; i < WORD; i++) {
1481      mask[i]  = newTemp(Ity_I32);
1482      shift[i] = 1 << i;
1483   }
1484   assign(mask[0], mkU32(0x55555555));
1485   assign(mask[1], mkU32(0x33333333));
1486   assign(mask[2], mkU32(0x0F0F0F0F));
1487   assign(mask[3], mkU32(0x00FF00FF));
1488   assign(mask[4], mkU32(0x0000FFFF));
1489   old = src1;
1490   for (i = 0; i < WORD; i++) {
1491      nyu1 = newTemp(Ity_I32);
1492      assign(nyu1,
1493             binop(Iop_Add32,
1494                   binop(Iop_And32,
1495                         mkexpr(old),
1496                         mkexpr(mask[i])),
1497                   binop(Iop_And32,
1498                         binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1499                         mkexpr(mask[i]))));
1500      old = nyu1;
1501   }
1502
1503   old = src2;
1504   for (i = 0; i < WORD; i++) {
1505      nyu2 = newTemp(Ity_I32);
1506      assign(nyu2,
1507             binop(Iop_Add32,
1508                   binop(Iop_And32,
1509                         mkexpr(old),
1510                         mkexpr(mask[i])),
1511                   binop(Iop_And32,
1512                         binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1513                         mkexpr(mask[i]))));
1514      old = nyu2;
1515   }
1516   assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2))));
1517   return retval;
1518}
1519
1520
1521// ROTL(src32/64, rot_amt5/6)
1522static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1523                                          IRExpr* rot_amt )
1524{
1525   IRExpr *mask, *rot;
1526   vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1527
1528   if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1529      // rot = (src << rot_amt) | (src >> (64-rot_amt))
1530      mask = binop(Iop_And8, rot_amt, mkU8(63));
1531      rot  = binop(Iop_Or64,
1532                binop(Iop_Shl64, src, mask),
1533                binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1534   } else {
1535      // rot = (src << rot_amt) | (src >> (32-rot_amt))
1536      mask = binop(Iop_And8, rot_amt, mkU8(31));
1537      rot  = binop(Iop_Or32,
1538                binop(Iop_Shl32, src, mask),
1539                binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
1540   }
1541   /* Note: the ITE not merely an optimisation; it's needed
1542      because otherwise the Shr is a shift by the word size when
1543      mask denotes zero.  For rotates by immediates, a lot of
1544      this junk gets folded out. */
1545   return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)),
1546                      /* non-zero rotate */ rot,
1547                      /*     zero rotate */ src);
1548}
1549
1550/* Standard effective address calc: (rA + rB) */
1551static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1552{
1553   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1554   vassert(rA < 32);
1555   vassert(rB < 32);
1556   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1557}
1558
1559/* Standard effective address calc: (rA + simm) */
1560static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1561{
1562   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1563   vassert(rA < 32);
1564   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
1565                mkSzExtendS16(ty, simm16));
1566}
1567
1568/* Standard effective address calc: (rA|0) */
1569static IRExpr* ea_rAor0 ( UInt rA )
1570{
1571   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1572   vassert(rA < 32);
1573   if (rA == 0) {
1574      return mkSzImm(ty, 0);
1575   } else {
1576      return getIReg(rA);
1577   }
1578}
1579
1580/* Standard effective address calc: (rA|0) + rB */
1581static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1582{
1583   vassert(rA < 32);
1584   vassert(rB < 32);
1585   return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1586}
1587
1588/* Standard effective address calc: (rA|0) + simm16 */
1589static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
1590{
1591   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1592   vassert(rA < 32);
1593   if (rA == 0) {
1594      return mkSzExtendS16(ty, simm16);
1595   } else {
1596      return ea_rA_simm( rA, simm16 );
1597   }
1598}
1599
1600
1601/* Align effective address */
1602static IRExpr* addr_align( IRExpr* addr, UChar align )
1603{
1604   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1605   Long mask;
1606   switch (align) {
1607   case 1:  return addr;                    // byte aligned
1608   case 2:  mask = ((Long)-1) << 1; break;  // half-word aligned
1609   case 4:  mask = ((Long)-1) << 2; break;  // word aligned
1610   case 16: mask = ((Long)-1) << 4; break;  // quad-word aligned
1611   default:
1612      vex_printf("addr_align: align = %u\n", align);
1613      vpanic("addr_align(ppc)");
1614   }
1615
1616   vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1617   return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
1618}
1619
1620
1621/* Exit the trace if ADDR (intended to be a guest memory address) is
1622   not ALIGN-aligned, generating a request for a SIGBUS followed by a
1623   restart of the current insn. */
1624static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1625{
1626   vassert(align == 4 || align == 8 || align == 16);
1627   if (mode64) {
1628      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1629      stmt(
1630         IRStmt_Exit(
1631            binop(Iop_CmpNE64,
1632                  binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1633                  mkU64(0)),
1634            Ijk_SigBUS,
1635            IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
1636         )
1637      );
1638   } else {
1639      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1640      stmt(
1641         IRStmt_Exit(
1642            binop(Iop_CmpNE32,
1643                  binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1644                  mkU32(0)),
1645            Ijk_SigBUS,
1646            IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
1647         )
1648      );
1649   }
1650}
1651
1652
1653/* Generate AbiHints which mark points at which the ELF or PowerOpen
1654   ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1655   N) becomes undefined.  That is at function calls and returns.  ELF
1656   ppc32 doesn't have this "feature" (how fortunate for it).  nia is
1657   the address of the next instruction to be executed.
1658*/
1659static void make_redzone_AbiHint ( VexAbiInfo* vbi,
1660                                   IRTemp nia, const HChar* who )
1661{
1662   Int szB = vbi->guest_stack_redzone_size;
1663   if (0) vex_printf("AbiHint: %s\n", who);
1664   vassert(szB >= 0);
1665   if (szB > 0) {
1666      if (mode64) {
1667         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1668         stmt( IRStmt_AbiHint(
1669                  binop(Iop_Sub64, getIReg(1), mkU64(szB)),
1670                  szB,
1671                  mkexpr(nia)
1672         ));
1673      } else {
1674         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1675         stmt( IRStmt_AbiHint(
1676                  binop(Iop_Sub32, getIReg(1), mkU32(szB)),
1677                  szB,
1678                  mkexpr(nia)
1679         ));
1680      }
1681   }
1682}
1683
1684
1685/*------------------------------------------------------------*/
1686/*--- Helpers for condition codes.                         ---*/
1687/*------------------------------------------------------------*/
1688
1689/* Condition register layout.
1690
1691   In the hardware, CR is laid out like this.  The leftmost end is the
1692   most significant bit in the register; however the IBM documentation
1693   numbers the bits backwards for some reason.
1694
1695   CR0      CR1    ..........   CR6       CR7
1696   0 .. 3   .......................  28 .. 31    (IBM bit numbering)
1697   31  28                             3    0     (normal bit numbering)
1698
1699   Each CR field is 4 bits:  [<,>,==,SO]
1700
1701   Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1702
1703   Indexing from BI to guest state:
1704
1705     let    n = BI / 4
1706          off = BI % 4
1707     this references CR n:
1708
1709        off==0   ->  guest_CRn_321 >> 3
1710        off==1   ->  guest_CRn_321 >> 2
1711        off==2   ->  guest_CRn_321 >> 1
1712        off==3   ->  guest_CRn_SO
1713
1714   Bear in mind the only significant bit in guest_CRn_SO is bit 0
1715   (normal notation) and in guest_CRn_321 the significant bits are
1716   3, 2 and 1 (normal notation).
1717*/
1718
1719static void putCR321 ( UInt cr, IRExpr* e )
1720{
1721   vassert(cr < 8);
1722   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1723   stmt( IRStmt_Put(guestCR321offset(cr), e) );
1724}
1725
1726static void putCR0 ( UInt cr, IRExpr* e )
1727{
1728   vassert(cr < 8);
1729   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1730   stmt( IRStmt_Put(guestCR0offset(cr), e) );
1731}
1732
1733static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1734{
1735   vassert(cr < 8);
1736   return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1737}
1738
1739static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1740{
1741   vassert(cr < 8);
1742   return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1743}
1744
1745/* Fetch the specified CR bit (as per IBM/hardware notation) and
1746   return it at the bottom of an I32; the top 31 bits are guaranteed
1747   to be zero. */
1748static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1749{
1750   UInt n   = bi / 4;
1751   UInt off = bi % 4;
1752   vassert(bi < 32);
1753   if (off == 3) {
1754      /* Fetch the SO bit for this CR field */
1755      /* Note: And32 is redundant paranoia iff guest state only has 0
1756         or 1 in that slot. */
1757      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1758   } else {
1759      /* Fetch the <, > or == bit for this CR field */
1760      return binop( Iop_And32,
1761                    binop( Iop_Shr32,
1762                           unop(Iop_8Uto32, getCR321(n)),
1763                           mkU8(toUChar(3-off)) ),
1764                    mkU32(1) );
1765   }
1766}
1767
1768/* Dually, write the least significant bit of BIT to the specified CR
1769   bit.  Indexing as per getCRbit. */
1770static void putCRbit ( UInt bi, IRExpr* bit )
1771{
1772   UInt    n, off;
1773   IRExpr* safe;
1774   vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
1775   safe = binop(Iop_And32, bit, mkU32(1));
1776   n   = bi / 4;
1777   off = bi % 4;
1778   vassert(bi < 32);
1779   if (off == 3) {
1780      /* This is the SO bit for this CR field */
1781      putCR0(n, unop(Iop_32to8, safe));
1782   } else {
1783      off = 3 - off;
1784      vassert(off == 1 || off == 2 || off == 3);
1785      putCR321(
1786         n,
1787         unop( Iop_32to8,
1788               binop( Iop_Or32,
1789                      /* old value with field masked out */
1790                      binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
1791                                       mkU32(~(1 << off))),
1792                      /* new value in the right place */
1793                      binop(Iop_Shl32, safe, mkU8(toUChar(off)))
1794               )
1795         )
1796      );
1797   }
1798}
1799
1800/* Fetch the specified CR bit (as per IBM/hardware notation) and
1801   return it somewhere in an I32; it does not matter where, but
1802   whichever bit it is, all other bits are guaranteed to be zero.  In
1803   other words, the I32-typed expression will be zero if the bit is
1804   zero and nonzero if the bit is 1.  Write into *where the index
1805   of where the bit will be. */
1806
1807static
1808IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
1809{
1810   UInt n   = bi / 4;
1811   UInt off = bi % 4;
1812   vassert(bi < 32);
1813   if (off == 3) {
1814      /* Fetch the SO bit for this CR field */
1815      /* Note: And32 is redundant paranoia iff guest state only has 0
1816         or 1 in that slot. */
1817      *where = 0;
1818      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1819   } else {
1820      /* Fetch the <, > or == bit for this CR field */
1821      *where = 3-off;
1822      return binop( Iop_And32,
1823                    unop(Iop_8Uto32, getCR321(n)),
1824                    mkU32(1 << (3-off)) );
1825   }
1826}
1827
1828/* Set the CR0 flags following an arithmetic operation.
1829   (Condition Register CR0 Field Definition, PPC32 p60)
1830*/
1831static IRExpr* getXER_SO ( void );
1832static void set_CR0 ( IRExpr* result )
1833{
1834   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
1835           typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
1836   if (mode64) {
1837      putCR321( 0, unop(Iop_64to8,
1838                        binop(Iop_CmpORD64S, result, mkU64(0))) );
1839   } else {
1840      putCR321( 0, unop(Iop_32to8,
1841                        binop(Iop_CmpORD32S, result, mkU32(0))) );
1842   }
1843   putCR0( 0, getXER_SO() );
1844}
1845
1846
1847/* Set the CR6 flags following an AltiVec compare operation.
1848 * NOTE: This also works for VSX single-precision compares.
1849 * */
1850static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
1851{
1852   /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
1853      all_ones  = (v[0] && v[1] && v[2] && v[3])
1854      all_zeros = ~(v[0] || v[1] || v[2] || v[3])
1855   */
1856   IRTemp v0 = newTemp(Ity_V128);
1857   IRTemp v1 = newTemp(Ity_V128);
1858   IRTemp v2 = newTemp(Ity_V128);
1859   IRTemp v3 = newTemp(Ity_V128);
1860   IRTemp rOnes  = newTemp(Ity_I8);
1861   IRTemp rZeros = newTemp(Ity_I8);
1862
1863   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
1864
1865   assign( v0, result );
1866   assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
1867   assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
1868   assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
1869
1870   assign( rZeros, unop(Iop_1Uto8,
1871       binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1872             unop(Iop_Not32,
1873                  unop(Iop_V128to32,
1874                       binop(Iop_OrV128,
1875                             binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
1876                             binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
1877                  ))) );
1878
1879   if (test_all_ones) {
1880      assign( rOnes, unop(Iop_1Uto8,
1881         binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1882               unop(Iop_V128to32,
1883                    binop(Iop_AndV128,
1884                          binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
1885                          binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
1886                    ))) );
1887      putCR321( 6, binop(Iop_Or8,
1888                         binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
1889                         binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
1890   } else {
1891      putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
1892   }
1893   putCR0( 6, mkU8(0) );
1894}
1895
1896
1897
1898/*------------------------------------------------------------*/
1899/*--- Helpers for XER flags.                               ---*/
1900/*------------------------------------------------------------*/
1901
1902static void putXER_SO ( IRExpr* e )
1903{
1904   IRExpr* so;
1905   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1906   so = binop(Iop_And8, e, mkU8(1));
1907   stmt( IRStmt_Put( OFFB_XER_SO, so ) );
1908}
1909
1910static void putXER_OV ( IRExpr* e )
1911{
1912   IRExpr* ov;
1913   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1914   ov = binop(Iop_And8, e, mkU8(1));
1915   stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
1916}
1917
1918static void putXER_CA ( IRExpr* e )
1919{
1920   IRExpr* ca;
1921   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1922   ca = binop(Iop_And8, e, mkU8(1));
1923   stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
1924}
1925
1926static void putXER_BC ( IRExpr* e )
1927{
1928   IRExpr* bc;
1929   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1930   bc = binop(Iop_And8, e, mkU8(0x7F));
1931   stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
1932}
1933
1934static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
1935{
1936   return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
1937}
1938
1939static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
1940{
1941   return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
1942}
1943
1944static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
1945{
1946   return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
1947}
1948
1949static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
1950{
1951   return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
1952}
1953
1954static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
1955{
1956   IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
1957   return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
1958}
1959
1960static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
1961{
1962   return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
1963}
1964
1965static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
1966{
1967   IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
1968   return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
1969}
1970
1971
1972/* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
1973   %XER.SO accordingly. */
1974
1975static void set_XER_OV_32( UInt op, IRExpr* res,
1976                           IRExpr* argL, IRExpr* argR )
1977{
1978   IRTemp  t64;
1979   IRExpr* xer_ov;
1980   vassert(op < PPCG_FLAG_OP_NUMBER);
1981   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
1982   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
1983   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
1984
1985#  define INT32_MIN 0x80000000
1986
1987#  define XOR2(_aa,_bb) \
1988      binop(Iop_Xor32,(_aa),(_bb))
1989
1990#  define XOR3(_cc,_dd,_ee) \
1991      binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
1992
1993#  define AND3(_ff,_gg,_hh) \
1994      binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
1995
1996#define NOT(_jj) \
1997      unop(Iop_Not32, (_jj))
1998
1999   switch (op) {
2000   case /* 0  */ PPCG_FLAG_OP_ADD:
2001   case /* 1  */ PPCG_FLAG_OP_ADDE:
2002      /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
2003      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2004      xer_ov
2005         = AND3( XOR3(argL,argR,mkU32(-1)),
2006                 XOR2(argL,res),
2007                 mkU32(INT32_MIN) );
2008      /* xer_ov can only be 0 or 1<<31 */
2009      xer_ov
2010         = binop(Iop_Shr32, xer_ov, mkU8(31) );
2011      break;
2012
2013   case /* 2  */ PPCG_FLAG_OP_DIVW:
2014      /* (argL == INT32_MIN && argR == -1) || argR == 0 */
2015      xer_ov
2016         = mkOR1(
2017              mkAND1(
2018                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
2019                 binop(Iop_CmpEQ32, argR, mkU32(-1))
2020              ),
2021              binop(Iop_CmpEQ32, argR, mkU32(0) )
2022           );
2023      xer_ov
2024         = unop(Iop_1Uto32, xer_ov);
2025      break;
2026
2027   case /* 3  */ PPCG_FLAG_OP_DIVWU:
2028      /* argR == 0 */
2029      xer_ov
2030         = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
2031      break;
2032
2033   case /* 4  */ PPCG_FLAG_OP_MULLW:
2034      /* OV true if result can't be represented in 32 bits
2035         i.e sHi != sign extension of sLo */
2036      t64 = newTemp(Ity_I64);
2037      assign( t64, binop(Iop_MullS32, argL, argR) );
2038      xer_ov
2039         = binop( Iop_CmpNE32,
2040                  unop(Iop_64HIto32, mkexpr(t64)),
2041                  binop( Iop_Sar32,
2042                         unop(Iop_64to32, mkexpr(t64)),
2043                         mkU8(31))
2044                  );
2045      xer_ov
2046         = unop(Iop_1Uto32, xer_ov);
2047      break;
2048
2049   case /* 5  */ PPCG_FLAG_OP_NEG:
2050      /* argL == INT32_MIN */
2051      xer_ov
2052         = unop( Iop_1Uto32,
2053                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
2054      break;
2055
2056   case /* 6  */ PPCG_FLAG_OP_SUBF:
2057   case /* 7  */ PPCG_FLAG_OP_SUBFC:
2058   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2059      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
2060      xer_ov
2061         = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
2062                 XOR2(NOT(argL),res),
2063                 mkU32(INT32_MIN) );
2064      /* xer_ov can only be 0 or 1<<31 */
2065      xer_ov
2066         = binop(Iop_Shr32, xer_ov, mkU8(31) );
2067      break;
2068
2069   case PPCG_FLAG_OP_DIVWEU:
2070      xer_ov
2071               = binop( Iop_Or32,
2072                        unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2073                        unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
2074      break;
2075
2076   case PPCG_FLAG_OP_DIVWE:
2077
2078      /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
2079       * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
2080       * an overflow is implied.
2081       */
2082      xer_ov = binop( Iop_Or32,
2083                      unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2084                      unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
2085                              mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
2086                                      binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
2087      break;
2088
2089
2090
2091   default:
2092      vex_printf("set_XER_OV: op = %u\n", op);
2093      vpanic("set_XER_OV(ppc)");
2094   }
2095
2096   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2097   putXER_OV( unop(Iop_32to8, xer_ov) );
2098
2099   /* Update the summary overflow */
2100   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2101
2102#  undef INT32_MIN
2103#  undef AND3
2104#  undef XOR3
2105#  undef XOR2
2106#  undef NOT
2107}
2108
2109static void set_XER_OV_64( UInt op, IRExpr* res,
2110                           IRExpr* argL, IRExpr* argR )
2111{
2112   IRExpr* xer_ov;
2113   vassert(op < PPCG_FLAG_OP_NUMBER);
2114   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
2115   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
2116   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
2117
2118#  define INT64_MIN 0x8000000000000000ULL
2119
2120#  define XOR2(_aa,_bb) \
2121      binop(Iop_Xor64,(_aa),(_bb))
2122
2123#  define XOR3(_cc,_dd,_ee) \
2124      binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
2125
2126#  define AND3(_ff,_gg,_hh) \
2127      binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
2128
2129#define NOT(_jj) \
2130      unop(Iop_Not64, (_jj))
2131
2132   switch (op) {
2133   case /* 0  */ PPCG_FLAG_OP_ADD:
2134   case /* 1  */ PPCG_FLAG_OP_ADDE:
2135      /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
2136      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2137      xer_ov
2138         = AND3( XOR3(argL,argR,mkU64(-1)),
2139                 XOR2(argL,res),
2140                 mkU64(INT64_MIN) );
2141      /* xer_ov can only be 0 or 1<<63 */
2142      xer_ov
2143         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2144      break;
2145
2146   case /* 2  */ PPCG_FLAG_OP_DIVW:
2147      /* (argL == INT64_MIN && argR == -1) || argR == 0 */
2148      xer_ov
2149         = mkOR1(
2150              mkAND1(
2151                 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
2152                 binop(Iop_CmpEQ64, argR, mkU64(-1))
2153              ),
2154              binop(Iop_CmpEQ64, argR, mkU64(0) )
2155           );
2156      break;
2157
2158   case /* 3  */ PPCG_FLAG_OP_DIVWU:
2159      /* argR == 0 */
2160      xer_ov
2161         = binop(Iop_CmpEQ64, argR, mkU64(0));
2162      break;
2163
2164   case /* 4  */ PPCG_FLAG_OP_MULLW: {
2165      /* OV true if result can't be represented in 64 bits
2166         i.e sHi != sign extension of sLo */
2167      xer_ov
2168         = binop( Iop_CmpNE32,
2169                  unop(Iop_64HIto32, res),
2170                  binop( Iop_Sar32,
2171                         unop(Iop_64to32, res),
2172                         mkU8(31))
2173                  );
2174      break;
2175   }
2176
2177   case /* 5  */ PPCG_FLAG_OP_NEG:
2178      /* argL == INT64_MIN */
2179      xer_ov
2180         = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
2181      break;
2182
2183   case /* 6  */ PPCG_FLAG_OP_SUBF:
2184   case /* 7  */ PPCG_FLAG_OP_SUBFC:
2185   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2186      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2187      xer_ov
2188         = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
2189                 XOR2(NOT(argL),res),
2190                 mkU64(INT64_MIN) );
2191      /* xer_ov can only be 0 or 1<<63 */
2192      xer_ov
2193         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2194      break;
2195
2196   case PPCG_FLAG_OP_DIVDE:
2197
2198      /* If argR == 0, we must set the OV bit.  But there's another condition
2199       * where we can get overflow set for divde . . . when the
2200       * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
2201       * both dividend and divisor are non-zero, it implies an overflow.
2202       */
2203      xer_ov
2204                  = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2205                           mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
2206                                   mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
2207                                           binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
2208      break;
2209
2210   case PPCG_FLAG_OP_DIVDEU:
2211     /* If argR == 0 or if argL >= argR, set OV. */
2212     xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2213                         binop( Iop_CmpLE64U, argR, argL ) );
2214     break;
2215
2216   case /* 18 */ PPCG_FLAG_OP_MULLD: {
2217      IRTemp  t128;
2218      /* OV true if result can't be represented in 64 bits
2219         i.e sHi != sign extension of sLo */
2220      t128 = newTemp(Ity_I128);
2221      assign( t128, binop(Iop_MullS64, argL, argR) );
2222      xer_ov
2223         = binop( Iop_CmpNE64,
2224                  unop(Iop_128HIto64, mkexpr(t128)),
2225                  binop( Iop_Sar64,
2226                         unop(Iop_128to64, mkexpr(t128)),
2227                         mkU8(63))
2228                  );
2229      break;
2230   }
2231
2232   default:
2233      vex_printf("set_XER_OV: op = %u\n", op);
2234      vpanic("set_XER_OV(ppc64)");
2235   }
2236
2237   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2238   putXER_OV( unop(Iop_1Uto8, xer_ov) );
2239
2240   /* Update the summary overflow */
2241   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2242
2243#  undef INT64_MIN
2244#  undef AND3
2245#  undef XOR3
2246#  undef XOR2
2247#  undef NOT
2248}
2249
2250static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
2251                         IRExpr* argL, IRExpr* argR )
2252{
2253   if (ty == Ity_I32)
2254      set_XER_OV_32( op, res, argL, argR );
2255   else
2256      set_XER_OV_64( op, res, argL, argR );
2257}
2258
2259
2260
2261/* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2262   value being OLDCA.  Set %XER.CA accordingly. */
2263
2264static void set_XER_CA_32 ( UInt op, IRExpr* res,
2265                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2266{
2267   IRExpr* xer_ca;
2268   vassert(op < PPCG_FLAG_OP_NUMBER);
2269   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
2270   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
2271   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
2272   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
2273
2274   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2275      seems reasonable given that it's always generated by
2276      getXER_CA32(), which masks it accordingly.  In any case it being
2277      0 or 1 is an invariant of the ppc guest state representation;
2278      if it has any other value, that invariant has been violated. */
2279
2280   switch (op) {
2281   case /* 0 */ PPCG_FLAG_OP_ADD:
2282      /* res <u argL */
2283      xer_ca
2284         = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
2285      break;
2286
2287   case /* 1 */ PPCG_FLAG_OP_ADDE:
2288      /* res <u argL || (old_ca==1 && res==argL) */
2289      xer_ca
2290         = mkOR1(
2291              binop(Iop_CmpLT32U, res, argL),
2292              mkAND1(
2293                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2294                 binop(Iop_CmpEQ32, res, argL)
2295              )
2296           );
2297      xer_ca
2298         = unop(Iop_1Uto32, xer_ca);
2299      break;
2300
2301   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2302      /* res <u argR || (old_ca==1 && res==argR) */
2303      xer_ca
2304         = mkOR1(
2305              binop(Iop_CmpLT32U, res, argR),
2306              mkAND1(
2307                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2308                 binop(Iop_CmpEQ32, res, argR)
2309              )
2310           );
2311      xer_ca
2312         = unop(Iop_1Uto32, xer_ca);
2313      break;
2314
2315   case /* 7 */ PPCG_FLAG_OP_SUBFC:
2316   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2317      /* res <=u argR */
2318      xer_ca
2319         = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
2320      break;
2321
2322   case /* 10 */ PPCG_FLAG_OP_SRAW:
2323      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2324         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2325         bit of argL. */
2326      /* This term valid for shift amount < 32 only */
2327      xer_ca
2328         = binop(
2329              Iop_And32,
2330              binop(Iop_Sar32, argL, mkU8(31)),
2331              binop( Iop_And32,
2332                     argL,
2333                     binop( Iop_Sub32,
2334                            binop(Iop_Shl32, mkU32(1),
2335                                             unop(Iop_32to8,argR)),
2336                            mkU32(1) )
2337                     )
2338              );
2339      xer_ca
2340         = IRExpr_ITE(
2341              /* shift amt > 31 ? */
2342              binop(Iop_CmpLT32U, mkU32(31), argR),
2343              /* yes -- get sign bit of argL */
2344              binop(Iop_Shr32, argL, mkU8(31)),
2345              /* no -- be like srawi */
2346              unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)))
2347           );
2348      break;
2349
2350   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2351      /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2352         0.  Since the shift amount is known to be in the range
2353         0 .. 31 inclusive the following seems viable:
2354         xer.ca == 1 iff the following is nonzero:
2355         (argL >>s 31)           -- either all 0s or all 1s
2356         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2357      xer_ca
2358         = binop(
2359              Iop_And32,
2360              binop(Iop_Sar32, argL, mkU8(31)),
2361              binop( Iop_And32,
2362                     argL,
2363                     binop( Iop_Sub32,
2364                            binop(Iop_Shl32, mkU32(1),
2365                                             unop(Iop_32to8,argR)),
2366                            mkU32(1) )
2367                     )
2368              );
2369      xer_ca
2370         = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2371      break;
2372
2373   default:
2374      vex_printf("set_XER_CA: op = %u\n", op);
2375      vpanic("set_XER_CA(ppc)");
2376   }
2377
2378   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2379   putXER_CA( unop(Iop_32to8, xer_ca) );
2380}
2381
2382static void set_XER_CA_64 ( UInt op, IRExpr* res,
2383                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2384{
2385   IRExpr* xer_ca;
2386   vassert(op < PPCG_FLAG_OP_NUMBER);
2387   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
2388   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
2389   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
2390   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
2391
2392   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2393      seems reasonable given that it's always generated by
2394      getXER_CA32(), which masks it accordingly.  In any case it being
2395      0 or 1 is an invariant of the ppc guest state representation;
2396      if it has any other value, that invariant has been violated. */
2397
2398   switch (op) {
2399   case /* 0 */ PPCG_FLAG_OP_ADD:
2400      /* res <u argL */
2401      xer_ca
2402         = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2403      break;
2404
2405   case /* 1 */ PPCG_FLAG_OP_ADDE:
2406      /* res <u argL || (old_ca==1 && res==argL) */
2407      xer_ca
2408         = mkOR1(
2409              binop(Iop_CmpLT64U, res, argL),
2410              mkAND1(
2411                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2412                 binop(Iop_CmpEQ64, res, argL)
2413                 )
2414              );
2415      xer_ca
2416         = unop(Iop_1Uto32, xer_ca);
2417      break;
2418
2419   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2420      /* res <u argR || (old_ca==1 && res==argR) */
2421      xer_ca
2422         = mkOR1(
2423              binop(Iop_CmpLT64U, res, argR),
2424              mkAND1(
2425                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2426                 binop(Iop_CmpEQ64, res, argR)
2427              )
2428           );
2429      xer_ca
2430         = unop(Iop_1Uto32, xer_ca);
2431      break;
2432
2433   case /* 7 */ PPCG_FLAG_OP_SUBFC:
2434   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2435      /* res <=u argR */
2436      xer_ca
2437         = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2438      break;
2439
2440
2441   case /* 10 */ PPCG_FLAG_OP_SRAW:
2442      /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2443         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2444         bit of argL. */
2445         /* This term valid for shift amount < 31 only */
2446
2447      xer_ca
2448         = binop(
2449              Iop_And64,
2450              binop(Iop_Sar64, argL, mkU8(31)),
2451              binop( Iop_And64,
2452                     argL,
2453                     binop( Iop_Sub64,
2454                            binop(Iop_Shl64, mkU64(1),
2455                                             unop(Iop_64to8,argR)),
2456                            mkU64(1) )
2457              )
2458           );
2459      xer_ca
2460         = IRExpr_ITE(
2461              /* shift amt > 31 ? */
2462              binop(Iop_CmpLT64U, mkU64(31), argR),
2463              /* yes -- get sign bit of argL */
2464              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2465              /* no -- be like srawi */
2466              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2467          );
2468      break;
2469
2470   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2471      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2472         Since the shift amount is known to be in the range 0 .. 31
2473         inclusive the following seems viable:
2474         xer.ca == 1 iff the following is nonzero:
2475         (argL >>s 31)           -- either all 0s or all 1s
2476         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2477
2478      xer_ca
2479         = binop(
2480              Iop_And64,
2481              binop(Iop_Sar64, argL, mkU8(31)),
2482              binop( Iop_And64,
2483                     argL,
2484                     binop( Iop_Sub64,
2485                            binop(Iop_Shl64, mkU64(1),
2486                                             unop(Iop_64to8,argR)),
2487                            mkU64(1) )
2488              )
2489           );
2490      xer_ca
2491         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2492      break;
2493
2494
2495   case /* 12 */ PPCG_FLAG_OP_SRAD:
2496      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2497         If it is <= 63, behave like SRADI; else XER.CA is the sign
2498         bit of argL. */
2499         /* This term valid for shift amount < 63 only */
2500
2501      xer_ca
2502         = binop(
2503              Iop_And64,
2504              binop(Iop_Sar64, argL, mkU8(63)),
2505              binop( Iop_And64,
2506                     argL,
2507                     binop( Iop_Sub64,
2508                            binop(Iop_Shl64, mkU64(1),
2509                                             unop(Iop_64to8,argR)),
2510                            mkU64(1) )
2511              )
2512           );
2513      xer_ca
2514         = IRExpr_ITE(
2515              /* shift amt > 63 ? */
2516              binop(Iop_CmpLT64U, mkU64(63), argR),
2517              /* yes -- get sign bit of argL */
2518              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2519              /* no -- be like sradi */
2520              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2521           );
2522      break;
2523
2524
2525   case /* 13 */ PPCG_FLAG_OP_SRADI:
2526      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2527         Since the shift amount is known to be in the range 0 .. 63
2528         inclusive, the following seems viable:
2529         xer.ca == 1 iff the following is nonzero:
2530         (argL >>s 63)           -- either all 0s or all 1s
2531         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2532
2533      xer_ca
2534         = binop(
2535              Iop_And64,
2536              binop(Iop_Sar64, argL, mkU8(63)),
2537              binop( Iop_And64,
2538                     argL,
2539                     binop( Iop_Sub64,
2540                            binop(Iop_Shl64, mkU64(1),
2541                                             unop(Iop_64to8,argR)),
2542                            mkU64(1) )
2543              )
2544           );
2545      xer_ca
2546         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2547      break;
2548
2549   default:
2550      vex_printf("set_XER_CA: op = %u\n", op);
2551      vpanic("set_XER_CA(ppc64)");
2552   }
2553
2554   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2555   putXER_CA( unop(Iop_32to8, xer_ca) );
2556}
2557
2558static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
2559                         IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2560{
2561   if (ty == Ity_I32)
2562      set_XER_CA_32( op, res, argL, argR, oldca );
2563   else
2564      set_XER_CA_64( op, res, argL, argR, oldca );
2565}
2566
2567
2568
2569/*------------------------------------------------------------*/
2570/*--- Read/write to guest-state                           --- */
2571/*------------------------------------------------------------*/
2572
2573static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
2574{
2575   IRType ty = mode64 ? Ity_I64 : Ity_I32;
2576   switch (reg) {
2577   case PPC_GST_SPRG3_RO:
2578      return IRExpr_Get( OFFB_SPRG3_RO, ty );
2579
2580   case PPC_GST_CIA:
2581      return IRExpr_Get( OFFB_CIA, ty );
2582
2583   case PPC_GST_LR:
2584      return IRExpr_Get( OFFB_LR, ty );
2585
2586   case PPC_GST_CTR:
2587      return IRExpr_Get( OFFB_CTR, ty );
2588
2589   case PPC_GST_VRSAVE:
2590      return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
2591
2592   case PPC_GST_VSCR:
2593      return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
2594                              mkU32(MASK_VSCR_VALID));
2595
2596   case PPC_GST_CR: {
2597      /* Synthesise the entire CR into a single word.  Expensive. */
2598#     define FIELD(_n)                                               \
2599         binop(Iop_Shl32,                                            \
2600               unop(Iop_8Uto32,                                      \
2601                    binop(Iop_Or8,                                   \
2602                          binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
2603                          binop(Iop_And8, getCR0(_n), mkU8(1))       \
2604                    )                                                \
2605               ),                                                    \
2606               mkU8(4 * (7-(_n)))                                    \
2607         )
2608      return binop(Iop_Or32,
2609                   binop(Iop_Or32,
2610                         binop(Iop_Or32, FIELD(0), FIELD(1)),
2611                         binop(Iop_Or32, FIELD(2), FIELD(3))
2612                         ),
2613                   binop(Iop_Or32,
2614                         binop(Iop_Or32, FIELD(4), FIELD(5)),
2615                         binop(Iop_Or32, FIELD(6), FIELD(7))
2616                         )
2617                   );
2618#     undef FIELD
2619   }
2620
2621   case PPC_GST_XER:
2622      return binop(Iop_Or32,
2623                   binop(Iop_Or32,
2624                         binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
2625                         binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
2626                   binop(Iop_Or32,
2627                         binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
2628                         getXER_BC32()));
2629
2630   case PPC_GST_TFHAR:
2631      return IRExpr_Get( OFFB_TFHAR, ty );
2632
2633   case PPC_GST_TEXASR:
2634      return IRExpr_Get( OFFB_TEXASR, ty );
2635
2636   case PPC_GST_TFIAR:
2637      return IRExpr_Get( OFFB_TFIAR, ty );
2638
2639   default:
2640      vex_printf("getGST(ppc): reg = %u", reg);
2641      vpanic("getGST(ppc)");
2642   }
2643}
2644
2645/* Get a masked word from the given reg */
2646static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
2647{
2648   IRTemp val = newTemp(Ity_I32);
2649   vassert( reg < PPC_GST_MAX );
2650
2651   switch (reg) {
2652
2653   case PPC_GST_FPSCR: {
2654      /* Vex-generated code expects the FPSCR to be set as follows:
2655         all exceptions masked, round-to-nearest.
2656         This corresponds to a FPSCR value of 0x0. */
2657
2658      /* In the lower 32 bits of FPSCR, we're only keeping track of
2659       * the binary floating point rounding mode, so if the mask isn't
2660       * asking for this, just return 0x0.
2661       */
2662      if (mask & MASK_FPSCR_RN) {
2663         assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) );
2664      } else {
2665         assign( val, mkU32(0x0) );
2666      }
2667      break;
2668   }
2669
2670   default:
2671      vex_printf("getGST_masked(ppc): reg = %u", reg);
2672      vpanic("getGST_masked(ppc)");
2673   }
2674
2675   if (mask != 0xFFFFFFFF) {
2676      return binop(Iop_And32, mkexpr(val), mkU32(mask));
2677   } else {
2678      return mkexpr(val);
2679   }
2680}
2681
2682/* Get a masked word from the given reg */
2683static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
2684   IRExpr * val;
2685   vassert( reg < PPC_GST_MAX );
2686
2687   switch (reg) {
2688
2689   case PPC_GST_FPSCR: {
2690      /* In the upper 32 bits of FPSCR, we're only keeping track
2691       * of the decimal floating point rounding mode, so if the mask
2692       * isn't asking for this, just return 0x0.
2693       */
2694      if (mask & MASK_FPSCR_DRN) {
2695         val = binop( Iop_And32,
2696                      unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
2697                      unop( Iop_64HIto32, mkU64( mask ) ) );
2698      } else {
2699         val = mkU32( 0x0ULL );
2700      }
2701      break;
2702   }
2703
2704   default:
2705      vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
2706      vpanic( "getGST_masked_upper(ppc)" );
2707   }
2708   return val;
2709}
2710
2711
2712/* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
2713   and return it at the bottom of an I32; the top 27 bits are
2714   guaranteed to be zero. */
2715static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
2716{
2717   UInt shft, mask;
2718
2719   vassert( fld < 8 );
2720   vassert( reg < PPC_GST_MAX );
2721
2722   shft = 4*(7-fld);
2723   mask = 0xF<<shft;
2724
2725   switch (reg) {
2726   case PPC_GST_XER:
2727      vassert(fld ==7);
2728      return binop(Iop_Or32,
2729                   binop(Iop_Or32,
2730                         binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
2731                         binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
2732                   binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
2733      break;
2734
2735   default:
2736      if (shft == 0)
2737         return getGST_masked( reg, mask );
2738      else
2739         return binop(Iop_Shr32,
2740                      getGST_masked( reg, mask ),
2741                      mkU8(toUChar( shft )));
2742   }
2743}
2744
2745static void putGST ( PPC_GST reg, IRExpr* src )
2746{
2747   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
2748   IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
2749   vassert( reg < PPC_GST_MAX );
2750   switch (reg) {
2751   case PPC_GST_IP_AT_SYSCALL:
2752      vassert( ty_src == ty );
2753      stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
2754      break;
2755   case PPC_GST_CIA:
2756      vassert( ty_src == ty );
2757      stmt( IRStmt_Put( OFFB_CIA, src ) );
2758      break;
2759   case PPC_GST_LR:
2760      vassert( ty_src == ty );
2761      stmt( IRStmt_Put( OFFB_LR, src ) );
2762      break;
2763   case PPC_GST_CTR:
2764      vassert( ty_src == ty );
2765      stmt( IRStmt_Put( OFFB_CTR, src ) );
2766      break;
2767   case PPC_GST_VRSAVE:
2768      vassert( ty_src == Ity_I32 );
2769      stmt( IRStmt_Put( OFFB_VRSAVE,src));
2770      break;
2771   case PPC_GST_VSCR:
2772      vassert( ty_src == Ity_I32 );
2773      stmt( IRStmt_Put( OFFB_VSCR,
2774                        binop(Iop_And32, src,
2775                              mkU32(MASK_VSCR_VALID)) ) );
2776      break;
2777   case PPC_GST_XER:
2778      vassert( ty_src == Ity_I32 );
2779      putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
2780      putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
2781      putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
2782      putXER_BC( unop(Iop_32to8, src) );
2783      break;
2784
2785   case PPC_GST_EMWARN:
2786      vassert( ty_src == Ity_I32 );
2787      stmt( IRStmt_Put( OFFB_EMNOTE,src) );
2788      break;
2789
2790   case PPC_GST_CMSTART:
2791      vassert( ty_src == ty );
2792      stmt( IRStmt_Put( OFFB_CMSTART, src) );
2793      break;
2794
2795   case PPC_GST_CMLEN:
2796      vassert( ty_src == ty );
2797      stmt( IRStmt_Put( OFFB_CMLEN, src) );
2798      break;
2799
2800   case PPC_GST_TEXASR:
2801      vassert( ty_src == Ity_I64 );
2802      stmt( IRStmt_Put( OFFB_TEXASR, src ) );
2803      break;
2804   case PPC_GST_TFIAR:
2805      vassert( ty_src == Ity_I64 );
2806      stmt( IRStmt_Put( OFFB_TFIAR, src ) );
2807      break;
2808   case PPC_GST_TFHAR:
2809      vassert( ty_src == Ity_I64 );
2810      stmt( IRStmt_Put( OFFB_TFHAR, src ) );
2811      break;
2812   default:
2813      vex_printf("putGST(ppc): reg = %u", reg);
2814      vpanic("putGST(ppc)");
2815   }
2816}
2817
2818/* Write masked src to the given reg */
2819static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
2820{
2821   IRType ty = mode64 ? Ity_I64 : Ity_I32;
2822   vassert( reg < PPC_GST_MAX );
2823   vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
2824
2825   switch (reg) {
2826   case PPC_GST_FPSCR: {
2827      /* Allow writes to either binary or decimal floating point
2828       * Rounding Mode
2829       */
2830      if (mask & MASK_FPSCR_RN) {
2831         stmt( IRStmt_Put( OFFB_FPROUND,
2832                           unop( Iop_32to8,
2833                                 binop( Iop_And32,
2834                                        unop( Iop_64to32, src ),
2835                                        mkU32( MASK_FPSCR_RN & mask ) ) ) ) );
2836      } else if (mask & MASK_FPSCR_DRN) {
2837         stmt( IRStmt_Put( OFFB_DFPROUND,
2838                           unop( Iop_32to8,
2839                                 binop( Iop_And32,
2840                                        unop( Iop_64HIto32, src ),
2841                                        mkU32( ( MASK_FPSCR_DRN & mask )
2842                                                 >> 32 ) ) ) ) );
2843      }
2844
2845      /* Give EmNote for attempted writes to:
2846         - Exception Controls
2847         - Non-IEEE Mode
2848      */
2849      if (mask & 0xFC) {  // Exception Control, Non-IEE mode
2850         VexEmNote ew = EmWarn_PPCexns;
2851
2852         /* If any of the src::exception_control bits are actually set,
2853            side-exit to the next insn, reporting the warning,
2854            so that Valgrind's dispatcher sees the warning. */
2855         putGST( PPC_GST_EMWARN, mkU32(ew) );
2856         stmt(
2857            IRStmt_Exit(
2858               binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
2859               Ijk_EmWarn,
2860               mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
2861      }
2862
2863      /* Ignore all other writes */
2864      break;
2865   }
2866
2867   default:
2868      vex_printf("putGST_masked(ppc): reg = %u", reg);
2869      vpanic("putGST_masked(ppc)");
2870   }
2871}
2872
2873/* Write the least significant nibble of src to the specified
2874   REG[FLD] (as per IBM/hardware notation). */
2875static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
2876{
2877   UInt shft;
2878   ULong mask;
2879
2880   vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
2881   vassert( fld < 16 );
2882   vassert( reg < PPC_GST_MAX );
2883
2884   if (fld < 8)
2885      shft = 4*(7-fld);
2886   else
2887      shft = 4*(15-fld);
2888   mask = 0xF;
2889   mask = mask << shft;
2890
2891   switch (reg) {
2892   case PPC_GST_CR:
2893      putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
2894      putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
2895      break;
2896
2897   default:
2898      {
2899         IRExpr * src64 = unop( Iop_32Uto64, src );
2900
2901         if (shft == 0) {
2902            putGST_masked( reg, src64, mask );
2903         } else {
2904            putGST_masked( reg,
2905                           binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
2906                           mask );
2907         }
2908      }
2909   }
2910}
2911
2912/*------------------------------------------------------------*/
2913/* Helpers for VSX instructions that do floating point
2914 * operations and need to determine if a src contains a
2915 * special FP value.
2916 *
2917 *------------------------------------------------------------*/
2918
2919#define NONZERO_FRAC_MASK 0x000fffffffffffffULL
2920#define FP_FRAC_PART(x) binop( Iop_And64, \
2921                               mkexpr( x ), \
2922                               mkU64( NONZERO_FRAC_MASK ) )
2923
2924// Returns exponent part of a single precision floating point as I32
2925static IRExpr * fp_exp_part_sp(IRTemp src)
2926{
2927   return binop( Iop_And32,
2928                 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
2929                 mkU32( 0xff ) );
2930}
2931
2932// Returns exponent part of floating point as I32
2933static IRExpr * fp_exp_part(IRTemp src, Bool sp)
2934{
2935   IRExpr * exp;
2936   if (sp)
2937      return fp_exp_part_sp(src);
2938
2939   if (!mode64)
2940      exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
2941                                                      mkexpr( src ) ),
2942                                     mkU8( 20 ) ), mkU32( 0x7ff ) );
2943   else
2944      exp = unop( Iop_64to32,
2945                  binop( Iop_And64,
2946                         binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
2947                         mkU64( 0x7ff ) ) );
2948   return exp;
2949}
2950
2951static IRExpr * is_Inf_sp(IRTemp src)
2952{
2953   IRTemp frac_part = newTemp(Ity_I32);
2954   IRExpr * Inf_exp;
2955
2956   assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
2957   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
2958   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
2959}
2960
2961
2962// Infinity: exp = 7ff and fraction is zero; s = 0/1
2963static IRExpr * is_Inf(IRTemp src, Bool sp)
2964{
2965   IRExpr * Inf_exp, * hi32, * low32;
2966   IRTemp frac_part;
2967
2968   if (sp)
2969      return is_Inf_sp(src);
2970
2971   frac_part = newTemp(Ity_I64);
2972   assign( frac_part, FP_FRAC_PART(src) );
2973   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
2974   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
2975   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
2976   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
2977                                  mkU32( 0 ) ) );
2978}
2979
2980static IRExpr * is_Zero_sp(IRTemp src)
2981{
2982   IRTemp sign_less_part = newTemp(Ity_I32);
2983   assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
2984   return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
2985}
2986
2987// Zero: exp is zero and fraction is zero; s = 0/1
2988static IRExpr * is_Zero(IRTemp src, Bool sp)
2989{
2990   IRExpr * hi32, * low32;
2991   IRTemp sign_less_part;
2992   if (sp)
2993      return is_Zero_sp(src);
2994
2995   sign_less_part = newTemp(Ity_I64);
2996
2997   assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
2998   hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
2999   low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
3000   return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
3001                              mkU32( 0 ) );
3002}
3003
3004/*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
3005 *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
3006 *  This function returns an IRExpr value of '1' for any type of NaN.
3007 */
3008static IRExpr * is_NaN(IRTemp src)
3009{
3010   IRExpr * NaN_exp, * hi32, * low32;
3011   IRTemp frac_part = newTemp(Ity_I64);
3012
3013   assign( frac_part, FP_FRAC_PART(src) );
3014   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
3015   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
3016   NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
3017                    mkU32( 0x7ff ) );
3018
3019   return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
3020                                               mkU32( 0 ) ) );
3021}
3022
3023/* This function returns an IRExpr value of '1' for any type of NaN.
3024 * The passed 'src' argument is assumed to be Ity_I32.
3025 */
3026static IRExpr * is_NaN_32(IRTemp src)
3027{
3028#define NONZERO_FRAC_MASK32 0x007fffffULL
3029#define FP_FRAC_PART32(x) binop( Iop_And32, \
3030                                 mkexpr( x ), \
3031                                 mkU32( NONZERO_FRAC_MASK32 ) )
3032
3033   IRExpr * frac_part = FP_FRAC_PART32(src);
3034   IRExpr * exp_part = binop( Iop_And32,
3035                              binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
3036                              mkU32( 0x0ff ) );
3037   IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
3038
3039   return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
3040}
3041
3042/* This function takes an Ity_I32 input argument interpreted
3043 * as a single-precision floating point value. If src is a
3044 * SNaN, it is changed to a QNaN and returned; otherwise,
3045 * the original value is returned.
3046 */
3047static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src)
3048{
3049#define SNAN_MASK32 0x00400000
3050   IRTemp tmp = newTemp(Ity_I32);
3051   IRTemp mask = newTemp(Ity_I32);
3052   IRTemp is_SNAN = newTemp(Ity_I1);
3053
3054   vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 );
3055   assign(tmp, src);
3056
3057   /* check if input is SNaN, if it is convert to QNaN */
3058   assign( is_SNAN,
3059           mkAND1( is_NaN_32( tmp ),
3060                   binop( Iop_CmpEQ32,
3061                          binop( Iop_And32, mkexpr( tmp ),
3062                                 mkU32( SNAN_MASK32 ) ),
3063                          mkU32( 0 ) ) ) );
3064   /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
3065   assign ( mask, binop( Iop_And32,
3066                         unop( Iop_1Sto32, mkexpr( is_SNAN ) ),
3067                         mkU32( SNAN_MASK32 ) ) );
3068   return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) );
3069}
3070
3071
3072/* This helper function performs the negation part of operations of the form:
3073 *    "Negate Multiply-<op>"
3074 *  where "<op>" is either "Add" or "Sub".
3075 *
3076 * This function takes one argument -- the floating point intermediate result (converted to
3077 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
3078 * the operation described above.
3079 */
3080static IRTemp getNegatedResult(IRTemp intermediateResult)
3081{
3082   ULong signbit_mask = 0x8000000000000000ULL;
3083   IRTemp signbit_32 = newTemp(Ity_I32);
3084   IRTemp resultantSignbit = newTemp(Ity_I1);
3085   IRTemp negatedResult = newTemp(Ity_I64);
3086   assign( signbit_32, binop( Iop_Shr32,
3087                          unop( Iop_64HIto32,
3088                                 binop( Iop_And64, mkexpr( intermediateResult ),
3089                                        mkU64( signbit_mask ) ) ),
3090                                 mkU8( 31 ) ) );
3091   /* We negate the signbit if and only if the intermediate result from the
3092    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
3093    */
3094   assign( resultantSignbit,
3095        unop( Iop_Not1,
3096              binop( Iop_CmpEQ32,
3097                     binop( Iop_Xor32,
3098                            mkexpr( signbit_32 ),
3099                            unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
3100                     mkU32( 1 ) ) ) );
3101
3102   assign( negatedResult,
3103        binop( Iop_Or64,
3104               binop( Iop_And64,
3105                      mkexpr( intermediateResult ),
3106                      mkU64( ~signbit_mask ) ),
3107               binop( Iop_32HLto64,
3108                      binop( Iop_Shl32,
3109                             unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
3110                             mkU8( 31 ) ),
3111                      mkU32( 0 ) ) ) );
3112
3113   return negatedResult;
3114}
3115
3116/* This helper function performs the negation part of operations of the form:
3117 *    "Negate Multiply-<op>"
3118 *  where "<op>" is either "Add" or "Sub".
3119 *
3120 * This function takes one argument -- the floating point intermediate result (converted to
3121 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
3122 * the operation described above.
3123 */
3124static IRTemp getNegatedResult_32(IRTemp intermediateResult)
3125{
3126   UInt signbit_mask = 0x80000000;
3127   IRTemp signbit_32 = newTemp(Ity_I32);
3128   IRTemp resultantSignbit = newTemp(Ity_I1);
3129   IRTemp negatedResult = newTemp(Ity_I32);
3130   assign( signbit_32, binop( Iop_Shr32,
3131                                 binop( Iop_And32, mkexpr( intermediateResult ),
3132                                        mkU32( signbit_mask ) ),
3133                                 mkU8( 31 ) ) );
3134   /* We negate the signbit if and only if the intermediate result from the
3135    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
3136    */
3137   assign( resultantSignbit,
3138        unop( Iop_Not1,
3139              binop( Iop_CmpEQ32,
3140                     binop( Iop_Xor32,
3141                            mkexpr( signbit_32 ),
3142                            unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
3143                     mkU32( 1 ) ) ) );
3144
3145   assign( negatedResult,
3146           binop( Iop_Or32,
3147                  binop( Iop_And32,
3148                         mkexpr( intermediateResult ),
3149                         mkU32( ~signbit_mask ) ),
3150                  binop( Iop_Shl32,
3151                         unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
3152                         mkU8( 31 ) ) ) );
3153
3154   return negatedResult;
3155}
3156
3157/*------------------------------------------------------------*/
3158/* Transactional memory helpers
3159 *
3160 *------------------------------------------------------------*/
3161
3162static ULong generate_TMreason( UInt failure_code,
3163                                             UInt persistant,
3164                                             UInt nest_overflow,
3165                                             UInt tm_exact )
3166{
3167   ULong tm_err_code =
3168     ( (ULong) 0) << (63-6)   /* Failure code */
3169     | ( (ULong) persistant) << (63-7)     /* Failure persistant */
3170     | ( (ULong) 0) << (63-8)   /* Disallowed */
3171     | ( (ULong) nest_overflow) << (63-9)   /* Nesting Overflow */
3172     | ( (ULong) 0) << (63-10)  /* Footprint Overflow */
3173     | ( (ULong) 0) << (63-11)  /* Self-Induced Conflict */
3174     | ( (ULong) 0) << (63-12)  /* Non-Transactional Conflict */
3175     | ( (ULong) 0) << (63-13)  /* Transactional Conflict */
3176     | ( (ULong) 0) << (63-14)  /* Translation Invalidation Conflict */
3177     | ( (ULong) 0) << (63-15)  /* Implementation-specific */
3178     | ( (ULong) 0) << (63-16)  /* Instruction Fetch Conflict */
3179     | ( (ULong) 0) << (63-30)  /* Reserved */
3180     | ( (ULong) 0) << (63-31)  /* Abort */
3181     | ( (ULong) 0) << (63-32)  /* Suspend */
3182     | ( (ULong) 0) << (63-33)  /* Reserved */
3183     | ( (ULong) 0) << (63-35)  /* Privilege */
3184     | ( (ULong) 0) << (63-36)  /* Failure Summary */
3185     | ( (ULong) tm_exact) << (63-37)  /* TFIAR Exact */
3186     | ( (ULong) 0) << (63-38)  /* ROT */
3187     | ( (ULong) 0) << (63-51)  /* Reserved */
3188     | ( (ULong) 0) << (63-63);  /* Transaction Level */
3189
3190     return tm_err_code;
3191}
3192
3193static void storeTMfailure( Addr64 err_address, ULong tm_reason,
3194                            Addr64 handler_address )
3195{
3196   putGST( PPC_GST_TFIAR,  mkU64( err_address ) );
3197   putGST( PPC_GST_TEXASR, mkU64( tm_reason ) );
3198   putGST( PPC_GST_TFHAR,  mkU64( handler_address ) );
3199}
3200
3201/*------------------------------------------------------------*/
3202/*--- Integer Instruction Translation                     --- */
3203/*------------------------------------------------------------*/
3204
3205/*
3206  Integer Arithmetic Instructions
3207*/
3208static Bool dis_int_arith ( UInt theInstr )
3209{
3210   /* D-Form, XO-Form */
3211   UChar opc1    = ifieldOPC(theInstr);
3212   UChar rD_addr = ifieldRegDS(theInstr);
3213   UChar rA_addr = ifieldRegA(theInstr);
3214   UInt  uimm16  = ifieldUIMM16(theInstr);
3215   UChar rB_addr = ifieldRegB(theInstr);
3216   UChar flag_OE = ifieldBIT10(theInstr);
3217   UInt  opc2    = ifieldOPClo9(theInstr);
3218   UChar flag_rC = ifieldBIT0(theInstr);
3219
3220   Long   simm16 = extend_s_16to64(uimm16);
3221   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3222   IRTemp rA     = newTemp(ty);
3223   IRTemp rB     = newTemp(ty);
3224   IRTemp rD     = newTemp(ty);
3225
3226   Bool do_rc = False;
3227
3228   assign( rA, getIReg(rA_addr) );
3229   assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
3230
3231   switch (opc1) {
3232   /* D-Form */
3233   case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
3234      DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3235      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3236                         mkSzExtendS16(ty, uimm16) ) );
3237      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3238                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3239                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3240      break;
3241
3242   case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
3243      DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3244      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3245                         mkSzExtendS16(ty, uimm16) ) );
3246      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3247                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3248                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3249      do_rc = True;  // Always record to CR
3250      flag_rC = 1;
3251      break;
3252
3253   case 0x0E: // addi   (Add Immediate, PPC32 p350)
3254      // li rD,val   == addi rD,0,val
3255      // la disp(rA) == addi rD,rA,disp
3256      if ( rA_addr == 0 ) {
3257         DIP("li r%u,%d\n", rD_addr, (Int)simm16);
3258         assign( rD, mkSzExtendS16(ty, uimm16) );
3259      } else {
3260         DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3261         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3262                            mkSzExtendS16(ty, uimm16) ) );
3263      }
3264      break;
3265
3266   case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
3267      // lis rD,val == addis rD,0,val
3268      if ( rA_addr == 0 ) {
3269         DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
3270         assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
3271      } else {
3272         DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
3273         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3274                            mkSzExtendS32(ty, uimm16 << 16) ) );
3275      }
3276      break;
3277
3278   case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
3279      DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3280      if (mode64)
3281         assign( rD, unop(Iop_128to64,
3282                          binop(Iop_MullS64, mkexpr(rA),
3283                                mkSzExtendS16(ty, uimm16))) );
3284      else
3285         assign( rD, unop(Iop_64to32,
3286                          binop(Iop_MullS32, mkexpr(rA),
3287                                mkSzExtendS16(ty, uimm16))) );
3288      break;
3289
3290   case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
3291      DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3292      // rD = simm16 - rA
3293      assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3294                         mkSzExtendS16(ty, uimm16),
3295                         mkexpr(rA)) );
3296      set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
3297                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3298                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3299      break;
3300
3301   /* XO-Form */
3302   case 0x1F:
3303      do_rc = True;    // All below record to CR
3304
3305      switch (opc2) {
3306      case 0x10A: // add  (Add, PPC32 p347)
3307         DIP("add%s%s r%u,r%u,r%u\n",
3308             flag_OE ? "o" : "", flag_rC ? ".":"",
3309             rD_addr, rA_addr, rB_addr);
3310         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3311                            mkexpr(rA), mkexpr(rB) ) );
3312         if (flag_OE) {
3313            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
3314                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3315         }
3316         break;
3317
3318      case 0x00A: // addc      (Add Carrying, PPC32 p348)
3319         DIP("addc%s%s r%u,r%u,r%u\n",
3320             flag_OE ? "o" : "", flag_rC ? ".":"",
3321             rD_addr, rA_addr, rB_addr);
3322         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3323                            mkexpr(rA), mkexpr(rB)) );
3324         set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3325                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3326                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3327         if (flag_OE) {
3328            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
3329                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3330         }
3331         break;
3332
3333      case 0x08A: { // adde      (Add Extended, PPC32 p349)
3334         IRTemp old_xer_ca = newTemp(ty);
3335         DIP("adde%s%s r%u,r%u,r%u\n",
3336             flag_OE ? "o" : "", flag_rC ? ".":"",
3337             rD_addr, rA_addr, rB_addr);
3338         // rD = rA + rB + XER[CA]
3339         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3340         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3341                            binop( mkSzOp(ty, Iop_Add8),
3342                                   mkexpr(rB), mkexpr(old_xer_ca))) );
3343         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3344                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3345                     mkexpr(old_xer_ca) );
3346         if (flag_OE) {
3347            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3348                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3349         }
3350         break;
3351      }
3352
3353      case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
3354         IRTemp old_xer_ca = newTemp(ty);
3355         IRExpr *min_one;
3356         if (rB_addr != 0) {
3357            vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
3358            return False;
3359         }
3360         DIP("addme%s%s r%u,r%u,r%u\n",
3361             flag_OE ? "o" : "", flag_rC ? ".":"",
3362             rD_addr, rA_addr, rB_addr);
3363         // rD = rA + (-1) + XER[CA]
3364         // => Just another form of adde
3365         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3366         min_one = mkSzImm(ty, (Long)-1);
3367         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3368                            binop( mkSzOp(ty, Iop_Add8),
3369                                   min_one, mkexpr(old_xer_ca)) ));
3370         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3371                     mkexpr(rD), mkexpr(rA), min_one,
3372                     mkexpr(old_xer_ca) );
3373         if (flag_OE) {
3374            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3375                        mkexpr(rD), mkexpr(rA), min_one );
3376         }
3377         break;
3378      }
3379
3380      case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
3381         IRTemp old_xer_ca = newTemp(ty);
3382         if (rB_addr != 0) {
3383            vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
3384            return False;
3385         }
3386         DIP("addze%s%s r%u,r%u,r%u\n",
3387             flag_OE ? "o" : "", flag_rC ? ".":"",
3388             rD_addr, rA_addr, rB_addr);
3389         // rD = rA + (0) + XER[CA]
3390         // => Just another form of adde
3391         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3392         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3393                            mkexpr(rA), mkexpr(old_xer_ca)) );
3394         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3395                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3396                     mkexpr(old_xer_ca) );
3397         if (flag_OE) {
3398            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3399                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3400         }
3401         break;
3402      }
3403
3404      case 0x1EB: // divw       (Divide Word, PPC32 p388)
3405         DIP("divw%s%s r%u,r%u,r%u\n",
3406             flag_OE ? "o" : "", flag_rC ? ".":"",
3407             rD_addr, rA_addr, rB_addr);
3408         if (mode64) {
3409            /* Note:
3410               XER settings are mode independent, and reflect the
3411               overflow of the low-order 32bit result
3412               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3413            */
3414            /* rD[hi32] are undefined: setting them to sign of lo32
3415                - makes set_CR0 happy */
3416            IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
3417            IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
3418            assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
3419                                                         divisor) ) );
3420            if (flag_OE) {
3421               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3422                           mkexpr(rD), dividend, divisor );
3423            }
3424         } else {
3425            assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
3426            if (flag_OE) {
3427               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3428                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3429            }
3430         }
3431         /* Note:
3432            if (0x8000_0000 / -1) or (x / 0)
3433            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3434            => But _no_ exception raised. */
3435         break;
3436
3437      case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
3438         DIP("divwu%s%s r%u,r%u,r%u\n",
3439             flag_OE ? "o" : "", flag_rC ? ".":"",
3440             rD_addr, rA_addr, rB_addr);
3441         if (mode64) {
3442            /* Note:
3443               XER settings are mode independent, and reflect the
3444               overflow of the low-order 32bit result
3445               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3446            */
3447            IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
3448            IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
3449            assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
3450                                                         divisor) ) );
3451            if (flag_OE) {
3452               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3453                           mkexpr(rD), dividend, divisor );
3454            }
3455         } else {
3456            assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
3457            if (flag_OE) {
3458               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3459                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3460            }
3461         }
3462         /* Note: ditto comment divw, for (x / 0) */
3463         break;
3464
3465      case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
3466         if (flag_OE != 0) {
3467            vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
3468            return False;
3469         }
3470         DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3471             rD_addr, rA_addr, rB_addr);
3472         if (mode64) {
3473            /* rD[hi32] are undefined: setting them to sign of lo32
3474                - makes set_CR0 happy */
3475            assign( rD, binop(Iop_Sar64,
3476                           binop(Iop_Mul64,
3477                                 mk64lo32Sto64( mkexpr(rA) ),
3478                                 mk64lo32Sto64( mkexpr(rB) )),
3479                              mkU8(32)) );
3480         } else {
3481            assign( rD, unop(Iop_64HIto32,
3482                             binop(Iop_MullS32,
3483                                   mkexpr(rA), mkexpr(rB))) );
3484         }
3485         break;
3486
3487      case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
3488         if (flag_OE != 0) {
3489            vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
3490            return False;
3491         }
3492         DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3493             rD_addr, rA_addr, rB_addr);
3494         if (mode64) {
3495            /* rD[hi32] are undefined: setting them to sign of lo32
3496                - makes set_CR0 happy */
3497            assign( rD, binop(Iop_Sar64,
3498                           binop(Iop_Mul64,
3499                                 mk64lo32Uto64( mkexpr(rA) ),
3500                                 mk64lo32Uto64( mkexpr(rB) ) ),
3501                              mkU8(32)) );
3502         } else {
3503            assign( rD, unop(Iop_64HIto32,
3504                             binop(Iop_MullU32,
3505                                   mkexpr(rA), mkexpr(rB))) );
3506         }
3507         break;
3508
3509      case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
3510         DIP("mullw%s%s r%u,r%u,r%u\n",
3511             flag_OE ? "o" : "", flag_rC ? ".":"",
3512             rD_addr, rA_addr, rB_addr);
3513         if (mode64) {
3514            /* rD[hi32] are undefined: setting them to sign of lo32
3515                - set_XER_OV() and set_CR0() depend on this */
3516            IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
3517            IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
3518            assign( rD, binop(Iop_MullS32, a, b) );
3519            if (flag_OE) {
3520               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3521                           mkexpr(rD),
3522                           unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
3523            }
3524         } else {
3525            assign( rD, unop(Iop_64to32,
3526                             binop(Iop_MullU32,
3527                                   mkexpr(rA), mkexpr(rB))) );
3528            if (flag_OE) {
3529               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3530                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3531            }
3532         }
3533         break;
3534
3535      case 0x068: // neg        (Negate, PPC32 p493)
3536         if (rB_addr != 0) {
3537            vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
3538            return False;
3539         }
3540         DIP("neg%s%s r%u,r%u\n",
3541             flag_OE ? "o" : "", flag_rC ? ".":"",
3542             rD_addr, rA_addr);
3543         // rD = (~rA) + 1
3544         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3545                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
3546                            mkSzImm(ty, 1)) );
3547         if (flag_OE) {
3548            set_XER_OV( ty, PPCG_FLAG_OP_NEG,
3549                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3550         }
3551         break;
3552
3553      case 0x028: // subf       (Subtract From, PPC32 p537)
3554         DIP("subf%s%s r%u,r%u,r%u\n",
3555             flag_OE ? "o" : "", flag_rC ? ".":"",
3556             rD_addr, rA_addr, rB_addr);
3557         // rD = rB - rA
3558         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3559                            mkexpr(rB), mkexpr(rA)) );
3560         if (flag_OE) {
3561            set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
3562                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3563         }
3564         break;
3565
3566      case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
3567         DIP("subfc%s%s r%u,r%u,r%u\n",
3568             flag_OE ? "o" : "", flag_rC ? ".":"",
3569             rD_addr, rA_addr, rB_addr);
3570         // rD = rB - rA
3571         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3572                            mkexpr(rB), mkexpr(rA)) );
3573         set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
3574                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3575                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3576         if (flag_OE) {
3577            set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
3578                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3579         }
3580         break;
3581
3582      case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
3583         IRTemp old_xer_ca = newTemp(ty);
3584         DIP("subfe%s%s r%u,r%u,r%u\n",
3585             flag_OE ? "o" : "", flag_rC ? ".":"",
3586             rD_addr, rA_addr, rB_addr);
3587         // rD = (log not)rA + rB + XER[CA]
3588         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3589         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3590                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3591                            binop( mkSzOp(ty, Iop_Add8),
3592                                   mkexpr(rB), mkexpr(old_xer_ca))) );
3593         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3594                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3595                     mkexpr(old_xer_ca) );
3596         if (flag_OE) {
3597            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3598                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3599         }
3600         break;
3601      }
3602
3603      case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
3604         IRTemp old_xer_ca = newTemp(ty);
3605         IRExpr *min_one;
3606         if (rB_addr != 0) {
3607            vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
3608            return False;
3609         }
3610         DIP("subfme%s%s r%u,r%u\n",
3611             flag_OE ? "o" : "", flag_rC ? ".":"",
3612             rD_addr, rA_addr);
3613         // rD = (log not)rA + (-1) + XER[CA]
3614         // => Just another form of subfe
3615         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3616         min_one = mkSzImm(ty, (Long)-1);
3617         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3618                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3619                            binop( mkSzOp(ty, Iop_Add8),
3620                                   min_one, mkexpr(old_xer_ca))) );
3621         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3622                     mkexpr(rD), mkexpr(rA), min_one,
3623                     mkexpr(old_xer_ca) );
3624         if (flag_OE) {
3625            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3626                        mkexpr(rD), mkexpr(rA), min_one );
3627         }
3628         break;
3629      }
3630
3631      case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
3632         IRTemp old_xer_ca = newTemp(ty);
3633         if (rB_addr != 0) {
3634            vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
3635            return False;
3636         }
3637         DIP("subfze%s%s r%u,r%u\n",
3638             flag_OE ? "o" : "", flag_rC ? ".":"",
3639             rD_addr, rA_addr);
3640         // rD = (log not)rA + (0) + XER[CA]
3641         // => Just another form of subfe
3642         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3643         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3644                           unop( mkSzOp(ty, Iop_Not8),
3645                                 mkexpr(rA)), mkexpr(old_xer_ca)) );
3646         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3647                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3648                     mkexpr(old_xer_ca) );
3649         if (flag_OE) {
3650            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3651                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3652         }
3653         break;
3654      }
3655
3656
3657      /* 64bit Arithmetic */
3658      case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
3659         if (flag_OE != 0) {
3660            vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
3661            return False;
3662         }
3663         DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3664             rD_addr, rA_addr, rB_addr);
3665         assign( rD, unop(Iop_128HIto64,
3666                          binop(Iop_MullS64,
3667                                mkexpr(rA), mkexpr(rB))) );
3668
3669         break;
3670
3671      case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
3672         if (flag_OE != 0) {
3673            vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
3674            return False;
3675         }
3676         DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3677             rD_addr, rA_addr, rB_addr);
3678         assign( rD, unop(Iop_128HIto64,
3679                          binop(Iop_MullU64,
3680                                mkexpr(rA), mkexpr(rB))) );
3681         break;
3682
3683      case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
3684         DIP("mulld%s%s r%u,r%u,r%u\n",
3685             flag_OE ? "o" : "", flag_rC ? ".":"",
3686             rD_addr, rA_addr, rB_addr);
3687         assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
3688         if (flag_OE) {
3689            set_XER_OV( ty, PPCG_FLAG_OP_MULLD,
3690                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3691         }
3692         break;
3693
3694      case 0x1E9: // divd (Divide DWord, PPC64 p419)
3695         DIP("divd%s%s r%u,r%u,r%u\n",
3696             flag_OE ? "o" : "", flag_rC ? ".":"",
3697             rD_addr, rA_addr, rB_addr);
3698         assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
3699         if (flag_OE) {
3700            set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3701                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3702         }
3703         break;
3704         /* Note:
3705            if (0x8000_0000_0000_0000 / -1) or (x / 0)
3706            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3707            => But _no_ exception raised. */
3708
3709      case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
3710         DIP("divdu%s%s r%u,r%u,r%u\n",
3711             flag_OE ? "o" : "", flag_rC ? ".":"",
3712             rD_addr, rA_addr, rB_addr);
3713         assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
3714         if (flag_OE) {
3715            set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3716                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3717         }
3718         break;
3719         /* Note: ditto comment divd, for (x / 0) */
3720
3721      case 0x18B: // divweu (Divide Word Extended Unsigned)
3722      {
3723        /*
3724         *  If (RA) >= (RB), or if an attempt is made to perform the division
3725         *         <anything> / 0
3726         * then the contents of register RD are undefined as are (if Rc=1) the contents of
3727         * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
3728         * to 1.
3729         */
3730         IRTemp res = newTemp(Ity_I32);
3731         IRExpr * dividend, * divisor;
3732         DIP("divweu%s%s r%u,r%u,r%u\n",
3733             flag_OE ? "o" : "", flag_rC ? ".":"",
3734                                         rD_addr, rA_addr, rB_addr);
3735         if (mode64) {
3736            dividend = unop( Iop_64to32, mkexpr( rA ) );
3737            divisor = unop( Iop_64to32, mkexpr( rB ) );
3738            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
3739            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
3740         } else {
3741            dividend = mkexpr( rA );
3742            divisor =  mkexpr( rB );
3743            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
3744            assign( rD, mkexpr( res) );
3745         }
3746
3747         if (flag_OE) {
3748            set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
3749                           mkexpr(res), dividend, divisor );
3750         }
3751         break;
3752      }
3753
3754      case 0x1AB: // divwe (Divide Word Extended)
3755      {
3756         /*
3757          * If the quotient cannot be represented in 32 bits, or if an
3758          * attempt is made to perform the division
3759          *      <anything> / 0
3760          * then the contents of register RD are undefined as are (if
3761          * Rc=1) the contents of the LT, GT, and EQ bits of CR
3762          * Field 0. In these cases, if OE=1 then OV is set to 1.
3763          */
3764
3765         IRTemp res = newTemp(Ity_I32);
3766         IRExpr * dividend, * divisor;
3767         DIP("divwe%s%s r%u,r%u,r%u\n",
3768             flag_OE ? "o" : "", flag_rC ? ".":"",
3769                                         rD_addr, rA_addr, rB_addr);
3770         if (mode64) {
3771            dividend = unop( Iop_64to32, mkexpr( rA ) );
3772            divisor = unop( Iop_64to32, mkexpr( rB ) );
3773            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
3774            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
3775         } else {
3776            dividend = mkexpr( rA );
3777            divisor =  mkexpr( rB );
3778            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
3779            assign( rD, mkexpr( res) );
3780         }
3781
3782         if (flag_OE) {
3783            set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
3784                           mkexpr(res), dividend, divisor );
3785         }
3786         break;
3787      }
3788
3789
3790      case 0x1A9: // divde (Divide Doubleword Extended)
3791        /*
3792         * If the quotient cannot be represented in 64 bits, or if an
3793         * attempt is made to perform the division
3794         *      <anything> / 0
3795         * then the contents of register RD are undefined as are (if
3796         * Rc=1) the contents of the LT, GT, and EQ bits of CR
3797         * Field 0. In these cases, if OE=1 then OV is set to 1.
3798         */
3799         DIP("divde%s%s r%u,r%u,r%u\n",
3800             flag_OE ? "o" : "", flag_rC ? ".":"",
3801             rD_addr, rA_addr, rB_addr);
3802         assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
3803         if (flag_OE) {
3804            set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
3805                           mkexpr( rA ), mkexpr( rB ) );
3806         }
3807         break;
3808
3809      case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
3810        // Same CR and OV rules as given for divweu above
3811        DIP("divdeu%s%s r%u,r%u,r%u\n",
3812            flag_OE ? "o" : "", flag_rC ? ".":"",
3813            rD_addr, rA_addr, rB_addr);
3814        assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
3815        if (flag_OE) {
3816           set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
3817                          mkexpr( rA ), mkexpr( rB ) );
3818        }
3819        break;
3820
3821      default:
3822         vex_printf("dis_int_arith(ppc)(opc2)\n");
3823         return False;
3824      }
3825      break;
3826
3827   default:
3828      vex_printf("dis_int_arith(ppc)(opc1)\n");
3829      return False;
3830   }
3831
3832   putIReg( rD_addr, mkexpr(rD) );
3833
3834   if (do_rc && flag_rC) {
3835      set_CR0( mkexpr(rD) );
3836   }
3837   return True;
3838}
3839
3840
3841
3842/*
3843  Integer Compare Instructions
3844*/
3845static Bool dis_int_cmp ( UInt theInstr )
3846{
3847   /* D-Form, X-Form */
3848   UChar opc1    = ifieldOPC(theInstr);
3849   UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
3850   UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
3851   UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
3852   UChar rA_addr = ifieldRegA(theInstr);
3853   UInt  uimm16  = ifieldUIMM16(theInstr);
3854   UChar rB_addr = ifieldRegB(theInstr);
3855   UInt  opc2    = ifieldOPClo10(theInstr);
3856   UChar b0      = ifieldBIT0(theInstr);
3857
3858   IRType ty = mode64 ? Ity_I64 : Ity_I32;
3859   IRExpr *a = getIReg(rA_addr);
3860   IRExpr *b;
3861
3862   if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
3863      vex_printf("dis_int_cmp(ppc)(flag_L)\n");
3864      return False;
3865   }
3866
3867   if (b22 != 0) {
3868      vex_printf("dis_int_cmp(ppc)(b22)\n");
3869      return False;
3870   }
3871
3872   switch (opc1) {
3873   case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
3874      DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
3875          (Int)extend_s_16to32(uimm16));
3876      b = mkSzExtendS16( ty, uimm16 );
3877      if (flag_L == 1) {
3878         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
3879      } else {
3880         a = mkNarrowTo32( ty, a );
3881         b = mkNarrowTo32( ty, b );
3882         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
3883      }
3884      putCR0( crfD, getXER_SO() );
3885      break;
3886
3887   case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
3888      DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
3889      b = mkSzImm( ty, uimm16 );
3890      if (flag_L == 1) {
3891         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
3892      } else {
3893         a = mkNarrowTo32( ty, a );
3894         b = mkNarrowTo32( ty, b );
3895         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
3896      }
3897      putCR0( crfD, getXER_SO() );
3898      break;
3899
3900   /* X Form */
3901   case 0x1F:
3902      if (b0 != 0) {
3903         vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
3904         return False;
3905      }
3906      b = getIReg(rB_addr);
3907
3908      switch (opc2) {
3909      case 0x000: // cmp (Compare, PPC32 p367)
3910         DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
3911         /* Comparing a reg with itself produces a result which
3912            doesn't depend on the contents of the reg.  Therefore
3913            remove the false dependency, which has been known to cause
3914            memcheck to produce false errors. */
3915         if (rA_addr == rB_addr)
3916            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
3917                    ? mkU64(0)  : mkU32(0);
3918         if (flag_L == 1) {
3919            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
3920         } else {
3921            a = mkNarrowTo32( ty, a );
3922            b = mkNarrowTo32( ty, b );
3923            putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
3924         }
3925         putCR0( crfD, getXER_SO() );
3926         break;
3927
3928      case 0x020: // cmpl (Compare Logical, PPC32 p369)
3929         DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
3930         /* Comparing a reg with itself produces a result which
3931            doesn't depend on the contents of the reg.  Therefore
3932            remove the false dependency, which has been known to cause
3933            memcheck to produce false errors. */
3934         if (rA_addr == rB_addr)
3935            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
3936                    ? mkU64(0)  : mkU32(0);
3937         if (flag_L == 1) {
3938            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
3939         } else {
3940            a = mkNarrowTo32( ty, a );
3941            b = mkNarrowTo32( ty, b );
3942            putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
3943         }
3944         putCR0( crfD, getXER_SO() );
3945         break;
3946
3947      default:
3948         vex_printf("dis_int_cmp(ppc)(opc2)\n");
3949         return False;
3950      }
3951      break;
3952
3953   default:
3954      vex_printf("dis_int_cmp(ppc)(opc1)\n");
3955      return False;
3956   }
3957
3958   return True;
3959}
3960
3961
3962/*
3963  Integer Logical Instructions
3964*/
3965static Bool dis_int_logic ( UInt theInstr )
3966{
3967   /* D-Form, X-Form */
3968   UChar opc1    = ifieldOPC(theInstr);
3969   UChar rS_addr = ifieldRegDS(theInstr);
3970   UChar rA_addr = ifieldRegA(theInstr);
3971   UInt  uimm16  = ifieldUIMM16(theInstr);
3972   UChar rB_addr = ifieldRegB(theInstr);
3973   UInt  opc2    = ifieldOPClo10(theInstr);
3974   UChar flag_rC = ifieldBIT0(theInstr);
3975
3976   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3977   IRTemp rS     = newTemp(ty);
3978   IRTemp rA     = newTemp(ty);
3979   IRTemp rB     = newTemp(ty);
3980   IRExpr* irx;
3981   Bool do_rc    = False;
3982
3983   assign( rS, getIReg(rS_addr) );
3984   assign( rB, getIReg(rB_addr) );
3985
3986   switch (opc1) {
3987   case 0x1C: // andi. (AND Immediate, PPC32 p358)
3988      DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3989      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3990                         mkSzImm(ty, uimm16)) );
3991      do_rc = True;  // Always record to CR
3992      flag_rC = 1;
3993      break;
3994
3995   case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
3996      DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3997      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3998                         mkSzImm(ty, uimm16 << 16)) );
3999      do_rc = True;  // Always record to CR
4000      flag_rC = 1;
4001      break;
4002
4003   case 0x18: // ori (OR Immediate, PPC32 p497)
4004      DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4005      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4006                         mkSzImm(ty, uimm16)) );
4007      break;
4008
4009   case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
4010      DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4011      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4012                         mkSzImm(ty, uimm16 << 16)) );
4013      break;
4014
4015   case 0x1A: // xori (XOR Immediate, PPC32 p550)
4016      DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4017      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
4018                         mkSzImm(ty, uimm16)) );
4019      break;
4020
4021   case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
4022      DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4023      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
4024                         mkSzImm(ty, uimm16 << 16)) );
4025      break;
4026
4027   /* X Form */
4028   case 0x1F:
4029      do_rc = True; // All below record to CR, except for where we return at case end.
4030
4031      switch (opc2) {
4032      case 0x01C: // and (AND, PPC32 p356)
4033         DIP("and%s r%u,r%u,r%u\n",
4034             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4035         assign(rA, binop( mkSzOp(ty, Iop_And8),
4036                           mkexpr(rS), mkexpr(rB)));
4037         break;
4038
4039      case 0x03C: // andc (AND with Complement, PPC32 p357)
4040         DIP("andc%s r%u,r%u,r%u\n",
4041             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4042         assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
4043                           unop( mkSzOp(ty, Iop_Not8),
4044                                 mkexpr(rB))));
4045         break;
4046
4047      case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
4048         IRExpr* lo32;
4049         if (rB_addr!=0) {
4050            vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
4051            return False;
4052         }
4053         DIP("cntlzw%s r%u,r%u\n",
4054             flag_rC ? ".":"", rA_addr, rS_addr);
4055
4056         // mode64: count in low word only
4057         lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
4058
4059         // Iop_Clz32 undefined for arg==0, so deal with that case:
4060         irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
4061         assign(rA, mkWidenFrom32(ty,
4062                         IRExpr_ITE( irx,
4063                                     unop(Iop_Clz32, lo32),
4064                                     mkU32(32)),
4065                         False));
4066
4067         // TODO: alternatively: assign(rA, verbose_Clz32(rS));
4068         break;
4069      }
4070
4071      case 0x11C: // eqv (Equivalent, PPC32 p396)
4072         DIP("eqv%s r%u,r%u,r%u\n",
4073             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4074         assign( rA, unop( mkSzOp(ty, Iop_Not8),
4075                           binop( mkSzOp(ty, Iop_Xor8),
4076                                  mkexpr(rS), mkexpr(rB))) );
4077         break;
4078
4079      case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
4080         if (rB_addr!=0) {
4081            vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
4082            return False;
4083         }
4084         DIP("extsb%s r%u,r%u\n",
4085             flag_rC ? ".":"", rA_addr, rS_addr);
4086         if (mode64)
4087            assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
4088         else
4089            assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
4090         break;
4091
4092      case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
4093         if (rB_addr!=0) {
4094            vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
4095            return False;
4096         }
4097         DIP("extsh%s r%u,r%u\n",
4098             flag_rC ? ".":"", rA_addr, rS_addr);
4099         if (mode64)
4100            assign( rA, unop(Iop_16Sto64,
4101                             unop(Iop_64to16, mkexpr(rS))) );
4102         else
4103            assign( rA, unop(Iop_16Sto32,
4104                             unop(Iop_32to16, mkexpr(rS))) );
4105         break;
4106
4107      case 0x1DC: // nand (NAND, PPC32 p492)
4108         DIP("nand%s r%u,r%u,r%u\n",
4109             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4110         assign( rA, unop( mkSzOp(ty, Iop_Not8),
4111                           binop( mkSzOp(ty, Iop_And8),
4112                                  mkexpr(rS), mkexpr(rB))) );
4113         break;
4114
4115      case 0x07C: // nor (NOR, PPC32 p494)
4116         DIP("nor%s r%u,r%u,r%u\n",
4117             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4118         assign( rA, unop( mkSzOp(ty, Iop_Not8),
4119                           binop( mkSzOp(ty, Iop_Or8),
4120                                  mkexpr(rS), mkexpr(rB))) );
4121         break;
4122
4123      case 0x1BC: // or (OR, PPC32 p495)
4124         if ((!flag_rC) && rS_addr == rB_addr) {
4125            DIP("mr r%u,r%u\n", rA_addr, rS_addr);
4126            assign( rA, mkexpr(rS) );
4127         } else {
4128            DIP("or%s r%u,r%u,r%u\n",
4129                flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4130            assign( rA, binop( mkSzOp(ty, Iop_Or8),
4131                               mkexpr(rS), mkexpr(rB)) );
4132         }
4133         break;
4134
4135      case 0x19C: // orc  (OR with Complement, PPC32 p496)
4136         DIP("orc%s r%u,r%u,r%u\n",
4137             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4138         assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4139                            unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
4140         break;
4141
4142      case 0x13C: // xor (XOR, PPC32 p549)
4143         DIP("xor%s r%u,r%u,r%u\n",
4144             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4145         assign( rA, binop( mkSzOp(ty, Iop_Xor8),
4146                            mkexpr(rS), mkexpr(rB)) );
4147         break;
4148
4149
4150      /* 64bit Integer Logical Instructions */
4151      case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
4152         if (rB_addr!=0) {
4153            vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
4154            return False;
4155         }
4156         DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
4157         assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
4158         break;
4159
4160      case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
4161         if (rB_addr!=0) {
4162            vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
4163            return False;
4164         }
4165         DIP("cntlzd%s r%u,r%u\n",
4166             flag_rC ? ".":"", rA_addr, rS_addr);
4167         // Iop_Clz64 undefined for arg==0, so deal with that case:
4168         irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
4169         assign(rA, IRExpr_ITE( irx,
4170                                unop(Iop_Clz64, mkexpr(rS)),
4171                                mkU64(64) ));
4172         // TODO: alternatively: assign(rA, verbose_Clz64(rS));
4173         break;
4174
4175      case 0x1FC: // cmpb (Power6: compare bytes)
4176         DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
4177
4178         if (mode64)
4179            assign( rA, unop( Iop_V128to64,
4180                              binop( Iop_CmpEQ8x16,
4181                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
4182                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
4183                                     )) );
4184         else
4185            assign( rA, unop( Iop_V128to32,
4186                              binop( Iop_CmpEQ8x16,
4187                                     unop( Iop_32UtoV128, mkexpr(rS) ),
4188                                     unop( Iop_32UtoV128, mkexpr(rB) )
4189                                     )) );
4190         break;
4191
4192      case 0x2DF: { // mftgpr (move floating-point to general purpose register)
4193         IRTemp frB = newTemp(Ity_F64);
4194         DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
4195
4196         assign( frB, getFReg(rB_addr));  // always F64
4197         if (mode64)
4198            assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
4199         else
4200            assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
4201
4202         putIReg( rS_addr, mkexpr(rA));
4203         return True;
4204      }
4205
4206      case 0x25F: { // mffgpr (move floating-point from general purpose register)
4207         IRTemp frA = newTemp(Ity_F64);
4208         DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
4209
4210         if (mode64)
4211            assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
4212         else
4213            assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
4214
4215         putFReg( rS_addr, mkexpr(frA));
4216         return True;
4217      }
4218      case 0x1FA: // popcntd (population count doubleword
4219      {
4220    	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
4221    	  IRTemp result = gen_POPCOUNT(ty, rS, DWORD);
4222    	  putIReg( rA_addr, mkexpr(result) );
4223    	  return True;
4224      }
4225      case 0x17A: // popcntw (Population Count Words)
4226      {
4227         DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
4228         if (mode64) {
4229            IRTemp resultHi, resultLo;
4230            IRTemp argLo = newTemp(Ity_I32);
4231            IRTemp argHi = newTemp(Ity_I32);
4232            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4233            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
4234            resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD);
4235            resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD);
4236            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
4237         } else {
4238            IRTemp result = gen_POPCOUNT(ty, rS, WORD);
4239            putIReg( rA_addr, mkexpr(result) );
4240         }
4241         return True;
4242      }
4243      case 0x7A: // popcntb (Population Count Byte)
4244      {
4245         DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
4246
4247         if (mode64) {
4248            IRTemp resultHi, resultLo;
4249            IRTemp argLo = newTemp(Ity_I32);
4250            IRTemp argHi = newTemp(Ity_I32);
4251            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4252            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
4253            resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE);
4254            resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE);
4255            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
4256                                    mkexpr(resultLo)));
4257         } else {
4258            IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
4259            putIReg( rA_addr, mkexpr(result) );
4260         }
4261         return True;
4262      }
4263       case 0x0FC: // bpermd (Bit Permute Doubleword)
4264       {
4265          /* This is a lot of rigmarole to emulate bpermd like this, as it
4266           * could be done much faster by implementing a call to the native
4267           * instruction.  However, where possible I want to avoid using new
4268           * native instructions so that we can use valgrind to emulate those
4269           * instructions on older PPC64 hardware.
4270           */
4271 #define BPERMD_IDX_MASK 0x00000000000000FFULL
4272 #define BPERMD_BIT_MASK 0x8000000000000000ULL
4273          int i;
4274          IRExpr * rS_expr = mkexpr(rS);
4275          IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
4276          DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
4277          for (i = 0; i < 8; i++) {
4278             IRTemp idx_tmp = newTemp( Ity_I64 );
4279             IRTemp perm_bit = newTemp( Ity_I64 );
4280             IRTemp idx = newTemp( Ity_I8 );
4281             IRTemp idx_LT64 = newTemp( Ity_I1 );
4282             IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
4283
4284             assign( idx_tmp,
4285                     binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
4286             assign( idx_LT64,
4287                           binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
4288             assign( idx,
4289                           binop( Iop_And8,
4290                                  unop( Iop_1Sto8,
4291                                        mkexpr(idx_LT64) ),
4292                                  unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
4293             /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
4294              * to determine which bit of rB to use for the perm bit, and then we shift
4295              * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
4296              * to set the final perm bit.
4297              */
4298             assign( idx_LT64_ity64,
4299                           unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
4300             assign( perm_bit,
4301                           binop( Iop_And64,
4302                                  mkexpr( idx_LT64_ity64 ),
4303                                  binop( Iop_Shr64,
4304                                         binop( Iop_And64,
4305                                                mkU64( BPERMD_BIT_MASK ),
4306                                                binop( Iop_Shl64,
4307                                                       mkexpr( rB ),
4308                                                       mkexpr( idx ) ) ),
4309                                         mkU8( 63 ) ) ) );
4310             res = binop( Iop_Or64,
4311                                res,
4312                                binop( Iop_Shl64,
4313                                       mkexpr( perm_bit ),
4314                                       mkU8( i ) ) );
4315             rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
4316          }
4317          putIReg(rA_addr, res);
4318          return True;
4319       }
4320
4321      default:
4322         vex_printf("dis_int_logic(ppc)(opc2)\n");
4323         return False;
4324      }
4325      break;
4326
4327   default:
4328      vex_printf("dis_int_logic(ppc)(opc1)\n");
4329      return False;
4330   }
4331
4332   putIReg( rA_addr, mkexpr(rA) );
4333
4334   if (do_rc && flag_rC) {
4335      set_CR0( mkexpr(rA) );
4336   }
4337   return True;
4338}
4339
4340/*
4341  Integer Parity Instructions
4342*/
4343static Bool dis_int_parity ( UInt theInstr )
4344{
4345   /* X-Form */
4346   UChar opc1    = ifieldOPC(theInstr);
4347   UChar rS_addr = ifieldRegDS(theInstr);
4348   UChar rA_addr = ifieldRegA(theInstr);
4349   UChar rB_addr = ifieldRegB(theInstr);
4350   UInt  opc2    = ifieldOPClo10(theInstr);
4351   UChar b0      = ifieldBIT0(theInstr);
4352   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4353
4354   IRTemp rS     = newTemp(ty);
4355   IRTemp rA     = newTemp(ty);
4356   IRTemp iTot1  = newTemp(Ity_I32);
4357   IRTemp iTot2  = newTemp(Ity_I32);
4358   IRTemp iTot3  = newTemp(Ity_I32);
4359   IRTemp iTot4  = newTemp(Ity_I32);
4360   IRTemp iTot5  = newTemp(Ity_I32);
4361   IRTemp iTot6  = newTemp(Ity_I32);
4362   IRTemp iTot7  = newTemp(Ity_I32);
4363   IRTemp iTot8  = newTemp(Ity_I32);
4364   IRTemp rS1    = newTemp(ty);
4365   IRTemp rS2    = newTemp(ty);
4366   IRTemp rS3    = newTemp(ty);
4367   IRTemp rS4    = newTemp(ty);
4368   IRTemp rS5    = newTemp(ty);
4369   IRTemp rS6    = newTemp(ty);
4370   IRTemp rS7    = newTemp(ty);
4371   IRTemp iHi    = newTemp(Ity_I32);
4372   IRTemp iLo    = newTemp(Ity_I32);
4373   IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
4374   IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
4375
4376   if (opc1 != 0x1f || rB_addr || b0) {
4377      vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
4378      return False;
4379   }
4380
4381   assign( rS, getIReg(rS_addr) );
4382
4383   switch (opc2) {
4384   case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
4385      DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
4386      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4387      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4388      assign( iTot2, binop(Iop_Add32,
4389                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4390                           mkexpr(iTot1)) );
4391      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4392      assign( iTot3, binop(Iop_Add32,
4393                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4394                           mkexpr(iTot2)) );
4395      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4396      assign( iTot4, binop(Iop_Add32,
4397                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4398                           mkexpr(iTot3)) );
4399      if (mode64) {
4400         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4401         assign( iTot5, binop(Iop_Add32,
4402                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
4403                              mkexpr(iTot4)) );
4404         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4405         assign( iTot6, binop(Iop_Add32,
4406                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4407                              mkexpr(iTot5)) );
4408         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4409         assign( iTot7, binop(Iop_Add32,
4410                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4411                              mkexpr(iTot6)) );
4412         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
4413         assign( iTot8, binop(Iop_Add32,
4414                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4415                              mkexpr(iTot7)) );
4416         assign( rA, unop(Iop_32Uto64,
4417                          binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
4418      } else
4419         assign( rA, mkexpr(iTot4) );
4420
4421      break;
4422   case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
4423      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4424      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4425      assign( iTot2, binop(Iop_Add32,
4426                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4427                           mkexpr(iTot1)) );
4428      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4429      assign( iTot3, binop(Iop_Add32,
4430                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4431                           mkexpr(iTot2)) );
4432      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4433      assign( iTot4, binop(Iop_Add32,
4434                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4435                           mkexpr(iTot3)) );
4436      assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
4437
4438      if (mode64) {
4439         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4440         assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
4441         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4442         assign( iTot6, binop(Iop_Add32,
4443                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4444                              mkexpr(iTot5)) );
4445         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4446         assign( iTot7, binop(Iop_Add32,
4447                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4448                              mkexpr(iTot6)) );
4449         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
4450         assign( iTot8, binop(Iop_Add32,
4451                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4452                              mkexpr(iTot7)) );
4453         assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
4454            assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
4455      } else
4456         assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
4457      break;
4458   default:
4459      vex_printf("dis_int_parity(ppc)(opc2)\n");
4460      return False;
4461   }
4462
4463   putIReg( rA_addr, mkexpr(rA) );
4464
4465   return True;
4466}
4467
4468
4469/*
4470  Integer Rotate Instructions
4471*/
4472static Bool dis_int_rot ( UInt theInstr )
4473{
4474   /* M-Form, MDS-Form */
4475   UChar opc1    = ifieldOPC(theInstr);
4476   UChar rS_addr = ifieldRegDS(theInstr);
4477   UChar rA_addr = ifieldRegA(theInstr);
4478   UChar rB_addr = ifieldRegB(theInstr);
4479   UChar sh_imm  = rB_addr;
4480   UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
4481   UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
4482   UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
4483   UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
4484   UChar b1      = ifieldBIT1(theInstr);
4485   UChar flag_rC = ifieldBIT0(theInstr);
4486
4487   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4488   IRTemp rS     = newTemp(ty);
4489   IRTemp rA     = newTemp(ty);
4490   IRTemp rB     = newTemp(ty);
4491   IRTemp rot    = newTemp(ty);
4492   IRExpr *r;
4493   UInt   mask32;
4494   ULong  mask64;
4495
4496   assign( rS, getIReg(rS_addr) );
4497   assign( rB, getIReg(rB_addr) );
4498
4499   switch (opc1) {
4500   case 0x14: {
4501      // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
4502      DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4503          rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4504      if (mode64) {
4505         // tmp32 = (ROTL(rS_Lo32, Imm)
4506         // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
4507         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4508         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4509         r = unop(Iop_32Uto64, r);
4510         assign( rot, binop(Iop_Or64, r,
4511                            binop(Iop_Shl64, r, mkU8(32))) );
4512         assign( rA,
4513            binop(Iop_Or64,
4514                  binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
4515                  binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
4516      }
4517      else {
4518         // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
4519         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4520         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4521         assign( rA,
4522            binop(Iop_Or32,
4523                  binop(Iop_And32, mkU32(mask32), r),
4524                  binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
4525      }
4526      break;
4527   }
4528
4529   case 0x15: {
4530      // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
4531      vassert(MaskBeg < 32);
4532      vassert(MaskEnd < 32);
4533      vassert(sh_imm  < 32);
4534
4535      if (mode64) {
4536         IRTemp rTmp = newTemp(Ity_I64);
4537         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4538         DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4539             rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4540         // tmp32 = (ROTL(rS_Lo32, Imm)
4541         // rA = ((tmp32 || tmp32) & mask64)
4542         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4543         r = unop(Iop_32Uto64, r);
4544         assign( rTmp, r );
4545         r = NULL;
4546         assign( rot, binop(Iop_Or64, mkexpr(rTmp),
4547                            binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
4548         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4549      }
4550      else {
4551         if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
4552            /* Special-case the ,n,0,31-n form as that is just n-bit
4553               shift left, PPC32 p501 */
4554            DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4555                rA_addr, rS_addr, sh_imm);
4556            assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
4557         }
4558         else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
4559            /* Special-case the ,32-n,n,31 form as that is just n-bit
4560               unsigned shift right, PPC32 p501 */
4561            DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4562                rA_addr, rS_addr, MaskBeg);
4563            assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
4564         }
4565         else {
4566            /* General case. */
4567            mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4568            DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4569                rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4570            // rA = ROTL(rS, Imm) & mask
4571            assign( rA, binop(Iop_And32,
4572                              ROTL(mkexpr(rS), mkU8(sh_imm)),
4573                              mkU32(mask32)) );
4574         }
4575      }
4576      break;
4577   }
4578
4579   case 0x17: {
4580      // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
4581      DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
4582          rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
4583      if (mode64) {
4584         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4585         /* weird insn alert!
4586            tmp32 = (ROTL(rS_Lo32, rB[0-4])
4587            rA = ((tmp32 || tmp32) & mask64)
4588         */
4589         // note, ROTL does the masking, so we don't do it here
4590         r = ROTL( unop(Iop_64to32, mkexpr(rS)),
4591                   unop(Iop_64to8, mkexpr(rB)) );
4592         r = unop(Iop_32Uto64, r);
4593         assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
4594         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4595      } else {
4596         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4597         // rA = ROTL(rS, rB[0-4]) & mask
4598         // note, ROTL does the masking, so we don't do it here
4599         assign( rA, binop(Iop_And32,
4600                           ROTL(mkexpr(rS),
4601                                unop(Iop_32to8, mkexpr(rB))),
4602                           mkU32(mask32)) );
4603      }
4604      break;
4605   }
4606
4607   /* 64bit Integer Rotates */
4608   case 0x1E: {
4609      msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
4610      sh_imm |= b1 << 5;
4611
4612      vassert( msk_imm < 64 );
4613      vassert( sh_imm < 64 );
4614
4615      switch (opc2) {
4616      case 0x4: {
4617         /* r = ROTL64( rS, rB_lo6) */
4618         r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
4619
4620         if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
4621            DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4622                rA_addr, rS_addr, rB_addr, msk_imm);
4623            // note, ROTL does the masking, so we don't do it here
4624            mask64 = MASK64(0, 63-msk_imm);
4625            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4626            break;
4627         } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
4628            DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4629                rA_addr, rS_addr, rB_addr, msk_imm);
4630            mask64 = MASK64(63-msk_imm, 63);
4631            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4632            break;
4633         }
4634         break;
4635      }
4636      case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
4637         DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4638             rA_addr, rS_addr, sh_imm, msk_imm);
4639         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4640         mask64 = MASK64(sh_imm, 63-msk_imm);
4641         assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4642         break;
4643         // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
4644         /*
4645           Hmm... looks like this'll do the job more simply:
4646           r = SHL(rS, sh_imm)
4647           m = ~(1 << (63-msk_imm))
4648           assign(rA, r & m);
4649         */
4650
4651      case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
4652         if (mode64
4653             && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
4654            /* special-case the ,64-n,n form as that is just
4655               unsigned shift-right by n */
4656            DIP("srdi%s r%u,r%u,%u\n",
4657                flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
4658            assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
4659         } else {
4660            DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4661                rA_addr, rS_addr, sh_imm, msk_imm);
4662            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4663            mask64 = MASK64(0, 63-msk_imm);
4664            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4665         }
4666         break;
4667
4668      case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
4669         if (mode64
4670             && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
4671            /* special-case the ,n,63-n form as that is just
4672               shift-left by n */
4673            DIP("sldi%s r%u,r%u,%u\n",
4674                flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
4675            assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
4676         } else {
4677            DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4678                rA_addr, rS_addr, sh_imm, msk_imm);
4679            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4680            mask64 = MASK64(63-msk_imm, 63);
4681            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4682         }
4683         break;
4684
4685      case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
4686         IRTemp rA_orig = newTemp(ty);
4687         DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4688             rA_addr, rS_addr, sh_imm, msk_imm);
4689         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4690         mask64 = MASK64(sh_imm, 63-msk_imm);
4691         assign( rA_orig, getIReg(rA_addr) );
4692         assign( rA, binop(Iop_Or64,
4693                           binop(Iop_And64, mkU64(mask64),  r),
4694                           binop(Iop_And64, mkU64(~mask64),
4695                                            mkexpr(rA_orig))) );
4696         break;
4697      }
4698      default:
4699         vex_printf("dis_int_rot(ppc)(opc2)\n");
4700         return False;
4701      }
4702      break;
4703   }
4704
4705   default:
4706      vex_printf("dis_int_rot(ppc)(opc1)\n");
4707      return False;
4708   }
4709
4710   putIReg( rA_addr, mkexpr(rA) );
4711
4712   if (flag_rC) {
4713      set_CR0( mkexpr(rA) );
4714   }
4715   return True;
4716}
4717
4718
4719/*
4720  Integer Load Instructions
4721*/
4722static Bool dis_int_load ( UInt theInstr )
4723{
4724   /* D-Form, X-Form, DS-Form */
4725   UChar opc1     = ifieldOPC(theInstr);
4726   UChar rD_addr  = ifieldRegDS(theInstr);
4727   UChar rA_addr  = ifieldRegA(theInstr);
4728   UInt  uimm16   = ifieldUIMM16(theInstr);
4729   UChar rB_addr  = ifieldRegB(theInstr);
4730   UInt  opc2     = ifieldOPClo10(theInstr);
4731   UChar b1       = ifieldBIT1(theInstr);
4732   UChar b0       = ifieldBIT0(theInstr);
4733
4734   Int     simm16 = extend_s_16to32(uimm16);
4735   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
4736   IRTemp  EA     = newTemp(ty);
4737   IRExpr* val;
4738
4739   switch (opc1) {
4740   case 0x1F: // register offset
4741      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
4742      break;
4743   case 0x38: // immediate offset: 64bit: lq: maskoff
4744              // lowest 4 bits of immediate before forming EA
4745      simm16 = simm16 & 0xFFFFFFF0;
4746      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
4747      break;
4748   case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
4749              // lowest 2 bits of immediate before forming EA
4750      simm16 = simm16 & 0xFFFFFFFC;
4751      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
4752      break;
4753   default:   // immediate offset
4754      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
4755      break;
4756   }
4757
4758   switch (opc1) {
4759   case 0x22: // lbz (Load B & Zero, PPC32 p433)
4760      DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4761      val = loadBE(Ity_I8, mkexpr(EA));
4762      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4763      break;
4764
4765   case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
4766      if (rA_addr == 0 || rA_addr == rD_addr) {
4767         vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
4768         return False;
4769      }
4770      DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4771      val = loadBE(Ity_I8, mkexpr(EA));
4772      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4773      putIReg( rA_addr, mkexpr(EA) );
4774      break;
4775
4776   case 0x2A: // lha (Load HW Alg, PPC32 p445)
4777      DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4778      val = loadBE(Ity_I16, mkexpr(EA));
4779      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4780      break;
4781
4782   case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
4783      if (rA_addr == 0 || rA_addr == rD_addr) {
4784         vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
4785         return False;
4786      }
4787      DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4788      val = loadBE(Ity_I16, mkexpr(EA));
4789      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4790      putIReg( rA_addr, mkexpr(EA) );
4791      break;
4792
4793   case 0x28: // lhz (Load HW & Zero, PPC32 p450)
4794      DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4795      val = loadBE(Ity_I16, mkexpr(EA));
4796      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4797      break;
4798
4799   case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
4800      if (rA_addr == 0 || rA_addr == rD_addr) {
4801         vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
4802         return False;
4803      }
4804      DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4805      val = loadBE(Ity_I16, mkexpr(EA));
4806      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4807      putIReg( rA_addr, mkexpr(EA) );
4808      break;
4809
4810   case 0x20: // lwz (Load W & Zero, PPC32 p460)
4811      DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4812      val = loadBE(Ity_I32, mkexpr(EA));
4813      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4814      break;
4815
4816   case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
4817      if (rA_addr == 0 || rA_addr == rD_addr) {
4818         vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
4819         return False;
4820      }
4821      DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4822      val = loadBE(Ity_I32, mkexpr(EA));
4823      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4824      putIReg( rA_addr, mkexpr(EA) );
4825      break;
4826
4827   /* X Form */
4828   case 0x1F:
4829      if (b0 != 0) {
4830         vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
4831         return False;
4832      }
4833
4834      switch (opc2) {
4835      case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
4836         DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4837         if (rA_addr == 0 || rA_addr == rD_addr) {
4838            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
4839            return False;
4840         }
4841         val = loadBE(Ity_I8, mkexpr(EA));
4842         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4843         putIReg( rA_addr, mkexpr(EA) );
4844         break;
4845
4846      case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
4847         DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4848         val = loadBE(Ity_I8, mkexpr(EA));
4849         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4850         break;
4851
4852      case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
4853         if (rA_addr == 0 || rA_addr == rD_addr) {
4854            vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
4855            return False;
4856         }
4857         DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4858         val = loadBE(Ity_I16, mkexpr(EA));
4859         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4860         putIReg( rA_addr, mkexpr(EA) );
4861         break;
4862
4863      case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
4864         DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4865         val = loadBE(Ity_I16, mkexpr(EA));
4866         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4867         break;
4868
4869      case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
4870         if (rA_addr == 0 || rA_addr == rD_addr) {
4871            vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
4872            return False;
4873         }
4874         DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4875         val = loadBE(Ity_I16, mkexpr(EA));
4876         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4877         putIReg( rA_addr, mkexpr(EA) );
4878         break;
4879
4880      case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
4881         DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4882         val = loadBE(Ity_I16, mkexpr(EA));
4883         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4884         break;
4885
4886      case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
4887         if (rA_addr == 0 || rA_addr == rD_addr) {
4888            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
4889            return False;
4890         }
4891         DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4892         val = loadBE(Ity_I32, mkexpr(EA));
4893         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4894         putIReg( rA_addr, mkexpr(EA) );
4895         break;
4896
4897      case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
4898         DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4899         val = loadBE(Ity_I32, mkexpr(EA));
4900         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4901         break;
4902
4903
4904      /* 64bit Loads */
4905      case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
4906         if (rA_addr == 0 || rA_addr == rD_addr) {
4907            vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
4908            return False;
4909         }
4910         DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4911         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4912         putIReg( rA_addr, mkexpr(EA) );
4913         break;
4914
4915      case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
4916         DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4917         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4918         break;
4919
4920      case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
4921         if (rA_addr == 0 || rA_addr == rD_addr) {
4922            vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
4923            return False;
4924         }
4925         DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4926         putIReg( rD_addr,
4927                  unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4928         putIReg( rA_addr, mkexpr(EA) );
4929         break;
4930
4931      case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
4932         DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4933         putIReg( rD_addr,
4934                  unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4935         break;
4936
4937      default:
4938         vex_printf("dis_int_load(ppc)(opc2)\n");
4939         return False;
4940      }
4941      break;
4942
4943   /* DS Form - 64bit Loads.  In each case EA will have been formed
4944      with the lowest 2 bits masked off the immediate offset. */
4945   case 0x3A:
4946      switch ((b1<<1) | b0) {
4947      case 0x0: // ld (Load DWord, PPC64 p472)
4948         DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4949         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4950         break;
4951
4952      case 0x1: // ldu (Load DWord, Update, PPC64 p474)
4953         if (rA_addr == 0 || rA_addr == rD_addr) {
4954            vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
4955            return False;
4956         }
4957         DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4958         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4959         putIReg( rA_addr, mkexpr(EA) );
4960         break;
4961
4962      case 0x2: // lwa (Load Word Alg, PPC64 p499)
4963         DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4964         putIReg( rD_addr,
4965                  unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4966         break;
4967
4968      default:
4969         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
4970         return False;
4971      }
4972      break;
4973
4974   case 0x38: {
4975      IRTemp  high = newTemp(ty);
4976      IRTemp  low  = newTemp(ty);
4977      /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
4978      DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4979      /* NOTE: there are some changes to XER[41:42] that have not been
4980       * implemented.
4981       */
4982      // trap if EA misaligned on 16 byte address
4983      if (mode64) {
4984         assign(high, loadBE(ty, mkexpr( EA ) ) );
4985         assign(low, loadBE(ty, binop( Iop_Add64,
4986                                       mkexpr( EA ),
4987                                       mkU64( 8 ) ) ) );
4988      } else {
4989         assign(high, loadBE(ty, binop( Iop_Add32,
4990                                        mkexpr( EA ),
4991                                        mkU32( 4 ) ) ) );
4992         assign(low, loadBE(ty, binop( Iop_Add32,
4993                                        mkexpr( EA ),
4994                                        mkU32( 12 ) ) ) );
4995      }
4996      gen_SIGBUS_if_misaligned( EA, 16 );
4997      putIReg( rD_addr,  mkexpr( high) );
4998      putIReg( rD_addr+1,  mkexpr( low) );
4999      break;
5000   }
5001   default:
5002      vex_printf("dis_int_load(ppc)(opc1)\n");
5003      return False;
5004   }
5005   return True;
5006}
5007
5008
5009
5010/*
5011  Integer Store Instructions
5012*/
5013static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi )
5014{
5015   /* D-Form, X-Form, DS-Form */
5016   UChar opc1    = ifieldOPC(theInstr);
5017   UInt  rS_addr = ifieldRegDS(theInstr);
5018   UInt  rA_addr = ifieldRegA(theInstr);
5019   UInt  uimm16  = ifieldUIMM16(theInstr);
5020   UInt  rB_addr = ifieldRegB(theInstr);
5021   UInt  opc2    = ifieldOPClo10(theInstr);
5022   UChar b1      = ifieldBIT1(theInstr);
5023   UChar b0      = ifieldBIT0(theInstr);
5024
5025   Int    simm16 = extend_s_16to32(uimm16);
5026   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
5027   IRTemp rS     = newTemp(ty);
5028   IRTemp rB     = newTemp(ty);
5029   IRTemp EA     = newTemp(ty);
5030
5031   assign( rB, getIReg(rB_addr) );
5032   assign( rS, getIReg(rS_addr) );
5033
5034   switch (opc1) {
5035   case 0x1F: // register offset
5036      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5037      break;
5038   case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
5039              // lowest 2 bits of immediate before forming EA
5040      simm16 = simm16 & 0xFFFFFFFC;
5041   default:   // immediate offset
5042      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5043      break;
5044   }
5045
5046   switch (opc1) {
5047   case 0x26: // stb (Store B, PPC32 p509)
5048      DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5049      storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5050      break;
5051
5052   case 0x27: // stbu (Store B, Update, PPC32 p510)
5053      if (rA_addr == 0 ) {
5054         vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
5055         return False;
5056      }
5057      DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5058      putIReg( rA_addr, mkexpr(EA) );
5059      storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5060      break;
5061
5062   case 0x2C: // sth (Store HW, PPC32 p522)
5063      DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5064      storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5065      break;
5066
5067   case 0x2D: // sthu (Store HW, Update, PPC32 p524)
5068      if (rA_addr == 0) {
5069         vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
5070         return False;
5071      }
5072      DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5073      putIReg( rA_addr, mkexpr(EA) );
5074      storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5075      break;
5076
5077   case 0x24: // stw (Store W, PPC32 p530)
5078      DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5079      storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5080      break;
5081
5082   case 0x25: // stwu (Store W, Update, PPC32 p534)
5083      if (rA_addr == 0) {
5084         vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
5085         return False;
5086      }
5087      DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5088      putIReg( rA_addr, mkexpr(EA) );
5089      storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5090      break;
5091
5092   /* X Form : all these use EA_indexed */
5093   case 0x1F:
5094      if (b0 != 0) {
5095         vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
5096         return False;
5097      }
5098
5099      switch (opc2) {
5100      case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
5101         if (rA_addr == 0) {
5102            vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
5103            return False;
5104         }
5105         DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5106         putIReg( rA_addr, mkexpr(EA) );
5107         storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5108         break;
5109
5110      case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
5111         DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5112         storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5113         break;
5114
5115      case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
5116         if (rA_addr == 0) {
5117            vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
5118            return False;
5119         }
5120         DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5121         putIReg( rA_addr, mkexpr(EA) );
5122         storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5123         break;
5124
5125      case 0x197: // sthx (Store HW Indexed, PPC32 p526)
5126         DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5127         storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5128         break;
5129
5130      case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
5131         if (rA_addr == 0) {
5132            vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
5133            return False;
5134         }
5135         DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5136         putIReg( rA_addr, mkexpr(EA) );
5137         storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5138         break;
5139
5140      case 0x097: // stwx (Store W Indexed, PPC32 p536)
5141         DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5142         storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5143         break;
5144
5145
5146      /* 64bit Stores */
5147      case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
5148         if (rA_addr == 0) {
5149            vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
5150            return False;
5151         }
5152         DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5153         putIReg( rA_addr, mkexpr(EA) );
5154         storeBE( mkexpr(EA), mkexpr(rS) );
5155         break;
5156
5157      case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
5158         DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5159         storeBE( mkexpr(EA), mkexpr(rS) );
5160         break;
5161
5162      default:
5163         vex_printf("dis_int_store(ppc)(opc2)\n");
5164         return False;
5165      }
5166      break;
5167
5168   /* DS Form - 64bit Stores.  In each case EA will have been formed
5169      with the lowest 2 bits masked off the immediate offset. */
5170   case 0x3E:
5171      switch ((b1<<1) | b0) {
5172      case 0x0: // std (Store DWord, PPC64 p580)
5173         if (!mode64)
5174            return False;
5175
5176         DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5177         storeBE( mkexpr(EA), mkexpr(rS) );
5178         break;
5179
5180      case 0x1: // stdu (Store DWord, Update, PPC64 p583)
5181         if (!mode64)
5182            return False;
5183
5184         DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5185         putIReg( rA_addr, mkexpr(EA) );
5186         storeBE( mkexpr(EA), mkexpr(rS) );
5187         break;
5188
5189      case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
5190         IRTemp EA_hi = newTemp(ty);
5191         IRTemp EA_lo = newTemp(ty);
5192         DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5193
5194         if (mode64) {
5195            /* upper 64-bits */
5196            assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
5197
5198            /* lower 64-bits */
5199            assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) );
5200         } else {
5201            /* upper half of upper 64-bits */
5202            assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) );
5203
5204            /* lower half of upper 64-bits */
5205            assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
5206         }
5207         putIReg( rA_addr, mkexpr(EA_hi) );
5208         storeBE( mkexpr(EA_hi), mkexpr(rS) );
5209         putIReg( rA_addr, mkexpr( EA_lo) );
5210         storeBE( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
5211         break;
5212      }
5213      default:
5214         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
5215         return False;
5216      }
5217      break;
5218
5219   default:
5220      vex_printf("dis_int_store(ppc)(opc1)\n");
5221      return False;
5222   }
5223   return True;
5224}
5225
5226
5227
5228/*
5229  Integer Load/Store Multiple Instructions
5230*/
5231static Bool dis_int_ldst_mult ( UInt theInstr )
5232{
5233   /* D-Form */
5234   UChar opc1     = ifieldOPC(theInstr);
5235   UChar rD_addr  = ifieldRegDS(theInstr);
5236   UChar rS_addr  = rD_addr;
5237   UChar rA_addr  = ifieldRegA(theInstr);
5238   UInt  uimm16   = ifieldUIMM16(theInstr);
5239
5240   Int     simm16 = extend_s_16to32(uimm16);
5241   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
5242   IROp    mkAdd  = mode64 ? Iop_Add64 : Iop_Add32;
5243   IRTemp  EA     = newTemp(ty);
5244   UInt    r      = 0;
5245   UInt    ea_off = 0;
5246   IRExpr* irx_addr;
5247
5248   assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
5249
5250   switch (opc1) {
5251   case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
5252      if (rA_addr >= rD_addr) {
5253         vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
5254         return False;
5255      }
5256      DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5257      for (r = rD_addr; r <= 31; r++) {
5258         irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
5259         putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ),
5260                                       False) );
5261         ea_off += 4;
5262      }
5263      break;
5264
5265   case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
5266      DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5267      for (r = rS_addr; r <= 31; r++) {
5268         irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
5269         storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
5270         ea_off += 4;
5271      }
5272      break;
5273
5274   default:
5275      vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
5276      return False;
5277   }
5278   return True;
5279}
5280
5281
5282
5283/*
5284  Integer Load/Store String Instructions
5285*/
5286static
5287void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
5288                             IRTemp EA,        // EA
5289                             Int    rD,        // first dst register
5290                             Int    maxBytes ) // 32 or 128
5291{
5292   Int     i, shift = 24;
5293   IRExpr* e_nbytes = mkexpr(tNBytes);
5294   IRExpr* e_EA     = mkexpr(EA);
5295   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
5296
5297   vassert(rD >= 0 && rD < 32);
5298   rD--; if (rD < 0) rD = 31;
5299
5300   for (i = 0; i < maxBytes; i++) {
5301      /* if (nBytes < (i+1)) goto NIA; */
5302      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
5303                         Ijk_Boring,
5304                         mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
5305      /* when crossing into a new dest register, set it to zero. */
5306      if ((i % 4) == 0) {
5307         rD++; if (rD == 32) rD = 0;
5308         putIReg(rD, mkSzImm(ty, 0));
5309         shift = 24;
5310      }
5311      /* rD |=  (8Uto32(*(EA+i))) << shift */
5312      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
5313      putIReg(
5314         rD,
5315         mkWidenFrom32(
5316            ty,
5317            binop(
5318               Iop_Or32,
5319               mkNarrowTo32(ty, getIReg(rD)),
5320               binop(
5321                  Iop_Shl32,
5322                  unop(
5323                     Iop_8Uto32,
5324                     loadBE(Ity_I8,
5325                            binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)))
5326                  ),
5327                  mkU8(toUChar(shift))
5328               )
5329            ),
5330            /*Signed*/False
5331	 )
5332      );
5333      shift -= 8;
5334   }
5335}
5336
5337static
5338void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
5339                              IRTemp EA,        // EA
5340                              Int    rS,        // first src register
5341                              Int    maxBytes ) // 32 or 128
5342{
5343   Int     i, shift = 24;
5344   IRExpr* e_nbytes = mkexpr(tNBytes);
5345   IRExpr* e_EA     = mkexpr(EA);
5346   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
5347
5348   vassert(rS >= 0 && rS < 32);
5349   rS--; if (rS < 0) rS = 31;
5350
5351   for (i = 0; i < maxBytes; i++) {
5352      /* if (nBytes < (i+1)) goto NIA; */
5353      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
5354                         Ijk_Boring,
5355                         mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
5356      /* check for crossing into a new src register. */
5357      if ((i % 4) == 0) {
5358         rS++; if (rS == 32) rS = 0;
5359         shift = 24;
5360      }
5361      /* *(EA+i) = 32to8(rS >> shift) */
5362      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
5363      storeBE(
5364         binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
5365         unop(Iop_32to8,
5366              binop(Iop_Shr32,
5367                    mkNarrowTo32(ty, getIReg(rS)),
5368                    mkU8(toUChar(shift))))
5369      );
5370      shift -= 8;
5371   }
5372}
5373
5374static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
5375{
5376   /* X-Form */
5377   UChar opc1     = ifieldOPC(theInstr);
5378   UChar rD_addr  = ifieldRegDS(theInstr);
5379   UChar rS_addr  = rD_addr;
5380   UChar rA_addr  = ifieldRegA(theInstr);
5381   UChar rB_addr  = ifieldRegB(theInstr);
5382   UChar NumBytes = rB_addr;
5383   UInt  opc2     = ifieldOPClo10(theInstr);
5384   UChar b0       = ifieldBIT0(theInstr);
5385
5386   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5387   IRTemp t_EA    = newTemp(ty);
5388   IRTemp t_nbytes = IRTemp_INVALID;
5389
5390   *stopHere = False;
5391
5392   if (opc1 != 0x1F || b0 != 0) {
5393      vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
5394      return False;
5395   }
5396
5397   switch (opc2) {
5398   case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
5399      /* NB: does not reject the case where RA is in the range of
5400         registers to be loaded.  It should. */
5401      DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
5402      assign( t_EA, ea_rAor0(rA_addr) );
5403      if (NumBytes == 8 && !mode64) {
5404         /* Special case hack */
5405         /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
5406         putIReg( rD_addr,
5407                  loadBE(Ity_I32, mkexpr(t_EA)) );
5408         putIReg( (rD_addr+1) % 32,
5409                  loadBE(Ity_I32,
5410                         binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
5411      } else {
5412         t_nbytes = newTemp(Ity_I32);
5413         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5414         generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5415         *stopHere = True;
5416      }
5417      return True;
5418
5419   case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
5420      /* NB: does not reject the case where RA is in the range of
5421         registers to be loaded.  It should.  Although considering
5422         that that can only be detected at run time, it's not easy to
5423         do so. */
5424      if (rD_addr == rA_addr || rD_addr == rB_addr)
5425         return False;
5426      if (rD_addr == 0 && rA_addr == 0)
5427         return False;
5428      DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5429      t_nbytes = newTemp(Ity_I32);
5430      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5431      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5432      generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
5433      *stopHere = True;
5434      return True;
5435
5436   case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
5437      DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
5438      assign( t_EA, ea_rAor0(rA_addr) );
5439      if (NumBytes == 8 && !mode64) {
5440         /* Special case hack */
5441         /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
5442         storeBE( mkexpr(t_EA),
5443                  getIReg(rD_addr) );
5444         storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
5445                  getIReg((rD_addr+1) % 32) );
5446      } else {
5447         t_nbytes = newTemp(Ity_I32);
5448         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5449         generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5450         *stopHere = True;
5451      }
5452      return True;
5453
5454   case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
5455      DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5456      t_nbytes = newTemp(Ity_I32);
5457      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5458      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5459      generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
5460      *stopHere = True;
5461      return True;
5462
5463   default:
5464      vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
5465      return False;
5466   }
5467   return True;
5468}
5469
5470
5471/* ------------------------------------------------------------------
5472   Integer Branch Instructions
5473   ------------------------------------------------------------------ */
5474
5475/*
5476  Branch helper function
5477  ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
5478  Returns an I32 which is 0x00000000 if the ctr condition failed
5479  and 0xFFFFFFFF otherwise.
5480*/
5481static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
5482{
5483   IRType ty = mode64 ? Ity_I64 : Ity_I32;
5484   IRTemp ok = newTemp(Ity_I32);
5485
5486   if ((BO >> 2) & 1) {     // independent of ctr
5487      assign( ok, mkU32(0xFFFFFFFF) );
5488   } else {
5489      if ((BO >> 1) & 1) {  // ctr == 0 ?
5490         assign( ok, unop( Iop_1Sto32,
5491                           binop( mkSzOp(ty, Iop_CmpEQ8),
5492                                  getGST( PPC_GST_CTR ),
5493                                  mkSzImm(ty,0))) );
5494      } else {              // ctr != 0 ?
5495         assign( ok, unop( Iop_1Sto32,
5496                           binop( mkSzOp(ty, Iop_CmpNE8),
5497                                  getGST( PPC_GST_CTR ),
5498                                  mkSzImm(ty,0))) );
5499      }
5500   }
5501   return mkexpr(ok);
5502}
5503
5504
5505/*
5506  Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
5507  Returns an I32 which is either 0 if the condition failed or
5508  some arbitrary nonzero value otherwise. */
5509
5510static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
5511{
5512   Int where;
5513   IRTemp res   = newTemp(Ity_I32);
5514   IRTemp cr_bi = newTemp(Ity_I32);
5515
5516   if ((BO >> 4) & 1) {
5517      assign( res, mkU32(1) );
5518   } else {
5519      // ok = (CR[BI] == BO[3]) Note, the following relies on
5520      // getCRbit_anywhere returning a value which
5521      // is either zero or has exactly 1 bit set.
5522      assign( cr_bi, getCRbit_anywhere( BI, &where ) );
5523
5524      if ((BO >> 3) & 1) {
5525         /* We can use cr_bi as-is. */
5526         assign( res, mkexpr(cr_bi) );
5527      } else {
5528         /* We have to invert the sense of the information held in
5529            cr_bi.  For that we need to know which bit
5530            getCRbit_anywhere regards as significant. */
5531         assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
5532                                       mkU32(1<<where)) );
5533      }
5534   }
5535   return mkexpr(res);
5536}
5537
5538
5539/*
5540  Integer Branch Instructions
5541*/
5542static Bool dis_branch ( UInt theInstr,
5543                         VexAbiInfo* vbi,
5544                         /*OUT*/DisResult* dres,
5545                         Bool (*resteerOkFn)(void*,Addr64),
5546                         void* callback_opaque )
5547{
5548   UChar opc1    = ifieldOPC(theInstr);
5549   UChar BO      = ifieldRegDS(theInstr);
5550   UChar BI      = ifieldRegA(theInstr);
5551   UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
5552   UChar b11to15 = ifieldRegB(theInstr);
5553   UInt  opc2    = ifieldOPClo10(theInstr);
5554   UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
5555   UChar flag_AA = ifieldBIT1(theInstr);
5556   UChar flag_LK = ifieldBIT0(theInstr);
5557
5558   IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
5559   Addr64   tgt       = 0;
5560   Int      BD        = extend_s_16to32(BD_u16);
5561   IRTemp   do_branch = newTemp(Ity_I32);
5562   IRTemp   ctr_ok    = newTemp(Ity_I32);
5563   IRTemp   cond_ok   = newTemp(Ity_I32);
5564   IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
5565   IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
5566   IRTemp   lr_old    = newTemp(ty);
5567
5568   /* Hack to pass through code that just wants to read the PC */
5569   if (theInstr == 0x429F0005) {
5570      DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
5571      putGST( PPC_GST_LR, e_nia );
5572      return True;
5573   }
5574
5575   /* The default what-next.  Individual cases can override it. */
5576   dres->whatNext = Dis_StopHere;
5577   vassert(dres->jk_StopHere == Ijk_INVALID);
5578
5579   switch (opc1) {
5580   case 0x12: // b     (Branch, PPC32 p360)
5581      if (flag_AA) {
5582         tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
5583      } else {
5584         tgt = mkSzAddr( ty, guest_CIA_curr_instr +
5585                             (Long)extend_s_26to64(LI_u26) );
5586      }
5587      if (mode64) {
5588         DIP("b%s%s 0x%llx\n",
5589             flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
5590      } else {
5591         DIP("b%s%s 0x%x\n",
5592             flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
5593      }
5594
5595      if (flag_LK) {
5596         putGST( PPC_GST_LR, e_nia );
5597         if (vbi->guest_ppc_zap_RZ_at_bl
5598             && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
5599            IRTemp t_tgt = newTemp(ty);
5600            assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
5601            make_redzone_AbiHint( vbi, t_tgt,
5602                                  "branch-and-link (unconditional call)" );
5603         }
5604      }
5605
5606      if (resteerOkFn( callback_opaque, tgt )) {
5607         dres->whatNext   = Dis_ResteerU;
5608         dres->continueAt = tgt;
5609      } else {
5610         dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
5611         putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
5612      }
5613      break;
5614
5615   case 0x10: // bc    (Branch Conditional, PPC32 p361)
5616      DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
5617          flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
5618
5619      if (!(BO & 0x4)) {
5620         putGST( PPC_GST_CTR,
5621                 binop(mkSzOp(ty, Iop_Sub8),
5622                       getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5623      }
5624
5625      /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
5626         cond_ok is either zero or nonzero, since that's the cheapest
5627         way to compute it.  Anding them together gives a value which
5628         is either zero or non zero and so that's what we must test
5629         for in the IRStmt_Exit. */
5630      assign( ctr_ok,  branch_ctr_ok( BO ) );
5631      assign( cond_ok, branch_cond_ok( BO, BI ) );
5632      assign( do_branch,
5633              binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5634
5635      if (flag_AA) {
5636         tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
5637      } else {
5638         tgt = mkSzAddr(ty, guest_CIA_curr_instr +
5639                            (Long)extend_s_16to64(BD_u16));
5640      }
5641      if (flag_LK)
5642         putGST( PPC_GST_LR, e_nia );
5643
5644      stmt( IRStmt_Exit(
5645               binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
5646               flag_LK ? Ijk_Call : Ijk_Boring,
5647               mkSzConst(ty, tgt), OFFB_CIA ) );
5648
5649      dres->jk_StopHere = Ijk_Boring;
5650      putGST( PPC_GST_CIA, e_nia );
5651      break;
5652
5653   case 0x13:
5654      /* For bclr and bcctr, it appears that the lowest two bits of
5655         b11to15 are a branch hint, and so we only need to ensure it's
5656         of the form 000XX. */
5657      if ((b11to15 & ~3) != 0) {
5658         vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15);
5659         return False;
5660      }
5661
5662      switch (opc2) {
5663      case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
5664         if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
5665            vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
5666            return False;
5667         }
5668         DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5669
5670         assign( cond_ok, branch_cond_ok( BO, BI ) );
5671
5672         /* FIXME: this is confusing.  lr_old holds the old value
5673            of ctr, not lr :-) */
5674         assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
5675
5676         if (flag_LK)
5677            putGST( PPC_GST_LR, e_nia );
5678
5679         stmt( IRStmt_Exit(
5680                  binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
5681                  Ijk_Boring,
5682                  c_nia, OFFB_CIA ));
5683
5684         if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
5685            make_redzone_AbiHint( vbi, lr_old,
5686                                  "b-ctr-l (indirect call)" );
5687	 }
5688
5689         dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
5690         putGST( PPC_GST_CIA, mkexpr(lr_old) );
5691         break;
5692
5693      case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
5694         Bool vanilla_return = False;
5695         if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
5696            DIP("blr\n");
5697            vanilla_return = True;
5698         } else {
5699            DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5700         }
5701
5702         if (!(BO & 0x4)) {
5703            putGST( PPC_GST_CTR,
5704                    binop(mkSzOp(ty, Iop_Sub8),
5705                          getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5706         }
5707
5708         /* See comments above for 'bc' about this */
5709         assign( ctr_ok,  branch_ctr_ok( BO ) );
5710         assign( cond_ok, branch_cond_ok( BO, BI ) );
5711         assign( do_branch,
5712                 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5713
5714         assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
5715
5716         if (flag_LK)
5717            putGST( PPC_GST_LR,  e_nia );
5718
5719         stmt( IRStmt_Exit(
5720                  binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
5721                  Ijk_Boring,
5722                  c_nia, OFFB_CIA ));
5723
5724         if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
5725            make_redzone_AbiHint( vbi, lr_old,
5726                                  "branch-to-lr (unconditional return)" );
5727         }
5728
5729         /* blrl is pretty strange; it's like a return that sets the
5730            return address of its caller to the insn following this
5731            one.  Mark it as a return. */
5732         dres->jk_StopHere = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
5733         putGST( PPC_GST_CIA, mkexpr(lr_old) );
5734         break;
5735      }
5736      default:
5737         vex_printf("dis_int_branch(ppc)(opc2)\n");
5738         return False;
5739      }
5740      break;
5741
5742   default:
5743      vex_printf("dis_int_branch(ppc)(opc1)\n");
5744      return False;
5745   }
5746
5747   return True;
5748}
5749
5750
5751
5752/*
5753  Condition Register Logical Instructions
5754*/
5755static Bool dis_cond_logic ( UInt theInstr )
5756{
5757   /* XL-Form */
5758   UChar opc1      = ifieldOPC(theInstr);
5759   UChar crbD_addr = ifieldRegDS(theInstr);
5760   UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
5761   UChar crbA_addr = ifieldRegA(theInstr);
5762   UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
5763   UChar crbB_addr = ifieldRegB(theInstr);
5764   UInt  opc2      = ifieldOPClo10(theInstr);
5765   UChar b0        = ifieldBIT0(theInstr);
5766
5767   IRTemp crbD     = newTemp(Ity_I32);
5768   IRTemp crbA     = newTemp(Ity_I32);
5769   IRTemp crbB     = newTemp(Ity_I32);
5770
5771   if (opc1 != 19 || b0 != 0) {
5772      vex_printf("dis_cond_logic(ppc)(opc1)\n");
5773      return False;
5774   }
5775
5776   if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
5777      if (((crbD_addr & 0x3) != 0) ||
5778          ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
5779         vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
5780         return False;
5781      }
5782      DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
5783      putCR0(   crfD_addr, getCR0(  crfS_addr) );
5784      putCR321( crfD_addr, getCR321(crfS_addr) );
5785   } else {
5786      assign( crbA, getCRbit(crbA_addr) );
5787      if (crbA_addr == crbB_addr)
5788         crbB = crbA;
5789      else
5790         assign( crbB, getCRbit(crbB_addr) );
5791
5792      switch (opc2) {
5793      case 0x101: // crand   (Cond Reg AND, PPC32 p372)
5794         DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5795         assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
5796         break;
5797      case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
5798         DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5799         assign( crbD, binop(Iop_And32,
5800                             mkexpr(crbA),
5801                             unop(Iop_Not32, mkexpr(crbB))) );
5802         break;
5803      case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
5804         DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5805         assign( crbD, unop(Iop_Not32,
5806                            binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
5807         break;
5808      case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
5809         DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5810         assign( crbD, unop(Iop_Not32,
5811                            binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
5812         break;
5813      case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
5814         DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5815         assign( crbD, unop(Iop_Not32,
5816                            binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
5817         break;
5818      case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
5819         DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5820         assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
5821         break;
5822      case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
5823         DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5824         assign( crbD, binop(Iop_Or32,
5825                             mkexpr(crbA),
5826                             unop(Iop_Not32, mkexpr(crbB))) );
5827         break;
5828      case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
5829         DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5830         assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
5831         break;
5832      default:
5833         vex_printf("dis_cond_logic(ppc)(opc2)\n");
5834         return False;
5835      }
5836
5837      putCRbit( crbD_addr, mkexpr(crbD) );
5838   }
5839   return True;
5840}
5841
5842
5843/*
5844  Trap instructions
5845*/
5846
5847/* Do the code generation for a trap.  Returned Bool is true iff
5848   this is an unconditional trap.  If the two arg IRExpr*s are
5849   Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
5850   then they are 64-bit, and we must be disassembling 64-bit
5851   instructions. */
5852static Bool do_trap ( UChar TO,
5853                      IRExpr* argL0, IRExpr* argR0, Addr64 cia )
5854{
5855   IRTemp argL, argR;
5856   IRExpr *argLe, *argRe, *cond, *tmp;
5857
5858   Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
5859
5860   IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
5861   IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
5862   IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
5863   IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
5864   IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
5865   IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
5866   IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
5867   IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
5868   IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
5869   IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
5870
5871   const UChar b11100 = 0x1C;
5872   const UChar b00111 = 0x07;
5873
5874   if (is32bit) {
5875      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
5876      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
5877   } else {
5878      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
5879      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
5880      vassert( mode64 );
5881   }
5882
5883   if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
5884      /* Unconditional trap.  Just do the exit without
5885         testing the arguments. */
5886      stmt( IRStmt_Exit(
5887               binop(opCMPEQ, const0, const0),
5888               Ijk_SigTRAP,
5889               mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
5890               OFFB_CIA
5891      ));
5892      return True; /* unconditional trap */
5893   }
5894
5895   if (is32bit) {
5896      argL = newTemp(Ity_I32);
5897      argR = newTemp(Ity_I32);
5898   } else {
5899      argL = newTemp(Ity_I64);
5900      argR = newTemp(Ity_I64);
5901   }
5902
5903   assign( argL, argL0 );
5904   assign( argR, argR0 );
5905
5906   argLe = mkexpr(argL);
5907   argRe = mkexpr(argR);
5908
5909   cond = const0;
5910   if (TO & 16) { // L <s R
5911      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
5912      cond = binop(opOR, tmp, cond);
5913   }
5914   if (TO & 8) { // L >s R
5915      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
5916      cond = binop(opOR, tmp, cond);
5917   }
5918   if (TO & 4) { // L == R
5919      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
5920      cond = binop(opOR, tmp, cond);
5921   }
5922   if (TO & 2) { // L <u R
5923      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
5924      cond = binop(opOR, tmp, cond);
5925   }
5926   if (TO & 1) { // L >u R
5927      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
5928      cond = binop(opOR, tmp, cond);
5929   }
5930   stmt( IRStmt_Exit(
5931            binop(opCMPNE, cond, const0),
5932            Ijk_SigTRAP,
5933            mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
5934            OFFB_CIA
5935   ));
5936   return False; /* not an unconditional trap */
5937}
5938
5939static Bool dis_trapi ( UInt theInstr,
5940                        /*OUT*/DisResult* dres )
5941{
5942   /* D-Form */
5943   UChar  opc1    = ifieldOPC(theInstr);
5944   UChar  TO      = ifieldRegDS(theInstr);
5945   UChar  rA_addr = ifieldRegA(theInstr);
5946   UInt   uimm16  = ifieldUIMM16(theInstr);
5947   ULong  simm16  = extend_s_16to64(uimm16);
5948   Addr64 cia     = guest_CIA_curr_instr;
5949   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5950   Bool   uncond  = False;
5951
5952   switch (opc1) {
5953   case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
5954      uncond = do_trap( TO,
5955                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
5956                               : getIReg(rA_addr),
5957                        mkU32( (UInt)simm16 ),
5958                        cia );
5959      if (TO == 4) {
5960         DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
5961      } else {
5962         DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
5963      }
5964      break;
5965   case 0x02: // tdi
5966      if (!mode64)
5967         return False;
5968      uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
5969      if (TO == 4) {
5970         DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
5971      } else {
5972         DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
5973      }
5974      break;
5975   default:
5976      return False;
5977   }
5978
5979   if (uncond) {
5980      /* If the trap shows signs of being unconditional, don't
5981         continue decoding past it. */
5982      putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
5983      dres->jk_StopHere = Ijk_Boring;
5984      dres->whatNext    = Dis_StopHere;
5985   }
5986
5987   return True;
5988}
5989
5990static Bool dis_trap ( UInt theInstr,
5991                        /*OUT*/DisResult* dres )
5992{
5993   /* X-Form */
5994   UInt   opc2    = ifieldOPClo10(theInstr);
5995   UChar  TO      = ifieldRegDS(theInstr);
5996   UChar  rA_addr = ifieldRegA(theInstr);
5997   UChar  rB_addr = ifieldRegB(theInstr);
5998   Addr64 cia     = guest_CIA_curr_instr;
5999   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
6000   Bool   uncond  = False;
6001
6002   if (ifieldBIT0(theInstr) != 0)
6003      return False;
6004
6005   switch (opc2) {
6006   case 0x004: // tw  (Trap Word, PPC64 p540)
6007      uncond = do_trap( TO,
6008                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
6009                               : getIReg(rA_addr),
6010                        mode64 ? unop(Iop_64to32, getIReg(rB_addr))
6011                               : getIReg(rB_addr),
6012                        cia );
6013      if (TO == 4) {
6014         DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
6015      } else {
6016         DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
6017      }
6018      break;
6019   case 0x044: // td (Trap Doubleword, PPC64 p534)
6020      if (!mode64)
6021         return False;
6022      uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
6023      if (TO == 4) {
6024         DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
6025      } else {
6026         DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
6027      }
6028      break;
6029   default:
6030      return False;
6031   }
6032
6033   if (uncond) {
6034      /* If the trap shows signs of being unconditional, don't
6035         continue decoding past it. */
6036      putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6037      dres->jk_StopHere = Ijk_Boring;
6038      dres->whatNext    = Dis_StopHere;
6039   }
6040
6041   return True;
6042}
6043
6044
6045/*
6046  System Linkage Instructions
6047*/
6048static Bool dis_syslink ( UInt theInstr,
6049                          VexAbiInfo* abiinfo, DisResult* dres )
6050{
6051   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6052
6053   if (theInstr != 0x44000002) {
6054      vex_printf("dis_syslink(ppc)(theInstr)\n");
6055      return False;
6056   }
6057
6058   // sc  (System Call, PPC32 p504)
6059   DIP("sc\n");
6060
6061   /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX
6062      Valgrind can back the guest up to this instruction if it needs
6063      to restart the syscall. */
6064   putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
6065
6066   /* It's important that all ArchRegs carry their up-to-date value
6067      at this point.  So we declare an end-of-block here, which
6068      forces any TempRegs caching ArchRegs to be flushed. */
6069   putGST( PPC_GST_CIA, abiinfo->guest_ppc_sc_continues_at_LR
6070                        ? getGST( PPC_GST_LR )
6071                        : mkSzImm( ty, nextInsnAddr() ));
6072
6073   dres->whatNext    = Dis_StopHere;
6074   dres->jk_StopHere = Ijk_Sys_syscall;
6075   return True;
6076}
6077
6078
6079/*
6080  Memory Synchronization Instructions
6081
6082  Note on Reservations:
6083  We rely on the assumption that V will in fact only allow one thread at
6084  once to run.  In effect, a thread can make a reservation, but we don't
6085  check any stores it does.  Instead, the reservation is cancelled when
6086  the scheduler switches to another thread (run_thread_for_a_while()).
6087*/
6088static Bool dis_memsync ( UInt theInstr )
6089{
6090   /* X-Form, XL-Form */
6091   UChar opc1    = ifieldOPC(theInstr);
6092   UInt  b11to25 = IFIELD(theInstr, 11, 15);
6093   UChar flag_L  = ifieldRegDS(theInstr);
6094   UInt  b11to20 = IFIELD(theInstr, 11, 10);
6095   UChar rD_addr = ifieldRegDS(theInstr);
6096   UChar rS_addr = rD_addr;
6097   UChar rA_addr = ifieldRegA(theInstr);
6098   UChar rB_addr = ifieldRegB(theInstr);
6099   UInt  opc2    = ifieldOPClo10(theInstr);
6100   UChar b0      = ifieldBIT0(theInstr);
6101
6102   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6103   IRTemp EA     = newTemp(ty);
6104
6105   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6106
6107   switch (opc1) {
6108   /* XL-Form */
6109   case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
6110      if (opc2 != 0x096) {
6111         vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
6112         return False;
6113      }
6114      if (b11to25 != 0 || b0 != 0) {
6115         vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
6116         return False;
6117      }
6118      DIP("isync\n");
6119      stmt( IRStmt_MBE(Imbe_Fence) );
6120      break;
6121
6122   /* X-Form */
6123   case 0x1F:
6124      switch (opc2) {
6125      case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394)
6126         if (b11to25 != 0 || b0 != 0) {
6127            vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n");
6128            return False;
6129         }
6130         DIP("eieio\n");
6131         /* Insert a memory fence, just to be on the safe side. */
6132         stmt( IRStmt_MBE(Imbe_Fence) );
6133         break;
6134
6135      case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
6136         IRTemp res;
6137         /* According to the PowerPC ISA version 2.05, b0 (called EH
6138            in the documentation) is merely a hint bit to the
6139            hardware, I think as to whether or not contention is
6140            likely.  So we can just ignore it. */
6141         DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
6142
6143         // trap if misaligned
6144         gen_SIGBUS_if_misaligned( EA, 4 );
6145
6146         // and actually do the load
6147         res = newTemp(Ity_I32);
6148         stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
6149
6150         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
6151         break;
6152      }
6153
6154      case 0x096: {
6155         // stwcx. (Store Word Conditional Indexed, PPC32 p532)
6156         // Note this has to handle stwcx. in both 32- and 64-bit modes,
6157         // so isn't quite as straightforward as it might otherwise be.
6158         IRTemp rS = newTemp(Ity_I32);
6159         IRTemp resSC;
6160         if (b0 != 1) {
6161            vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
6162            return False;
6163         }
6164         DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6165
6166         // trap if misaligned
6167         gen_SIGBUS_if_misaligned( EA, 4 );
6168
6169         // Get the data to be stored, and narrow to 32 bits if necessary
6170         assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
6171
6172         // Do the store, and get success/failure bit into resSC
6173         resSC = newTemp(Ity_I1);
6174         stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
6175
6176         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6177         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6178         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6179         putCR0(0, getXER_SO());
6180
6181         /* Note:
6182            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6183            whether rS is stored is dependent on that value. */
6184         /* So I guess we can just ignore this case? */
6185         break;
6186      }
6187
6188      case 0x256: // sync (Synchronize, PPC32 p543),
6189                  // also lwsync (L==1), ptesync (L==2)
6190         /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
6191
6192            The PowerPC architecture used in IBM chips has expanded
6193            the sync instruction into two variants: lightweight sync
6194            and heavyweight sync.  The original sync instruction is
6195            the new heavyweight sync and lightweight sync is a strict
6196            subset of the heavyweight sync functionality. This allows
6197            the programmer to specify a less expensive operation on
6198            high-end systems when the full sync functionality is not
6199            necessary.
6200
6201            The basic "sync" mnemonic now utilizes an operand. "sync"
6202            without an operand now becomes a extended mnemonic for
6203            heavyweight sync.  Processors without the lwsync
6204            instruction will not decode the L field and will perform a
6205            heavyweight sync.  Everything is backward compatible.
6206
6207            sync    =       sync 0
6208            lwsync  =       sync 1
6209            ptesync =       sync 2    *** TODO - not implemented ***
6210         */
6211         if (b11to20 != 0 || b0 != 0) {
6212            vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
6213            return False;
6214         }
6215         if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
6216            vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
6217            return False;
6218         }
6219         DIP("%ssync\n", flag_L == 1 ? "lw" : "");
6220         /* Insert a memory fence.  It's sometimes important that these
6221            are carried through to the generated code. */
6222         stmt( IRStmt_MBE(Imbe_Fence) );
6223         break;
6224
6225      /* 64bit Memsync */
6226      case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
6227         IRTemp res;
6228         /* According to the PowerPC ISA version 2.05, b0 (called EH
6229            in the documentation) is merely a hint bit to the
6230            hardware, I think as to whether or not contention is
6231            likely.  So we can just ignore it. */
6232         if (!mode64)
6233            return False;
6234         DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
6235
6236         // trap if misaligned
6237         gen_SIGBUS_if_misaligned( EA, 8 );
6238
6239         // and actually do the load
6240         res = newTemp(Ity_I64);
6241         stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
6242
6243         putIReg( rD_addr, mkexpr(res) );
6244         break;
6245      }
6246
6247      case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
6248         // A marginally simplified version of the stwcx. case
6249         IRTemp rS = newTemp(Ity_I64);
6250         IRTemp resSC;
6251         if (b0 != 1) {
6252            vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
6253            return False;
6254         }
6255         if (!mode64)
6256            return False;
6257         DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6258
6259         // trap if misaligned
6260         gen_SIGBUS_if_misaligned( EA, 8 );
6261
6262         // Get the data to be stored
6263         assign( rS, getIReg(rS_addr) );
6264
6265         // Do the store, and get success/failure bit into resSC
6266         resSC = newTemp(Ity_I1);
6267         stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
6268
6269         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6270         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6271         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6272         putCR0(0, getXER_SO());
6273
6274         /* Note:
6275            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6276            whether rS is stored is dependent on that value. */
6277         /* So I guess we can just ignore this case? */
6278         break;
6279      }
6280
6281      /* 128bit Memsync */
6282      case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
6283         IRTemp res_hi = newTemp(ty);
6284         IRTemp res_lo = newTemp(ty);
6285
6286         /* According to the PowerPC ISA version 2.07, b0 (called EH
6287            in the documentation) is merely a hint bit to the
6288            hardware, I think as to whether or not contention is
6289            likely.  So we can just ignore it. */
6290         DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
6291
6292         // trap if misaligned
6293         gen_SIGBUS_if_misaligned( EA, 16 );
6294
6295         // and actually do the load
6296         if (mode64) {
6297            stmt( IRStmt_LLSC( Iend_BE, res_hi,
6298                               mkexpr(EA), NULL/*this is a load*/) );
6299            stmt( IRStmt_LLSC( Iend_BE, res_lo,
6300                               binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
6301                               NULL/*this is a load*/) );
6302         } else {
6303            stmt( IRStmt_LLSC( Iend_BE, res_hi,
6304                               binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
6305                               NULL/*this is a load*/) );
6306            stmt( IRStmt_LLSC( Iend_BE, res_lo,
6307                               binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
6308                               NULL/*this is a load*/) );
6309         }
6310         putIReg( rD_addr,   mkexpr(res_hi) );
6311         putIReg( rD_addr+1, mkexpr(res_lo) );
6312         break;
6313      }
6314
6315      case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
6316         // A marginally simplified version of the stwcx. case
6317         IRTemp rS_hi = newTemp(ty);
6318         IRTemp rS_lo = newTemp(ty);
6319         IRTemp resSC;
6320         if (b0 != 1) {
6321            vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
6322            return False;
6323         }
6324
6325         DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6326
6327         // trap if misaligned
6328         gen_SIGBUS_if_misaligned( EA, 16 );
6329         // Get the data to be stored
6330         assign( rS_hi, getIReg(rS_addr) );
6331         assign( rS_lo, getIReg(rS_addr+1) );
6332
6333         // Do the store, and get success/failure bit into resSC
6334         resSC = newTemp(Ity_I1);
6335
6336         if (mode64) {
6337            stmt( IRStmt_LLSC( Iend_BE, resSC, mkexpr(EA), mkexpr(rS_hi) ) );
6338            storeBE(binop( Iop_Add64, mkexpr(EA), mkU64(8) ), mkexpr(rS_lo) );
6339         } else {
6340            stmt( IRStmt_LLSC( Iend_BE, resSC, binop( Iop_Add32,
6341                                                      mkexpr(EA),
6342                                                      mkU32(4) ),
6343                                                      mkexpr(rS_hi) ) );
6344            storeBE(binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
6345         }
6346
6347         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6348         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6349         putCR321(0, binop( Iop_Shl8,
6350                            unop(Iop_1Uto8, mkexpr(resSC) ),
6351                            mkU8(1)));
6352         putCR0(0, getXER_SO());
6353         break;
6354      }
6355
6356      default:
6357         vex_printf("dis_memsync(ppc)(opc2)\n");
6358         return False;
6359      }
6360      break;
6361
6362   default:
6363      vex_printf("dis_memsync(ppc)(opc1)\n");
6364      return False;
6365   }
6366   return True;
6367}
6368
6369
6370
6371/*
6372  Integer Shift Instructions
6373*/
6374static Bool dis_int_shift ( UInt theInstr )
6375{
6376   /* X-Form, XS-Form */
6377   UChar opc1    = ifieldOPC(theInstr);
6378   UChar rS_addr = ifieldRegDS(theInstr);
6379   UChar rA_addr = ifieldRegA(theInstr);
6380   UChar rB_addr = ifieldRegB(theInstr);
6381   UChar sh_imm  = rB_addr;
6382   UInt  opc2    = ifieldOPClo10(theInstr);
6383   UChar b1      = ifieldBIT1(theInstr);
6384   UChar flag_rC = ifieldBIT0(theInstr);
6385
6386   IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
6387   IRTemp  rA         = newTemp(ty);
6388   IRTemp  rS         = newTemp(ty);
6389   IRTemp  rB         = newTemp(ty);
6390   IRTemp  outofrange = newTemp(Ity_I1);
6391   IRTemp  rS_lo32    = newTemp(Ity_I32);
6392   IRTemp  rB_lo32    = newTemp(Ity_I32);
6393   IRExpr* e_tmp;
6394
6395   assign( rS, getIReg(rS_addr) );
6396   assign( rB, getIReg(rB_addr) );
6397   assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
6398   assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
6399
6400   if (opc1 == 0x1F) {
6401      switch (opc2) {
6402      case 0x018: { // slw (Shift Left Word, PPC32 p505)
6403         DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6404             rA_addr, rS_addr, rB_addr);
6405         /* rA = rS << rB */
6406         /* ppc32 semantics are:
6407            slw(x,y) = (x << (y & 31))         -- primary result
6408                       & ~((y << 26) >>s 31)   -- make result 0
6409                                                  for y in 32 .. 63
6410         */
6411         e_tmp =
6412            binop( Iop_And32,
6413               binop( Iop_Shl32,
6414                      mkexpr(rS_lo32),
6415                      unop( Iop_32to8,
6416                            binop(Iop_And32,
6417                                  mkexpr(rB_lo32), mkU32(31)))),
6418               unop( Iop_Not32,
6419                     binop( Iop_Sar32,
6420                            binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
6421                            mkU8(31))) );
6422         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6423         break;
6424      }
6425
6426      case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
6427         IRTemp sh_amt = newTemp(Ity_I32);
6428         DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6429             rA_addr, rS_addr, rB_addr);
6430         /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
6431            amt = rB & 63
6432            rA = Sar32( rS, amt > 31 ? 31 : amt )
6433            XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
6434         */
6435         assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
6436                                          mkexpr(rB_lo32)) );
6437         assign( outofrange,
6438                 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) );
6439         e_tmp = binop( Iop_Sar32,
6440                        mkexpr(rS_lo32),
6441                        unop( Iop_32to8,
6442                              IRExpr_ITE( mkexpr(outofrange),
6443                                          mkU32(31),
6444                                          mkexpr(sh_amt)) ) );
6445         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
6446
6447         set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
6448                     mkexpr(rA),
6449                     mkWidenFrom32(ty, mkexpr(rS_lo32), True),
6450                     mkWidenFrom32(ty, mkexpr(sh_amt), True ),
6451                     mkWidenFrom32(ty, getXER_CA32(), True) );
6452         break;
6453      }
6454
6455      case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
6456         DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
6457             rA_addr, rS_addr, sh_imm);
6458         vassert(sh_imm < 32);
6459         if (mode64) {
6460            assign( rA, binop(Iop_Sar64,
6461                              binop(Iop_Shl64, getIReg(rS_addr),
6462                                               mkU8(32)),
6463                              mkU8(32 + sh_imm)) );
6464         } else {
6465            assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
6466                                         mkU8(sh_imm)) );
6467         }
6468
6469         set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
6470                     mkexpr(rA),
6471                     mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
6472                     mkSzImm(ty, sh_imm),
6473                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6474         break;
6475
6476      case 0x218: // srw (Shift Right Word, PPC32 p508)
6477         DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6478             rA_addr, rS_addr, rB_addr);
6479         /* rA = rS >>u rB */
6480         /* ppc32 semantics are:
6481            srw(x,y) = (x >>u (y & 31))        -- primary result
6482                       & ~((y << 26) >>s 31)   -- make result 0
6483                                                  for y in 32 .. 63
6484         */
6485         e_tmp =
6486            binop(
6487               Iop_And32,
6488               binop( Iop_Shr32,
6489                      mkexpr(rS_lo32),
6490                      unop( Iop_32to8,
6491                            binop(Iop_And32, mkexpr(rB_lo32),
6492                                             mkU32(31)))),
6493               unop( Iop_Not32,
6494                     binop( Iop_Sar32,
6495                            binop(Iop_Shl32, mkexpr(rB_lo32),
6496                                             mkU8(26)),
6497                            mkU8(31))));
6498         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6499         break;
6500
6501
6502      /* 64bit Shifts */
6503      case 0x01B: // sld (Shift Left DWord, PPC64 p568)
6504         DIP("sld%s r%u,r%u,r%u\n",
6505             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6506         /* rA = rS << rB */
6507         /* ppc64 semantics are:
6508            slw(x,y) = (x << (y & 63))         -- primary result
6509                       & ~((y << 57) >>s 63)   -- make result 0
6510                                                  for y in 64 ..
6511         */
6512         assign( rA,
6513            binop(
6514               Iop_And64,
6515               binop( Iop_Shl64,
6516                      mkexpr(rS),
6517                      unop( Iop_64to8,
6518                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6519               unop( Iop_Not64,
6520                     binop( Iop_Sar64,
6521                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6522                            mkU8(63)))) );
6523         break;
6524
6525      case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
6526         IRTemp sh_amt = newTemp(Ity_I64);
6527         DIP("srad%s r%u,r%u,r%u\n",
6528             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6529         /* amt = rB & 127
6530            rA = Sar64( rS, amt > 63 ? 63 : amt )
6531            XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
6532         */
6533         assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
6534         assign( outofrange,
6535                 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) );
6536         assign( rA,
6537                 binop( Iop_Sar64,
6538                        mkexpr(rS),
6539                        unop( Iop_64to8,
6540                              IRExpr_ITE( mkexpr(outofrange),
6541                                          mkU64(63),
6542                                          mkexpr(sh_amt)) ))
6543               );
6544         set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
6545                     mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
6546                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6547         break;
6548      }
6549
6550      case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
6551         sh_imm |= b1<<5;
6552         vassert(sh_imm < 64);
6553         DIP("sradi%s r%u,r%u,%u\n",
6554             flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
6555         assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
6556
6557         set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
6558                     mkexpr(rA),
6559                     getIReg(rS_addr),
6560                     mkU64(sh_imm),
6561                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6562         break;
6563
6564      case 0x21B: // srd (Shift Right DWord, PPC64 p574)
6565         DIP("srd%s r%u,r%u,r%u\n",
6566             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6567         /* rA = rS >>u rB */
6568         /* ppc semantics are:
6569            srw(x,y) = (x >>u (y & 63))        -- primary result
6570                       & ~((y << 57) >>s 63)   -- make result 0
6571                                                  for y in 64 .. 127
6572         */
6573         assign( rA,
6574            binop(
6575               Iop_And64,
6576               binop( Iop_Shr64,
6577                      mkexpr(rS),
6578                      unop( Iop_64to8,
6579                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6580               unop( Iop_Not64,
6581                     binop( Iop_Sar64,
6582                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6583                            mkU8(63)))) );
6584         break;
6585
6586      default:
6587         vex_printf("dis_int_shift(ppc)(opc2)\n");
6588         return False;
6589      }
6590   } else {
6591      vex_printf("dis_int_shift(ppc)(opc1)\n");
6592      return False;
6593   }
6594
6595   putIReg( rA_addr, mkexpr(rA) );
6596
6597   if (flag_rC) {
6598      set_CR0( mkexpr(rA) );
6599   }
6600   return True;
6601}
6602
6603
6604
6605/*
6606  Integer Load/Store Reverse Instructions
6607*/
6608/* Generates code to swap the byte order in an Ity_I32. */
6609static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
6610{
6611   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
6612   return
6613      binop(Iop_Or32,
6614         binop(Iop_Shl32, mkexpr(t), mkU8(24)),
6615      binop(Iop_Or32,
6616         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
6617                          mkU32(0x00FF0000)),
6618      binop(Iop_Or32,
6619         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
6620                          mkU32(0x0000FF00)),
6621         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
6622                          mkU32(0x000000FF) )
6623      )));
6624}
6625
6626/* Generates code to swap the byte order in the lower half of an Ity_I32,
6627   and zeroes the upper half. */
6628static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
6629{
6630   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
6631   return
6632      binop(Iop_Or32,
6633         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
6634                          mkU32(0x0000FF00)),
6635         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
6636                          mkU32(0x000000FF))
6637      );
6638}
6639
6640static Bool dis_int_ldst_rev ( UInt theInstr )
6641{
6642   /* X-Form */
6643   UChar opc1    = ifieldOPC(theInstr);
6644   UChar rD_addr = ifieldRegDS(theInstr);
6645   UChar rS_addr = rD_addr;
6646   UChar rA_addr = ifieldRegA(theInstr);
6647   UChar rB_addr = ifieldRegB(theInstr);
6648   UInt  opc2    = ifieldOPClo10(theInstr);
6649   UChar b0      = ifieldBIT0(theInstr);
6650
6651   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6652   IRTemp EA = newTemp(ty);
6653   IRTemp w1 = newTemp(Ity_I32);
6654   IRTemp w2 = newTemp(Ity_I32);
6655
6656   if (opc1 != 0x1F || b0 != 0) {
6657      vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
6658      return False;
6659   }
6660
6661   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6662
6663   switch (opc2) {
6664
6665      case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
6666         DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
6667         assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) );
6668         assign( w2, gen_byterev16(w1) );
6669         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
6670                                         /* Signed */False) );
6671         break;
6672
6673      case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
6674         DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
6675         assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
6676         assign( w2, gen_byterev32(w1) );
6677         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
6678                                         /* Signed */False) );
6679         break;
6680
6681      case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
6682      {
6683         IRExpr * nextAddr;
6684         IRTemp w3 = newTemp( Ity_I32 );
6685         IRTemp w4 = newTemp( Ity_I32 );
6686         DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
6687         assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) );
6688         assign( w2, gen_byterev32( w1 ) );
6689         nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
6690                           ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
6691         assign( w3, loadBE( Ity_I32, nextAddr ) );
6692         assign( w4, gen_byterev32( w3 ) );
6693         putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
6694         break;
6695      }
6696
6697      case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
6698         DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6699         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
6700         storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
6701         break;
6702
6703      case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
6704         DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6705         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
6706         storeBE( mkexpr(EA), gen_byterev32(w1) );
6707         break;
6708
6709      case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
6710      {
6711         IRTemp lo = newTemp(Ity_I32);
6712         IRTemp hi = newTemp(Ity_I32);
6713         IRTemp rS = newTemp(Ity_I64);
6714         assign( rS, getIReg( rS_addr ) );
6715         DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6716         assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
6717         assign(hi, unop(Iop_64to32, mkexpr(rS)));
6718         storeBE( mkexpr( EA ),
6719                  binop( Iop_32HLto64, gen_byterev32( hi ), gen_byterev32( lo ) ) );
6720         break;
6721      }
6722
6723      default:
6724         vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
6725         return False;
6726   }
6727   return True;
6728}
6729
6730
6731
6732/*
6733  Processor Control Instructions
6734*/
6735static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr )
6736{
6737   UChar opc1     = ifieldOPC(theInstr);
6738
6739   /* X-Form */
6740   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
6741   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
6742   UChar rD_addr  = ifieldRegDS(theInstr);
6743   UInt  b11to20  = IFIELD( theInstr, 11, 10 );
6744
6745   /* XFX-Form */
6746   UChar rS_addr  = rD_addr;
6747   UInt  SPR      = b11to20;
6748   UInt  TBR      = b11to20;
6749   UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
6750   UInt  CRM      = IFIELD( theInstr, 12, 8 );
6751   UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
6752
6753   UInt  opc2     = ifieldOPClo10(theInstr);
6754   UChar b0       = ifieldBIT0(theInstr);
6755
6756   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6757   IRTemp rS = newTemp(ty);
6758   assign( rS, getIReg(rS_addr) );
6759
6760   /* Reorder SPR field as per PPC32 p470 */
6761   SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
6762   /* Reorder TBR field as per PPC32 p475 */
6763   TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
6764
6765   /* b0 = 0, inst is treated as floating point inst for reservation purposes
6766    * b0 = 1, inst is treated as vector inst for reservation purposes
6767    */
6768   if (opc1 != 0x1F) {
6769      vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0);
6770      return False;
6771   }
6772
6773   switch (opc2) {
6774   /* X-Form */
6775   case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
6776      if (b21to22 != 0 || b11to20 != 0) {
6777         vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
6778         return False;
6779      }
6780      DIP("mcrxr crf%d\n", crfD);
6781      /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
6782      putGST_field( PPC_GST_CR,
6783                    getGST_field( PPC_GST_XER, 7 ),
6784                    crfD );
6785
6786      // Clear XER[0-3]
6787      putXER_SO( mkU8(0) );
6788      putXER_OV( mkU8(0) );
6789      putXER_CA( mkU8(0) );
6790      break;
6791   }
6792
6793   case 0x013:
6794      // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
6795      // b20==1 & b11==0: mfocrf (Move from One CR Field)
6796      // However it seems that the 'mfcr' behaviour is an acceptable
6797      // implementation of mfocr (from the 2.02 arch spec)
6798      if (b11to20 == 0) {
6799         DIP("mfcr r%u\n", rD_addr);
6800         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
6801                                         /* Signed */False) );
6802         break;
6803      }
6804      if (b20 == 1 && b11 == 0) {
6805         DIP("mfocrf r%u,%u\n", rD_addr, CRM);
6806         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
6807                                         /* Signed */False) );
6808         break;
6809      }
6810      /* not decodable */
6811      return False;
6812
6813   /* XFX-Form */
6814   case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
6815
6816      switch (SPR) {  // Choose a register...
6817      case 0x1:
6818         DIP("mfxer r%u\n", rD_addr);
6819         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
6820                                         /* Signed */False) );
6821         break;
6822      case 0x8:
6823         DIP("mflr r%u\n", rD_addr);
6824         putIReg( rD_addr, getGST( PPC_GST_LR ) );
6825         break;
6826      case 0x9:
6827         DIP("mfctr r%u\n", rD_addr);
6828         putIReg( rD_addr, getGST( PPC_GST_CTR ) );
6829         break;
6830      case 0x80:  // 128
6831         DIP("mfspr r%u (TFHAR)\n", rD_addr);
6832         putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
6833         break;
6834      case 0x81:  // 129
6835         DIP("mfspr r%u (TFIAR)\n", rD_addr);
6836         putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
6837         break;
6838      case 0x82:  // 130
6839         DIP("mfspr r%u (TEXASR)\n", rD_addr);
6840         putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
6841         break;
6842      case 0x100:
6843         DIP("mfvrsave r%u\n", rD_addr);
6844         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
6845                                         /* Signed */False) );
6846         break;
6847
6848      case 0x103:
6849         DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
6850         putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
6851         break;
6852
6853      /* Even a lowly PPC7400 can run the associated helper, so no
6854         obvious need for feature testing at this point. */
6855      case 268 /* 0x10C */:
6856      case 269 /* 0x10D */: {
6857         UInt     arg  = SPR==268 ? 0 : 1;
6858         IRTemp   val  = newTemp(Ity_I32);
6859         IRExpr** args = mkIRExprVec_1( mkU32(arg) );
6860         IRDirty* d    = unsafeIRDirty_1_N(
6861                            val,
6862                            0/*regparms*/,
6863                            "ppc32g_dirtyhelper_MFSPR_268_269",
6864                            fnptr_to_fnentry
6865                               (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
6866                            args
6867                         );
6868         /* execute the dirty call, dumping the result in val. */
6869         stmt( IRStmt_Dirty(d) );
6870         putIReg( rD_addr,
6871                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
6872         DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
6873         break;
6874      }
6875
6876      /* Again, runs natively on PPC7400 (7447, really).  Not
6877         bothering with a feature test. */
6878      case 287: /* 0x11F */ {
6879         IRTemp   val  = newTemp(Ity_I32);
6880         IRExpr** args = mkIRExprVec_0();
6881         IRDirty* d    = unsafeIRDirty_1_N(
6882                            val,
6883                            0/*regparms*/,
6884                            "ppc32g_dirtyhelper_MFSPR_287",
6885                            fnptr_to_fnentry
6886                               (vbi, &ppc32g_dirtyhelper_MFSPR_287),
6887                            args
6888                         );
6889         /* execute the dirty call, dumping the result in val. */
6890         stmt( IRStmt_Dirty(d) );
6891         putIReg( rD_addr,
6892                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
6893         DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
6894         break;
6895      }
6896
6897      default:
6898         vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
6899         return False;
6900      }
6901      break;
6902
6903   case 0x173: { // mftb (Move from Time Base, PPC32 p475)
6904      IRTemp   val  = newTemp(Ity_I64);
6905      IRExpr** args = mkIRExprVec_0();
6906      IRDirty* d    = unsafeIRDirty_1_N(
6907                              val,
6908                              0/*regparms*/,
6909                              "ppcg_dirtyhelper_MFTB",
6910                              fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
6911                              args );
6912      /* execute the dirty call, dumping the result in val. */
6913      stmt( IRStmt_Dirty(d) );
6914
6915      switch (TBR) {
6916      case 269:
6917         DIP("mftbu r%u", rD_addr);
6918         putIReg( rD_addr,
6919                  mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
6920                                /* Signed */False) );
6921         break;
6922      case 268:
6923         DIP("mftb r%u", rD_addr);
6924         putIReg( rD_addr, (mode64) ? mkexpr(val) :
6925                                      unop(Iop_64to32, mkexpr(val)) );
6926         break;
6927      default:
6928         return False; /* illegal instruction */
6929      }
6930      break;
6931   }
6932
6933   case 0x090: {
6934      // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
6935      // b20==1: mtocrf (Move to One Cond Reg Field)
6936      Int   cr;
6937      UChar shft;
6938      if (b11 != 0)
6939         return False;
6940      if (b20 == 1) {
6941         /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
6942            1 field is written.  It seems more robust to decline to
6943            decode the insn if so. */
6944         switch (CRM) {
6945            case 0x01: case 0x02: case 0x04: case 0x08:
6946            case 0x10: case 0x20: case 0x40: case 0x80:
6947               break;
6948            default:
6949               return False;
6950         }
6951      }
6952      DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
6953                           CRM, rS_addr);
6954      /* Write to each field specified by CRM */
6955      for (cr = 0; cr < 8; cr++) {
6956         if ((CRM & (1 << (7-cr))) == 0)
6957            continue;
6958         shft = 4*(7-cr);
6959         putGST_field( PPC_GST_CR,
6960                       binop(Iop_Shr32,
6961                             mkNarrowTo32(ty, mkexpr(rS)),
6962                             mkU8(shft)), cr );
6963      }
6964      break;
6965   }
6966
6967   case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
6968
6969      switch (SPR) {  // Choose a register...
6970      case 0x1:
6971         DIP("mtxer r%u\n", rS_addr);
6972         putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
6973         break;
6974      case 0x8:
6975         DIP("mtlr r%u\n", rS_addr);
6976         putGST( PPC_GST_LR, mkexpr(rS) );
6977         break;
6978      case 0x9:
6979         DIP("mtctr r%u\n", rS_addr);
6980         putGST( PPC_GST_CTR, mkexpr(rS) );
6981         break;
6982      case 0x100:
6983         DIP("mtvrsave r%u\n", rS_addr);
6984         putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
6985         break;
6986      case 0x80:  // 128
6987         DIP("mtspr r%u (TFHAR)\n", rS_addr);
6988         putGST( PPC_GST_TFHAR, mkexpr(rS) );
6989         break;
6990      case 0x81:  // 129
6991         DIP("mtspr r%u (TFIAR)\n", rS_addr);
6992         putGST( PPC_GST_TFIAR, mkexpr(rS) );
6993         break;
6994      case 0x82:  // 130
6995         DIP("mtspr r%u (TEXASR)\n", rS_addr);
6996         putGST( PPC_GST_TEXASR, mkexpr(rS) );
6997         break;
6998      default:
6999         vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
7000         return False;
7001      }
7002      break;
7003
7004   case 0x33:                // mfvsrd
7005   {
7006      UChar XS = ifieldRegXS( theInstr );
7007      UChar rA_addr = ifieldRegA(theInstr);
7008      IRExpr * high64;
7009      IRTemp vS = newTemp( Ity_V128 );
7010      DIP("mfvsrd r%u,vsr%d\n", rA_addr, (UInt)XS);
7011
7012      /*  XS = SX || S
7013       *  For SX=0, mfvsrd is treated as a Floating-Point
7014       *            instruction in terms of resource availability.
7015       *  For SX=1, mfvsrd is treated as a Vector instruction in
7016       *            terms of resource availability.
7017       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7018       */
7019      assign( vS, getVSReg( XS ) );
7020      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
7021      putIReg( rA_addr, (mode64) ? high64 :
7022      unop( Iop_64to32, high64 ) );
7023      break;
7024   }
7025
7026   case 0x73:                // mfvsrwz
7027   {
7028      UChar XS = ifieldRegXS( theInstr );
7029      UChar rA_addr = ifieldRegA(theInstr);
7030      IRExpr * high64;
7031      IRTemp vS = newTemp( Ity_V128 );
7032      DIP("mfvsrwz r%u,vsr%d\n", rA_addr, (UInt)XS);
7033      /*  XS = SX || S
7034       *  For SX=0, mfvsrwz is treated as a Floating-Point
7035       *            instruction in terms of resource availability.
7036       *  For SX=1, mfvsrwz is treated as a Vector instruction in
7037       *            terms of resource availability.
7038       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7039       */
7040
7041      assign( vS, getVSReg( XS ) );
7042      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
7043      /* move value to the destination setting the upper 32-bits to zero */
7044      putIReg( rA_addr, (mode64) ?
7045                                  binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) :
7046                                  unop(  Iop_64to32,
7047                                         binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
7048      break;
7049   }
7050
7051   case 0xB3:                // mtvsrd
7052   {
7053      UChar XT = ifieldRegXT( theInstr );
7054      UChar rA_addr = ifieldRegA(theInstr);
7055      IRTemp rA = newTemp(ty);
7056      DIP("mtvsrd vsr%d,r%u\n", (UInt)XT, rA_addr);
7057      /*  XS = SX || S
7058       *  For SX=0, mfvsrd is treated as a Floating-Point
7059       *            instruction in terms of resource availability.
7060       *  For SX=1, mfvsrd is treated as a Vector instruction in
7061       *            terms of resource availability.
7062       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7063       */
7064      assign( rA, getIReg(rA_addr) );
7065
7066      if (mode64)
7067         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
7068      else
7069         putVSReg( XT, binop( Iop_64HLtoV128,
7070                              binop( Iop_32HLto64,
7071                                     mkU32( 0 ),
7072                                     mkexpr( rA ) ),
7073                                     mkU64( 0 ) ) );
7074      break;
7075   }
7076
7077   case 0xD3:                // mtvsrwa
7078   {
7079      UChar XT = ifieldRegXT( theInstr );
7080      UChar rA_addr = ifieldRegA(theInstr);
7081      IRTemp rA = newTemp( Ity_I32 );
7082      DIP("mtvsrwa vsr%d,r%u\n", (UInt)XT, rA_addr);
7083      /*  XS = SX || S
7084       *  For SX=0, mtvsrwa is treated as a Floating-Point
7085       *            instruction in terms of resource availability.
7086       *  For SX=1, mtvsrwa is treated as a Vector instruction in
7087       *            terms of resource availability.
7088       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7089       */
7090      if (mode64)
7091         assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
7092      else
7093         assign( rA, getIReg(rA_addr) );
7094
7095      putVSReg( XT, binop( Iop_64HLtoV128,
7096                           unop( Iop_32Sto64, mkexpr( rA ) ),
7097                           mkU64( 0 ) ) );
7098      break;
7099   }
7100
7101   case 0xF3:                // mtvsrwz
7102      {
7103         UChar XT = ifieldRegXT( theInstr );
7104         UChar rA_addr = ifieldRegA(theInstr);
7105         IRTemp rA = newTemp( Ity_I32 );
7106         DIP("mtvsrwz vsr%d,r%u\n", rA_addr, (UInt)XT);
7107         /*  XS = SX || S
7108          *  For SX=0, mtvsrwz is treated as a Floating-Point
7109          *            instruction in terms of resource availability.
7110          *  For SX=1, mtvsrwz is treated as a Vector instruction in
7111          *            terms of resource availability.
7112          * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7113          */
7114         if (mode64)
7115             assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
7116         else
7117             assign( rA, getIReg(rA_addr) );
7118
7119         putVSReg( XT, binop( Iop_64HLtoV128,
7120                              binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
7121                              mkU64( 0 ) ) );
7122         break;
7123      }
7124
7125   default:
7126      vex_printf("dis_proc_ctl(ppc)(opc2)\n");
7127      return False;
7128   }
7129   return True;
7130}
7131
7132
7133/*
7134  Cache Management Instructions
7135*/
7136static Bool dis_cache_manage ( UInt         theInstr,
7137                               DisResult*   dres,
7138                               VexArchInfo* guest_archinfo )
7139{
7140   /* X-Form */
7141   UChar opc1    = ifieldOPC(theInstr);
7142   UChar b21to25 = ifieldRegDS(theInstr);
7143   UChar rA_addr = ifieldRegA(theInstr);
7144   UChar rB_addr = ifieldRegB(theInstr);
7145   UInt  opc2    = ifieldOPClo10(theInstr);
7146   UChar b0      = ifieldBIT0(theInstr);
7147   UInt  lineszB = guest_archinfo->ppc_icache_line_szB;
7148   Bool  is_dcbzl = False;
7149
7150   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
7151
7152   // Check for valid hint values for dcbt and dcbtst as currently described in
7153   // ISA 2.07.  If valid, then we simply set b21to25 to zero since we have no
7154   // means of modeling the hint anyway.
7155   if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) {
7156      if (b21to25 == 0x10 || b21to25 < 0x10)
7157         b21to25 = 0;
7158   }
7159   if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
7160      b21to25 = 0;
7161
7162   if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
7163      if (b21to25 == 1) {
7164         is_dcbzl = True;
7165         b21to25 = 0;
7166         if (!(guest_archinfo->ppc_dcbzl_szB)) {
7167            vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
7168            return False;
7169         }
7170      }
7171   }
7172
7173   if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
7174      if (0) vex_printf("dis_cache_manage %d %d %d\n",
7175                        (Int)opc1, (Int)b21to25, (Int)b0);
7176      vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n");
7177      return False;
7178   }
7179
7180   /* stay sane .. */
7181   vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
7182
7183   switch (opc2) {
7184//zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
7185//zz       vassert(0); /* AWAITING TEST CASE */
7186//zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
7187//zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
7188//zz       break;
7189
7190   case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
7191      DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
7192      /* nop as far as vex is concerned */
7193      break;
7194
7195   case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
7196      DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
7197      /* nop as far as vex is concerned */
7198      break;
7199
7200   case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
7201      DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
7202      /* nop as far as vex is concerned */
7203      break;
7204
7205   case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
7206      DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
7207      /* nop as far as vex is concerned */
7208      break;
7209
7210   case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
7211                 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
7212      /* Clear all bytes in cache block at (rA|0) + rB. */
7213      IRTemp  EA   = newTemp(ty);
7214      IRTemp  addr = newTemp(ty);
7215      IRExpr* irx_addr;
7216      UInt    i;
7217      UInt clearszB;
7218      if (is_dcbzl) {
7219          clearszB = guest_archinfo->ppc_dcbzl_szB;
7220          DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
7221      }
7222      else {
7223          clearszB = guest_archinfo->ppc_dcbz_szB;
7224          DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
7225      }
7226
7227      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7228
7229      if (mode64) {
7230         /* Round EA down to the start of the containing block. */
7231         assign( addr, binop( Iop_And64,
7232                              mkexpr(EA),
7233                              mkU64( ~((ULong)clearszB-1) )) );
7234
7235         for (i = 0; i < clearszB / 8; i++) {
7236            irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
7237            storeBE( irx_addr, mkU64(0) );
7238         }
7239      } else {
7240         /* Round EA down to the start of the containing block. */
7241         assign( addr, binop( Iop_And32,
7242                              mkexpr(EA),
7243                              mkU32( ~(clearszB-1) )) );
7244
7245         for (i = 0; i < clearszB / 4; i++) {
7246            irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
7247            storeBE( irx_addr, mkU32(0) );
7248         }
7249      }
7250      break;
7251   }
7252
7253   case 0x3D6: {
7254      // icbi (Instruction Cache Block Invalidate, PPC32 p431)
7255      /* Invalidate all translations containing code from the cache
7256         block at (rA|0) + rB. */
7257      IRTemp EA   = newTemp(ty);
7258      IRTemp addr = newTemp(ty);
7259      DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
7260      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7261
7262      /* Round EA down to the start of the containing block. */
7263      assign( addr, binop( mkSzOp(ty, Iop_And8),
7264                           mkexpr(EA),
7265                           mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
7266      putGST( PPC_GST_CMSTART, mkexpr(addr) );
7267      putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) );
7268
7269      /* be paranoid ... */
7270      stmt( IRStmt_MBE(Imbe_Fence) );
7271
7272      putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
7273      dres->jk_StopHere = Ijk_InvalICache;
7274      dres->whatNext    = Dis_StopHere;
7275      break;
7276   }
7277
7278   default:
7279      vex_printf("dis_cache_manage(ppc)(opc2)\n");
7280      return False;
7281   }
7282   return True;
7283}
7284
7285
7286/*------------------------------------------------------------*/
7287/*--- Floating Point Helpers                               ---*/
7288/*------------------------------------------------------------*/
7289
7290/* --------- Synthesise a 2-bit FPU rounding mode. --------- */
7291/* Produces a value in 0 .. 3, which is encoded as per the type
7292   IRRoundingMode.  PPCRoundingMode encoding is different to
7293   IRRoundingMode, so need to map it.
7294*/
7295static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
7296{
7297/*
7298   rounding mode | PPC | IR
7299   ------------------------
7300   to nearest    | 00  | 00
7301   to zero       | 01  | 11
7302   to +infinity  | 10  | 10
7303   to -infinity  | 11  | 01
7304*/
7305   IRTemp rm_PPC32 = newTemp(Ity_I32);
7306   assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
7307
7308   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7309   return binop( Iop_Xor32,
7310                 mkexpr(rm_PPC32),
7311                 binop( Iop_And32,
7312                        binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
7313                        mkU32(2) ));
7314}
7315
7316/* The DFP IR rounding modes were chosen such that the existing PPC to IR
7317 * mapping would still work with the extended three bit DFP rounding
7318 * mode designator.
7319
7320 *  rounding mode                     | PPC  |  IR
7321 *  -----------------------------------------------
7322 *  to nearest, ties to even          | 000  | 000
7323 *  to zero                           | 001  | 011
7324 *  to +infinity                      | 010  | 010
7325 *  to -infinity                      | 011  | 001
7326 *  to nearest, ties away from 0      | 100  | 100
7327 *  to nearest, ties toward 0         | 101  | 111
7328 *  to away from 0                    | 110  | 110
7329 *  to prepare for shorter precision  | 111  | 101
7330 */
7331static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
7332{
7333   IRTemp rm_PPC32 = newTemp( Ity_I32 );
7334   assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
7335
7336   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7337   return binop( Iop_Xor32,
7338                 mkexpr( rm_PPC32 ),
7339                 binop( Iop_And32,
7340                        binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
7341                        mkU32( 2 ) ) );
7342}
7343
7344#define NANmaskSingle   0x7F800000
7345#define NANmaskDouble   0x7FF00000
7346
7347static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
7348{
7349   IRTemp exp_zero  = newTemp(Ity_I8);
7350   IRTemp frac_mask = newTemp(Ity_I32);
7351   IRTemp frac_not_zero = newTemp(Ity_I8);
7352
7353   /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
7354    * The input value is always 64-bits, for single precision values, the
7355    * lower 32 bits must be zero.
7356    *
7357    * Single Pricision
7358    *  [62:54] exponent field is equal to 0xFF for NAN and Infinity.
7359    *  [53:32] fraction field is zero for Infinity and non-zero for NAN
7360    *  [31:0]  unused for single precision representation
7361    *
7362    * Double Pricision
7363    *  [62:51] exponent field is equal to 0xFF for NAN and Infinity.
7364    *  [50:0]  fraction field is zero for Infinity and non-zero for NAN
7365    *
7366    * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
7367    */
7368   assign( frac_mask, unop( Iop_Not32,
7369                            binop( Iop_Or32,
7370                                   mkU32( 0x80000000ULL ), Hi32Mask) ) );
7371
7372   assign( exp_zero,
7373           unop( Iop_1Sto8,
7374                 binop( Iop_CmpEQ32,
7375                        binop( Iop_And32,
7376                               unop( Iop_64HIto32,
7377                                     unop( Iop_ReinterpF64asI64,
7378                                           value ) ),
7379                               Hi32Mask ),
7380                        Hi32Mask ) ) );
7381   assign( frac_not_zero,
7382           binop( Iop_Or8,
7383                  unop( Iop_1Sto8,
7384                        binop( Iop_CmpNE32,
7385                               binop( Iop_And32,
7386                                      unop( Iop_64HIto32,
7387                                            unop( Iop_ReinterpF64asI64,
7388                                                  value ) ),
7389                                      mkexpr( frac_mask ) ),
7390                               mkU32( 0x0 ) ) ),
7391                  unop( Iop_1Sto8,
7392                        binop( Iop_CmpNE32,
7393                               binop( Iop_And32,
7394                                      unop( Iop_64to32,
7395                                            unop( Iop_ReinterpF64asI64,
7396                                                  value ) ),
7397                                      mkU32( 0xFFFFFFFF ) ),
7398                               mkU32( 0x0 ) ) ) ) );
7399   return unop( Iop_8Sto32,
7400                binop( Iop_And8,
7401                       mkexpr( exp_zero ),
7402                       mkexpr( frac_not_zero ) ) );
7403}
7404
7405static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
7406{
7407   /* This function will only complement the 64-bit floating point value if it
7408    * is not Nan.  NaN is not a signed value.  Need to do computations using
7409    * 32-bit operands to ensure it will run in 32-bit mode.
7410    */
7411   return  binop( Iop_32HLto64,
7412                  binop( Iop_Or32,
7413                         binop( Iop_And32,
7414                                nan_mask,
7415                                unop( Iop_64HIto32,
7416                                      unop( Iop_ReinterpF64asI64,
7417                                            value ) ) ),
7418                         binop( Iop_And32,
7419                                unop( Iop_Not32,
7420                                      nan_mask ),
7421                                unop( Iop_64HIto32,
7422                                      unop( Iop_ReinterpF64asI64,
7423                                            unop( Iop_NegF64,
7424                                                  value ) ) ) ) ),
7425                  unop( Iop_64to32,
7426                        unop( Iop_ReinterpF64asI64, value ) ) );
7427}
7428
7429/*------------------------------------------------------------*/
7430/*--- Floating Point Instruction Translation               ---*/
7431/*------------------------------------------------------------*/
7432
7433/*
7434  Floating Point Load Instructions
7435*/
7436static Bool dis_fp_load ( UInt theInstr )
7437{
7438   /* X-Form, D-Form */
7439   UChar opc1      = ifieldOPC(theInstr);
7440   UChar frD_addr  = ifieldRegDS(theInstr);
7441   UChar rA_addr   = ifieldRegA(theInstr);
7442   UChar rB_addr   = ifieldRegB(theInstr);
7443   UInt  opc2      = ifieldOPClo10(theInstr);
7444   UChar b0        = ifieldBIT0(theInstr);
7445   UInt  uimm16    = ifieldUIMM16(theInstr);
7446
7447   Int    simm16 = extend_s_16to32(uimm16);
7448   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
7449   IRTemp EA     = newTemp(ty);
7450   IRTemp rA     = newTemp(ty);
7451   IRTemp rB     = newTemp(ty);
7452   IRTemp iHi    = newTemp(Ity_I32);
7453   IRTemp iLo    = newTemp(Ity_I32);
7454
7455   assign( rA, getIReg(rA_addr) );
7456   assign( rB, getIReg(rB_addr) );
7457
7458   /* These are completely straightforward from a rounding and status
7459      bits perspective: no rounding involved and no funny status or CR
7460      bits affected. */
7461
7462   switch (opc1) {
7463   case 0x30: // lfs (Load Float Single, PPC32 p441)
7464      DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7465      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
7466      putFReg( frD_addr,
7467               unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
7468      break;
7469
7470   case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
7471      if (rA_addr == 0)
7472         return False;
7473      DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7474      assign( EA, ea_rA_simm(rA_addr, simm16) );
7475      putFReg( frD_addr,
7476               unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
7477      putIReg( rA_addr, mkexpr(EA) );
7478      break;
7479
7480   case 0x32: // lfd (Load Float Double, PPC32 p437)
7481      DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7482      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
7483      putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
7484      break;
7485
7486   case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
7487      if (rA_addr == 0)
7488         return False;
7489      DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7490      assign( EA, ea_rA_simm(rA_addr, simm16) );
7491      putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
7492      putIReg( rA_addr, mkexpr(EA) );
7493      break;
7494
7495   case 0x1F:
7496      if (b0 != 0) {
7497         vex_printf("dis_fp_load(ppc)(instr,b0)\n");
7498         return False;
7499      }
7500
7501      switch(opc2) {
7502      case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
7503         DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7504         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7505         putFReg( frD_addr, unop( Iop_F32toF64,
7506                                  loadBE(Ity_F32, mkexpr(EA))) );
7507         break;
7508
7509      case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
7510         if (rA_addr == 0)
7511            return False;
7512         DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7513         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
7514         putFReg( frD_addr,
7515                  unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
7516         putIReg( rA_addr, mkexpr(EA) );
7517         break;
7518
7519      case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
7520         DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7521         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7522         putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
7523         break;
7524
7525      case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
7526         if (rA_addr == 0)
7527            return False;
7528         DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7529         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
7530         putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
7531         putIReg( rA_addr, mkexpr(EA) );
7532         break;
7533
7534      case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
7535         DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7536         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7537         assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
7538         assign( iHi, binop(Iop_Sub32,
7539                            mkU32(0),
7540                            binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
7541         putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
7542                                 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
7543         break;
7544
7545      case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
7546      {
7547         IRTemp dw = newTemp( Ity_I64 );
7548         DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7549         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7550         assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
7551         assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
7552         putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
7553         break;
7554      }
7555
7556      default:
7557         vex_printf("dis_fp_load(ppc)(opc2)\n");
7558         return False;
7559      }
7560      break;
7561
7562   default:
7563      vex_printf("dis_fp_load(ppc)(opc1)\n");
7564      return False;
7565   }
7566   return True;
7567}
7568
7569
7570
7571/*
7572  Floating Point Store Instructions
7573*/
7574static Bool dis_fp_store ( UInt theInstr )
7575{
7576   /* X-Form, D-Form */
7577   UChar opc1      = ifieldOPC(theInstr);
7578   UChar frS_addr  = ifieldRegDS(theInstr);
7579   UChar rA_addr   = ifieldRegA(theInstr);
7580   UChar rB_addr   = ifieldRegB(theInstr);
7581   UInt  opc2      = ifieldOPClo10(theInstr);
7582   UChar b0        = ifieldBIT0(theInstr);
7583   Int   uimm16    = ifieldUIMM16(theInstr);
7584
7585   Int    simm16 = extend_s_16to32(uimm16);
7586   IRTemp frS    = newTemp(Ity_F64);
7587   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
7588   IRTemp EA     = newTemp(ty);
7589   IRTemp rA     = newTemp(ty);
7590   IRTemp rB     = newTemp(ty);
7591
7592   assign( frS, getFReg(frS_addr) );
7593   assign( rA,  getIReg(rA_addr) );
7594   assign( rB,  getIReg(rB_addr) );
7595
7596   /* These are straightforward from a status bits perspective: no
7597      funny status or CR bits affected.  For single precision stores,
7598      the values are truncated and denormalised (not rounded) to turn
7599      them into single precision values. */
7600
7601   switch (opc1) {
7602
7603   case 0x34: // stfs (Store Float Single, PPC32 p518)
7604      DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
7605      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
7606      /* Use Iop_TruncF64asF32 to truncate and possible denormalise
7607         the value to be stored in the correct way, without any
7608         rounding. */
7609      storeBE( mkexpr(EA),
7610               unop(Iop_TruncF64asF32, mkexpr(frS)) );
7611      break;
7612
7613   case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
7614      if (rA_addr == 0)
7615         return False;
7616      DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
7617      assign( EA, ea_rA_simm(rA_addr, simm16) );
7618      /* See comment for stfs */
7619      storeBE( mkexpr(EA),
7620               unop(Iop_TruncF64asF32, mkexpr(frS)) );
7621      putIReg( rA_addr, mkexpr(EA) );
7622      break;
7623
7624   case 0x36: // stfd (Store Float Double, PPC32 p513)
7625      DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
7626      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
7627      storeBE( mkexpr(EA), mkexpr(frS) );
7628      break;
7629
7630   case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
7631      if (rA_addr == 0)
7632         return False;
7633      DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
7634      assign( EA, ea_rA_simm(rA_addr, simm16) );
7635      storeBE( mkexpr(EA), mkexpr(frS) );
7636      putIReg( rA_addr, mkexpr(EA) );
7637      break;
7638
7639   case 0x1F:
7640      if (b0 != 0) {
7641         vex_printf("dis_fp_store(ppc)(instr,b0)\n");
7642         return False;
7643      }
7644      switch(opc2) {
7645      case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
7646         DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
7647         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7648         /* See note for stfs */
7649         storeBE( mkexpr(EA),
7650                  unop(Iop_TruncF64asF32, mkexpr(frS)) );
7651         break;
7652
7653      case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
7654         if (rA_addr == 0)
7655            return False;
7656         DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
7657         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
7658         /* See note for stfs */
7659         storeBE( mkexpr(EA),
7660                  unop(Iop_TruncF64asF32, mkexpr(frS)) );
7661         putIReg( rA_addr, mkexpr(EA) );
7662         break;
7663
7664      case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
7665         DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
7666         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7667         storeBE( mkexpr(EA), mkexpr(frS) );
7668         break;
7669
7670      case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
7671         if (rA_addr == 0)
7672            return False;
7673         DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
7674         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
7675         storeBE( mkexpr(EA), mkexpr(frS) );
7676         putIReg( rA_addr, mkexpr(EA) );
7677         break;
7678
7679      case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
7680         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7681         DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
7682         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7683         storeBE( mkexpr(EA),
7684                  unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
7685         break;
7686
7687      default:
7688         vex_printf("dis_fp_store(ppc)(opc2)\n");
7689         return False;
7690      }
7691      break;
7692
7693   default:
7694      vex_printf("dis_fp_store(ppc)(opc1)\n");
7695      return False;
7696   }
7697   return True;
7698}
7699
7700
7701
7702/*
7703  Floating Point Arith Instructions
7704*/
7705static Bool dis_fp_arith ( UInt theInstr )
7706{
7707   /* A-Form */
7708   UChar opc1     = ifieldOPC(theInstr);
7709   UChar frD_addr = ifieldRegDS(theInstr);
7710   UChar frA_addr = ifieldRegA(theInstr);
7711   UChar frB_addr = ifieldRegB(theInstr);
7712   UChar frC_addr = ifieldRegC(theInstr);
7713   UChar opc2     = ifieldOPClo5(theInstr);
7714   UChar flag_rC  = ifieldBIT0(theInstr);
7715
7716   IRTemp  frD = newTemp(Ity_F64);
7717   IRTemp  frA = newTemp(Ity_F64);
7718   IRTemp  frB = newTemp(Ity_F64);
7719   IRTemp  frC = newTemp(Ity_F64);
7720   IRExpr* rm  = get_IR_roundingmode();
7721
7722   /* By default, we will examine the results of the operation and set
7723      fpscr[FPRF] accordingly. */
7724   Bool set_FPRF = True;
7725
7726   /* By default, if flag_RC is set, we will clear cr1 after the
7727      operation.  In reality we should set cr1 to indicate the
7728      exception status of the operation, but since we're not
7729      simulating exceptions, the exception status will appear to be
7730      zero.  Hence cr1 should be cleared if this is a . form insn. */
7731   Bool clear_CR1 = True;
7732
7733   assign( frA, getFReg(frA_addr));
7734   assign( frB, getFReg(frB_addr));
7735   assign( frC, getFReg(frC_addr));
7736
7737   switch (opc1) {
7738   case 0x3B:
7739      switch (opc2) {
7740      case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
7741         if (frC_addr != 0)
7742            return False;
7743         DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7744             frD_addr, frA_addr, frB_addr);
7745         assign( frD, triop( Iop_DivF64r32,
7746                             rm, mkexpr(frA), mkexpr(frB) ));
7747         break;
7748
7749      case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
7750         if (frC_addr != 0)
7751            return False;
7752         DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7753             frD_addr, frA_addr, frB_addr);
7754         assign( frD, triop( Iop_SubF64r32,
7755                             rm, mkexpr(frA), mkexpr(frB) ));
7756         break;
7757
7758      case 0x15: // fadds (Floating Add Single, PPC32 p401)
7759         if (frC_addr != 0)
7760            return False;
7761         DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7762             frD_addr, frA_addr, frB_addr);
7763         assign( frD, triop( Iop_AddF64r32,
7764                             rm, mkexpr(frA), mkexpr(frB) ));
7765         break;
7766
7767      case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
7768         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
7769         if (frA_addr != 0 || frC_addr != 0)
7770            return False;
7771         DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
7772             frD_addr, frB_addr);
7773         // however illogically, on ppc970 this insn behaves identically
7774         // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
7775         assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
7776         break;
7777
7778      case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
7779         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7780         if (frA_addr != 0 || frC_addr != 0)
7781            return False;
7782         DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
7783             frD_addr, frB_addr);
7784         { IRExpr* ieee_one
7785              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
7786           assign( frD, triop( Iop_DivF64r32,
7787                               rm,
7788                               ieee_one, mkexpr(frB) ));
7789         }
7790         break;
7791
7792      case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
7793         if (frB_addr != 0)
7794            return False;
7795         DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7796             frD_addr, frA_addr, frC_addr);
7797         assign( frD, triop( Iop_MulF64r32,
7798                             rm, mkexpr(frA), mkexpr(frC) ));
7799         break;
7800
7801      case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
7802         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7803         // Undocumented instruction?
7804         if (frA_addr != 0 || frC_addr != 0)
7805            return False;
7806         DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
7807             frD_addr, frB_addr);
7808         assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
7809         break;
7810
7811      default:
7812         vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
7813         return False;
7814      }
7815      break;
7816
7817   case 0x3F:
7818      switch (opc2) {
7819      case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
7820         if (frC_addr != 0)
7821            return False;
7822         DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7823             frD_addr, frA_addr, frB_addr);
7824         assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
7825         break;
7826
7827      case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
7828         if (frC_addr != 0)
7829            return False;
7830         DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7831             frD_addr, frA_addr, frB_addr);
7832         assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
7833         break;
7834
7835      case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
7836         if (frC_addr != 0)
7837            return False;
7838         DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7839             frD_addr, frA_addr, frB_addr);
7840         assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
7841         break;
7842
7843      case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
7844         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
7845         if (frA_addr != 0 || frC_addr != 0)
7846            return False;
7847         DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
7848             frD_addr, frB_addr);
7849         assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
7850         break;
7851
7852      case 0x17: { // fsel (Floating Select, PPC32 p426)
7853         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7854         IRTemp cc    = newTemp(Ity_I32);
7855         IRTemp cc_b0 = newTemp(Ity_I32);
7856
7857         DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7858             frD_addr, frA_addr, frC_addr, frB_addr);
7859
7860         // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
7861         // => GT|EQ == (cc & 0x1 == 0)
7862         assign( cc, binop(Iop_CmpF64, mkexpr(frA),
7863                                       IRExpr_Const(IRConst_F64(0))) );
7864         assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
7865
7866         // frD = (frA >= 0.0) ? frC : frB
7867         //     = (cc_b0 == 0) ? frC : frB
7868         assign( frD,
7869                 IRExpr_ITE(
7870                    binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
7871                    mkexpr(frC),
7872                    mkexpr(frB) ));
7873
7874         /* One of the rare ones which don't mess with FPRF */
7875         set_FPRF = False;
7876         break;
7877      }
7878
7879      case 0x18: // fre (Floating Reciprocal Estimate)
7880         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7881         // Note: unclear whether this insn really exists or not
7882         // ppc970 doesn't have it, but POWER5 does
7883         if (frA_addr != 0 || frC_addr != 0)
7884            return False;
7885         DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
7886             frD_addr, frB_addr);
7887         { IRExpr* ieee_one
7888              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
7889           assign( frD, triop( Iop_DivF64,
7890                               rm,
7891                               ieee_one, mkexpr(frB) ));
7892         }
7893         break;
7894
7895      case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
7896         if (frB_addr != 0)
7897            vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
7898         DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7899             frD_addr, frA_addr, frC_addr);
7900         assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
7901         break;
7902
7903      case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
7904         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7905         if (frA_addr != 0 || frC_addr != 0)
7906            return False;
7907         DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
7908             frD_addr, frB_addr);
7909         assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
7910         break;
7911
7912      default:
7913         vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
7914         return False;
7915      }
7916      break;
7917
7918   default:
7919      vex_printf("dis_fp_arith(ppc)(opc1)\n");
7920      return False;
7921   }
7922
7923   putFReg( frD_addr, mkexpr(frD) );
7924
7925   if (set_FPRF) {
7926      // XXX XXX XXX FIXME
7927      // set FPRF from frD
7928   }
7929
7930   if (flag_rC && clear_CR1) {
7931      putCR321( 1, mkU8(0) );
7932      putCR0( 1, mkU8(0) );
7933   }
7934
7935   return True;
7936}
7937
7938
7939
7940/*
7941  Floating Point Mult-Add Instructions
7942*/
7943static Bool dis_fp_multadd ( UInt theInstr )
7944{
7945   /* A-Form */
7946   UChar opc1     = ifieldOPC(theInstr);
7947   UChar frD_addr = ifieldRegDS(theInstr);
7948   UChar frA_addr = ifieldRegA(theInstr);
7949   UChar frB_addr = ifieldRegB(theInstr);
7950   UChar frC_addr = ifieldRegC(theInstr);
7951   UChar opc2     = ifieldOPClo5(theInstr);
7952   UChar flag_rC  = ifieldBIT0(theInstr);
7953
7954   IRTemp  frD = newTemp(Ity_F64);
7955   IRTemp  frA = newTemp(Ity_F64);
7956   IRTemp  frB = newTemp(Ity_F64);
7957   IRTemp  frC = newTemp(Ity_F64);
7958   IRTemp  rmt = newTemp(Ity_I32);
7959   IRTemp  tmp = newTemp(Ity_F64);
7960   IRTemp  sign_tmp = newTemp(Ity_I64);
7961   IRTemp  nan_mask = newTemp(Ity_I32);
7962   IRExpr* rm;
7963
7964   /* By default, we will examine the results of the operation and set
7965      fpscr[FPRF] accordingly. */
7966   Bool set_FPRF = True;
7967
7968   /* By default, if flag_RC is set, we will clear cr1 after the
7969      operation.  In reality we should set cr1 to indicate the
7970      exception status of the operation, but since we're not
7971      simulating exceptions, the exception status will appear to be
7972      zero.  Hence cr1 should be cleared if this is a . form insn. */
7973   Bool clear_CR1 = True;
7974
7975   /* Bind the rounding mode expression to a temp; there's no
7976      point in creating gratuitous CSEs, as we know we'll need
7977      to use it twice. */
7978   assign( rmt, get_IR_roundingmode() );
7979   rm = mkexpr(rmt);
7980
7981   assign( frA, getFReg(frA_addr));
7982   assign( frB, getFReg(frB_addr));
7983   assign( frC, getFReg(frC_addr));
7984
7985   /* The rounding in this is all a bit dodgy.  The idea is to only do
7986      one rounding.  That clearly isn't achieveable without dedicated
7987      four-input IR primops, although in the single precision case we
7988      can sort-of simulate it by doing the inner multiply in double
7989      precision.
7990
7991      In the negated cases, the negation happens after rounding. */
7992
7993   switch (opc1) {
7994   case 0x3B:
7995      switch (opc2) {
7996      case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
7997         DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7998             frD_addr, frA_addr, frC_addr, frB_addr);
7999         assign( frD, qop( Iop_MSubF64r32, rm,
8000                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8001         break;
8002
8003      case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
8004         DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8005             frD_addr, frA_addr, frC_addr, frB_addr);
8006         assign( frD, qop( Iop_MAddF64r32, rm,
8007                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8008         break;
8009
8010      case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
8011      case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
8012
8013         if (opc2 == 0x1E) {
8014            DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8015                     frD_addr, frA_addr, frC_addr, frB_addr);
8016            assign( tmp, qop( Iop_MSubF64r32, rm,
8017                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8018         } else {
8019            DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8020                     frD_addr, frA_addr, frC_addr, frB_addr);
8021            assign( tmp, qop( Iop_MAddF64r32, rm,
8022                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8023         }
8024
8025         assign( nan_mask, Check_NaN( mkexpr( tmp ),
8026                                      mkU32( NANmaskSingle ) ) );
8027         assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
8028                                               mkexpr( nan_mask ) ) );
8029         assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
8030         break;
8031
8032      default:
8033         vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
8034         return False;
8035      }
8036      break;
8037
8038   case 0x3F:
8039      switch (opc2) {
8040      case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
8041         DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8042             frD_addr, frA_addr, frC_addr, frB_addr);
8043         assign( frD, qop( Iop_MSubF64, rm,
8044                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8045         break;
8046
8047      case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
8048         DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8049             frD_addr, frA_addr, frC_addr, frB_addr);
8050         assign( frD, qop( Iop_MAddF64, rm,
8051                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8052         break;
8053
8054      case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
8055      case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
8056
8057         if (opc2 == 0x1E) {
8058            DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8059                     frD_addr, frA_addr, frC_addr, frB_addr);
8060            assign( tmp, qop( Iop_MSubF64, rm,
8061                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8062         } else {
8063            DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8064                     frD_addr, frA_addr, frC_addr, frB_addr);
8065            assign( tmp, qop( Iop_MAddF64, rm,
8066                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8067         }
8068
8069         assign( nan_mask, Check_NaN( mkexpr( tmp ),
8070                                      mkU32( NANmaskDouble ) ) );
8071         assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
8072                                               mkexpr( nan_mask ) ) );
8073         assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
8074         break;
8075
8076      default:
8077         vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
8078         return False;
8079      }
8080      break;
8081
8082   default:
8083      vex_printf("dis_fp_multadd(ppc)(opc1)\n");
8084      return False;
8085   }
8086
8087   putFReg( frD_addr, mkexpr(frD) );
8088
8089   if (set_FPRF) {
8090      // XXX XXX XXX FIXME
8091      // set FPRF from frD
8092   }
8093
8094   if (flag_rC && clear_CR1) {
8095      putCR321( 1, mkU8(0) );
8096      putCR0( 1, mkU8(0) );
8097   }
8098
8099   return True;
8100}
8101
8102/*
8103 * fe_flag is set to 1 if any of the following conditions occurs:
8104 *  - The floating-point operand in register FRB is a Zero, a
8105 *    NaN, an Infinity, or a negative value.
8106 *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
8107 *  Otherwise fe_flag is set to 0.
8108 *
8109 * fg_flag is set to 1 if either of the following conditions occurs.
8110 *   - The floating-point operand in register FRB is a Zero, an
8111 *     Infinity, or a denormalized value.
8112 *  Otherwise fg_flag is set to 0.
8113 *
8114 */
8115static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
8116{
8117   // The following temps are for holding intermediate results
8118   IRTemp e_b = newTemp(Ity_I32);
8119   IRExpr * fe_flag,  * fg_flag;
8120   IRTemp frB_exp_shR = newTemp(Ity_I32);
8121   UInt bias = sp? 127 : 1023;
8122   IRExpr * frbNaN, * frbDenorm, * frBNeg;
8123   IRExpr * eb_LTE;
8124   IRTemp  frbZero_tmp = newTemp(Ity_I1);
8125   IRTemp  frbInf_tmp = newTemp(Ity_I1);
8126   *fe_flag_tmp = newTemp(Ity_I32);
8127   *fg_flag_tmp = newTemp(Ity_I32);
8128   assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
8129   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
8130
8131   //////////////////  fe_flag tests BEGIN //////////////////////
8132   /* We first do all tests that may result in setting fe_flag to '1'.
8133    * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
8134    * for details.)
8135    */
8136   frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
8137   assign( frbInf_tmp, is_Inf(frB_Int, sp) );
8138   assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
8139   {
8140      // Test_value = -970 for double precision
8141      UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
8142      eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
8143   }
8144   frBNeg = binop( Iop_CmpEQ32,
8145                   binop( Iop_Shr32,
8146                          sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
8147                          mkU8( 31 ) ),
8148                   mkU32( 1 ) );
8149   //////////////////  fe_flag tests END //////////////////////
8150
8151   //////////////////  fg_flag tests BEGIN //////////////////////
8152   /*
8153    * The following tests were already performed above in the fe_flag
8154    * tests.  So these conditions will result in both fe_ and fg_ flags
8155    * being set.
8156    *   - Test if FRB is Zero
8157    *   - Test if FRB is an Infinity
8158    */
8159
8160   /*
8161    * Test if FRB holds a denormalized value.  A denormalized value is one where
8162    * the exp is 0 and the fraction is non-zero.
8163    */
8164   if (sp) {
8165      IRTemp frac_part = newTemp(Ity_I32);
8166      assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
8167      frbDenorm
8168               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8169                         binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
8170   } else {
8171      IRExpr * hi32, * low32, * fraction_is_nonzero;
8172      IRTemp frac_part = newTemp(Ity_I64);
8173
8174      assign( frac_part, FP_FRAC_PART(frB_Int) );
8175      hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8176      low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8177      fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8178                                                mkU32( 0 ) );
8179      frbDenorm
8180               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8181                         fraction_is_nonzero );
8182   }
8183   //////////////////  fg_flag tests END //////////////////////
8184
8185   /////////////////////////
8186   fe_flag = mkOR1( mkexpr( frbZero_tmp ),
8187                    mkOR1( frbNaN,
8188                           mkOR1( mkexpr( frbInf_tmp ),
8189                                  mkOR1( frBNeg, eb_LTE ) ) ) );
8190
8191   fe_flag = unop(Iop_1Uto32, fe_flag);
8192
8193   fg_flag = mkOR1( mkexpr( frbZero_tmp ),
8194                    mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
8195   fg_flag = unop(Iop_1Uto32, fg_flag);
8196   assign (*fg_flag_tmp, fg_flag);
8197   assign (*fe_flag_tmp, fe_flag);
8198}
8199/*
8200 * fe_flag is set to 1 if any of the following conditions occurs:
8201 *  - The double-precision floating-point operand in register FRA is a NaN or an
8202 *    Infinity.
8203 *  - The double-precision floating-point operand in register FRB is a Zero, a
8204 *    NaN, or an Infinity.
8205 *  - e_b is less than or equal to -1022.
8206 *  - e_b is greater than or equal to 1021.
8207 *  - The double-precision floating-point operand in register FRA is not a zero
8208 *    and the difference, e_a - e_b, is greater than or equal to 1023.
8209 *  - The double-precision floating-point operand in register FRA is not a zero
8210 *    and the difference, e_a - e_b, is less than or equal to -1021.
8211 *  - The double-precision floating-point operand in register FRA is not a zero
8212 *    and e_a is less than or equal to -970
8213 *  Otherwise fe_flag is set to 0.
8214 *
8215 * fg_flag is set to 1 if either of the following conditions occurs.
8216 *   - The double-precision floating-point operand in register FRA is an Infinity.
8217 *   - The double-precision floating-point operand in register FRB is a Zero, an
8218 *     Infinity, or a denormalized value.
8219 *  Otherwise fg_flag is set to 0.
8220 *
8221 */
8222static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
8223{
8224   // The following temps are for holding intermediate results
8225   IRTemp e_a = newTemp(Ity_I32);
8226   IRTemp e_b = newTemp(Ity_I32);
8227   IRTemp frA_exp_shR = newTemp(Ity_I32);
8228   IRTemp frB_exp_shR = newTemp(Ity_I32);
8229
8230   UInt bias = sp? 127 : 1023;
8231   *fe_flag_tmp = newTemp(Ity_I32);
8232   *fg_flag_tmp = newTemp(Ity_I32);
8233
8234   /* The following variables hold boolean results from tests
8235    * that are OR'ed together for setting the fe_ and fg_ flags.
8236    * For some cases, the booleans are used more than once, so
8237    * I make those IRTemp's instead of IRExpr's.
8238    */
8239   IRExpr * fraNaN, * frbNaN, * frbDenorm;
8240   IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
8241   IRTemp  fraInf_tmp = newTemp(Ity_I1);
8242   IRTemp  frbZero_tmp = newTemp(Ity_I1);
8243   IRTemp  frbInf_tmp = newTemp(Ity_I1);
8244   IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
8245
8246/* The following are the flags that are set by OR'ing the results of
8247 * all the tests done for tdiv.  These flags are the input to the specified CR.
8248 */
8249   IRExpr * fe_flag, * fg_flag;
8250
8251   // Create temps that will be used throughout the following tests.
8252   assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
8253   assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
8254   /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
8255   assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
8256   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
8257
8258
8259   //////////////////  fe_flag tests BEGIN //////////////////////
8260   /* We first do all tests that may result in setting fe_flag to '1'. */
8261
8262   /*
8263    * Test if the double-precision floating-point operand in register FRA is
8264    * a NaN:
8265    */
8266   fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
8267   /*
8268    * Test if the double-precision floating-point operand in register FRA is
8269    * an Infinity.
8270    */
8271   assign(fraInf_tmp, is_Inf(frA_int, sp));
8272
8273   /*
8274    * Test if the double-precision floating-point operand in register FRB is
8275    * a NaN:
8276    */
8277   frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
8278   /*
8279    * Test if the double-precision floating-point operand in register FRB is
8280    * an Infinity.
8281    */
8282   assign( frbInf_tmp, is_Inf(frB_int, sp) );
8283   /*
8284    * Test if the double-precision floating-point operand in register FRB is
8285    * a Zero.
8286    */
8287   assign( frbZero_tmp, is_Zero(frB_int, sp) );
8288
8289   /*
8290    * Test if e_b <= -1022 for double precision;
8291    * or e_b <= -126 for single precision
8292    */
8293   {
8294      UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
8295      eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
8296   }
8297
8298   /*
8299    * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
8300    * or e_b >= -125 (125 < e_b) for single precision
8301    */
8302   {
8303      Int test_value = sp ? 125 : 1021;
8304      eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
8305   }
8306
8307   /*
8308    * Test if FRA != Zero and (e_a - e_b) >= bias
8309    */
8310   assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
8311   ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
8312                       binop( Iop_CmpLT32S, mkU32( bias ),
8313                              binop( Iop_Sub32, mkexpr( e_a ),
8314                                     mkexpr( e_b ) ) ) );
8315
8316   /*
8317    * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
8318    */
8319   {
8320      UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
8321
8322      ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
8323                          binop( Iop_CmpLE32S,
8324                                 binop( Iop_Sub32,
8325                                        mkexpr( e_a ),
8326                                        mkexpr( e_b ) ),
8327                                        mkU32( test_value ) ) );
8328   }
8329
8330   /*
8331    * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
8332    */
8333   {
8334      UInt test_value = 0xfffffc36;  //Int test_value = -970;
8335
8336      ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
8337                                                        mkexpr( e_a ),
8338                                                        mkU32( test_value ) ) );
8339   }
8340   //////////////////  fe_flag tests END //////////////////////
8341
8342   //////////////////  fg_flag tests BEGIN //////////////////////
8343   /*
8344    * The following tests were already performed above in the fe_flag
8345    * tests.  So these conditions will result in both fe_ and fg_ flags
8346    * being set.
8347    *   - Test if FRA is an Infinity
8348    *   - Test if FRB ix Zero
8349    *   - Test if FRB is an Infinity
8350    */
8351
8352   /*
8353    * Test if FRB holds a denormalized value.  A denormalized value is one where
8354    * the exp is 0 and the fraction is non-zero.
8355    */
8356   {
8357      IRExpr * fraction_is_nonzero;
8358
8359      if (sp) {
8360         fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
8361                                      mkU32( 0 ) );
8362      } else {
8363         IRExpr * hi32, * low32;
8364         IRTemp frac_part = newTemp(Ity_I64);
8365         assign( frac_part, FP_FRAC_PART(frB_int) );
8366
8367         hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8368         low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8369         fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8370                                      mkU32( 0 ) );
8371      }
8372      frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
8373                                 mkU32( 0x0 ) ), fraction_is_nonzero );
8374
8375   }
8376   //////////////////  fg_flag tests END //////////////////////
8377
8378   fe_flag
8379   = mkOR1(
8380            fraNaN,
8381            mkOR1(
8382                   mkexpr( fraInf_tmp ),
8383                   mkOR1(
8384                          mkexpr( frbZero_tmp ),
8385                          mkOR1(
8386                                 frbNaN,
8387                                 mkOR1(
8388                                        mkexpr( frbInf_tmp ),
8389                                        mkOR1( eb_LTE,
8390                                               mkOR1( eb_GTE,
8391                                                      mkOR1( ea_eb_GTE,
8392                                                             mkOR1( ea_eb_LTE,
8393                                                                    ea_LTE ) ) ) ) ) ) ) ) );
8394
8395   fe_flag = unop(Iop_1Uto32, fe_flag);
8396
8397   fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
8398                                                 mkOR1( mkexpr( frbInf_tmp ),
8399                                                        frbDenorm ) ) );
8400   fg_flag = unop(Iop_1Uto32, fg_flag);
8401   assign(*fe_flag_tmp, fe_flag);
8402   assign(*fg_flag_tmp, fg_flag);
8403}
8404
8405/* See description for _do_fp_tdiv() above. */
8406static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
8407{
8408   IRTemp  fe_flag, fg_flag;
8409   /////////////////////////
8410   /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8411    * where fl_flag == 1 on ppc64.
8412    */
8413   IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
8414   fe_flag = fg_flag = IRTemp_INVALID;
8415   _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
8416   return binop( Iop_Or32,
8417                 binop( Iop_Or32,
8418                        binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
8419                        binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8420                 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
8421}
8422
8423static Bool dis_fp_tests ( UInt theInstr )
8424{
8425   UChar opc1     = ifieldOPC(theInstr);
8426   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
8427   UChar frB_addr = ifieldRegB(theInstr);
8428   UChar b0       = ifieldBIT0(theInstr);
8429   UInt  opc2     = ifieldOPClo10(theInstr);
8430   IRTemp frB_I64     = newTemp(Ity_I64);
8431
8432   if (opc1 != 0x3F || b0 != 0 ){
8433      vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
8434      return False;
8435   }
8436   assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
8437
8438   switch (opc2) {
8439      case 0x080: // ftdiv
8440      {
8441         UChar frA_addr = ifieldRegA(theInstr);
8442         IRTemp frA_I64     = newTemp(Ity_I64);
8443         UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
8444         if (b21to22 != 0 ) {
8445            vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
8446            return False;
8447         }
8448
8449         assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
8450         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
8451
8452         DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
8453         break;
8454      }
8455      case 0x0A0: // ftsqrt
8456      {
8457         IRTemp flags = newTemp(Ity_I32);
8458         IRTemp  fe_flag, fg_flag;
8459         fe_flag = fg_flag = IRTemp_INVALID;
8460         UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
8461         if ( b18to22 != 0) {
8462            vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
8463            return False;
8464         }
8465         DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
8466         do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
8467         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8468          * where fl_flag == 1 on ppc64.
8469          */
8470         assign( flags,
8471                 binop( Iop_Or32,
8472                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
8473                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8474                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
8475         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
8476         break;
8477      }
8478
8479      default:
8480         vex_printf("dis_fp_tests(ppc)(opc2)\n");
8481         return False;
8482
8483   }
8484   return True;
8485}
8486
8487/*
8488  Floating Point Compare Instructions
8489*/
8490static Bool dis_fp_cmp ( UInt theInstr )
8491{
8492   /* X-Form */
8493   UChar opc1     = ifieldOPC(theInstr);
8494   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
8495   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
8496   UChar frA_addr = ifieldRegA(theInstr);
8497   UChar frB_addr = ifieldRegB(theInstr);
8498   UInt  opc2     = ifieldOPClo10(theInstr);
8499   UChar b0       = ifieldBIT0(theInstr);
8500
8501   IRTemp ccIR    = newTemp(Ity_I32);
8502   IRTemp ccPPC32 = newTemp(Ity_I32);
8503
8504   IRTemp frA     = newTemp(Ity_F64);
8505   IRTemp frB     = newTemp(Ity_F64);
8506
8507   if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
8508      vex_printf("dis_fp_cmp(ppc)(instr)\n");
8509      return False;
8510   }
8511
8512   assign( frA, getFReg(frA_addr));
8513   assign( frB, getFReg(frB_addr));
8514
8515   assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
8516
8517   /* Map compare result from IR to PPC32 */
8518   /*
8519     FP cmp result | PPC | IR
8520     --------------------------
8521     UN            | 0x1 | 0x45
8522     EQ            | 0x2 | 0x40
8523     GT            | 0x4 | 0x00
8524     LT            | 0x8 | 0x01
8525   */
8526
8527   // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
8528   //                    | ((ccIR ^ (ccIR>>6)) & 1)
8529   assign(
8530      ccPPC32,
8531      binop(
8532         Iop_Shl32,
8533         mkU32(1),
8534         unop(
8535            Iop_32to8,
8536            binop(
8537               Iop_Or32,
8538               binop(
8539                  Iop_And32,
8540                  unop(
8541                     Iop_Not32,
8542                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
8543                  ),
8544                  mkU32(2)
8545               ),
8546               binop(
8547                  Iop_And32,
8548                  binop(
8549                     Iop_Xor32,
8550                     mkexpr(ccIR),
8551                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
8552                  ),
8553                  mkU32(1)
8554               )
8555            )
8556         )
8557      )
8558   );
8559
8560   putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
8561
8562   /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
8563      putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
8564   */
8565   // XXX XXX XXX FIXME
8566   // Also write the result into FPRF (it's not entirely clear how)
8567
8568   /* Note: Differences between fcmpu and fcmpo are only in exception
8569      flag settings, which aren't supported anyway. */
8570   switch (opc2) {
8571   case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
8572      DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
8573      break;
8574   case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
8575      DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
8576      break;
8577   default:
8578      vex_printf("dis_fp_cmp(ppc)(opc2)\n");
8579      return False;
8580   }
8581   return True;
8582}
8583
8584
8585
8586/*
8587  Floating Point Rounding/Conversion Instructions
8588*/
8589static Bool dis_fp_round ( UInt theInstr )
8590{
8591   /* X-Form */
8592   UChar opc1     = ifieldOPC(theInstr);
8593   UChar b16to20  = ifieldRegA(theInstr);
8594   UChar frD_addr = ifieldRegDS(theInstr);
8595   UChar frB_addr = ifieldRegB(theInstr);
8596   UInt  opc2     = ifieldOPClo10(theInstr);
8597   UChar flag_rC  = ifieldBIT0(theInstr);
8598
8599   IRTemp  frD     = newTemp(Ity_F64);
8600   IRTemp  frB     = newTemp(Ity_F64);
8601   IRTemp  r_tmp32 = newTemp(Ity_I32);
8602   IRTemp  r_tmp64 = newTemp(Ity_I64);
8603   IRExpr* rm      = get_IR_roundingmode();
8604
8605   /* By default, we will examine the results of the operation and set
8606      fpscr[FPRF] accordingly. */
8607   Bool set_FPRF = True;
8608
8609   /* By default, if flag_RC is set, we will clear cr1 after the
8610      operation.  In reality we should set cr1 to indicate the
8611      exception status of the operation, but since we're not
8612      simulating exceptions, the exception status will appear to be
8613      zero.  Hence cr1 should be cleared if this is a . form insn. */
8614   Bool clear_CR1 = True;
8615   if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
8616      vex_printf("dis_fp_round(ppc)(instr)\n");
8617      return False;
8618   }
8619
8620   assign( frB, getFReg(frB_addr));
8621   if (opc1 == 0x3B) {
8622      /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
8623       * they're very similar to the other instructions handled here, but have
8624       * a different primary opcode.
8625       */
8626      switch (opc2) {
8627         case 0x34E: // fcfids (Float convert from signed DWord to single precision)
8628            DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8629            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
8630            assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
8631                                                              mkexpr( r_tmp64 ) ) ) );
8632            goto putFR;
8633
8634         case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
8635            DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8636            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
8637            assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
8638            goto putFR;
8639      }
8640   }
8641
8642
8643   switch (opc2) {
8644   case 0x00C: // frsp (Float Round to Single, PPC32 p423)
8645      DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8646      assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
8647      break;
8648
8649   case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
8650      DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8651      assign( r_tmp32,
8652              binop(Iop_F64toI32S, rm, mkexpr(frB)) );
8653      assign( frD, unop( Iop_ReinterpI64asF64,
8654                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
8655      /* FPRF is undefined after fctiw.  Leave unchanged. */
8656      set_FPRF = False;
8657      break;
8658
8659   case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
8660      DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8661      assign( r_tmp32,
8662              binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
8663      assign( frD, unop( Iop_ReinterpI64asF64,
8664                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
8665      /* FPRF is undefined after fctiwz.  Leave unchanged. */
8666      set_FPRF = False;
8667      break;
8668
8669   case 0x08F: case 0x08E: // fctiwu[z]
8670      DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
8671               flag_rC ? ".":"", frD_addr, frB_addr);
8672      assign( r_tmp32,
8673              binop( Iop_F64toI32U,
8674                     opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
8675                     mkexpr( frB ) ) );
8676      assign( frD, unop( Iop_ReinterpI64asF64,
8677                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
8678      /* FPRF is undefined after fctiwz.  Leave unchanged. */
8679      set_FPRF = False;
8680      break;
8681
8682
8683   case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
8684      DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8685      assign( r_tmp64,
8686              binop(Iop_F64toI64S, rm, mkexpr(frB)) );
8687      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
8688      /* FPRF is undefined after fctid.  Leave unchanged. */
8689      set_FPRF = False;
8690      break;
8691
8692   case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
8693      DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8694      assign( r_tmp64,
8695              binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
8696      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
8697      /* FPRF is undefined after fctidz.  Leave unchanged. */
8698      set_FPRF = False;
8699      break;
8700
8701   case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
8702   {
8703      DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
8704               flag_rC ? ".":"", frD_addr, frB_addr);
8705      assign( r_tmp64,
8706              binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
8707      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
8708      /* FPRF is undefined after fctidz.  Leave unchanged. */
8709      set_FPRF = False;
8710      break;
8711   }
8712   case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
8713      DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8714      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
8715      assign( frD,
8716              binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
8717      break;
8718
8719   case 0x3CE: // fcfidu (Float convert from unsigned DWord)
8720      DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8721      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
8722      assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
8723      break;
8724
8725   case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
8726      switch(opc2) {
8727      case 0x188: // frin (Floating Round to Integer Nearest)
8728         DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8729         assign( r_tmp64,
8730                 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
8731         break;
8732      case 0x1A8: // friz (Floating Round to Integer Toward Zero)
8733         DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8734         assign( r_tmp64,
8735                 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
8736         break;
8737      case 0x1C8: // frip (Floating Round to Integer Plus)
8738         DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8739         assign( r_tmp64,
8740                 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
8741         break;
8742      case 0x1E8: // frim (Floating Round to Integer Minus)
8743         DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8744         assign( r_tmp64,
8745                 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
8746         break;
8747      }
8748
8749      /* don't use the rounded integer if frB is outside -9e18..9e18 */
8750      /* F64 has only log10(2**52) significant digits anyway */
8751      /* need to preserve sign of zero */
8752      /*   frD = (fabs(frB) > 9e18) ? frB :
8753               (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
8754      assign(frD, IRExpr_ITE(
8755                     binop(Iop_CmpNE8,
8756                           unop(Iop_32to8,
8757                                binop(Iop_CmpF64,
8758                                      IRExpr_Const(IRConst_F64(9e18)),
8759                                      unop(Iop_AbsF64, mkexpr(frB)))),
8760                           mkU8(0)),
8761                     mkexpr(frB),
8762                     IRExpr_ITE(
8763                        binop(Iop_CmpNE32,
8764                              binop(Iop_Shr32,
8765                                    unop(Iop_64HIto32,
8766                                         unop(Iop_ReinterpF64asI64,
8767                                              mkexpr(frB))),
8768                                    mkU8(31)),
8769                              mkU32(0)),
8770                        unop(Iop_NegF64,
8771                             unop( Iop_AbsF64,
8772                                   binop(Iop_I64StoF64, mkU32(0),
8773                                         mkexpr(r_tmp64)) )),
8774                        binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
8775                     )
8776      ));
8777      break;
8778
8779   default:
8780      vex_printf("dis_fp_round(ppc)(opc2)\n");
8781      return False;
8782   }
8783putFR:
8784   putFReg( frD_addr, mkexpr(frD) );
8785
8786   if (set_FPRF) {
8787      // XXX XXX XXX FIXME
8788      // set FPRF from frD
8789   }
8790
8791   if (flag_rC && clear_CR1) {
8792      putCR321( 1, mkU8(0) );
8793      putCR0( 1, mkU8(0) );
8794   }
8795
8796   return True;
8797}
8798
8799/*
8800  Floating Point Pair Instructions
8801*/
8802static Bool dis_fp_pair ( UInt theInstr )
8803{
8804   /* X-Form/DS-Form */
8805   UChar  opc1         = ifieldOPC(theInstr);
8806   UChar  frT_hi_addr  = ifieldRegDS(theInstr);
8807   UChar  frT_lo_addr  = frT_hi_addr + 1;
8808   UChar  rA_addr      = ifieldRegA(theInstr);
8809   UChar  rB_addr      = ifieldRegB(theInstr);
8810   UInt  uimm16        = ifieldUIMM16(theInstr);
8811   Int    simm16       = extend_s_16to32(uimm16);
8812   UInt   opc2         = ifieldOPClo10(theInstr);
8813   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
8814   IRTemp EA_hi        = newTemp(ty);
8815   IRTemp EA_lo        = newTemp(ty);
8816   IRTemp frT_hi       = newTemp(Ity_F64);
8817   IRTemp frT_lo       = newTemp(Ity_F64);
8818   UChar b0            = ifieldBIT0(theInstr);
8819   Bool is_load        = 0;
8820
8821   if ((frT_hi_addr %2) != 0) {
8822      vex_printf("dis_fp_pair(ppc) : odd frT register\n");
8823      return False;
8824   }
8825
8826   switch (opc1) {
8827   case 0x1F: // register offset
8828      switch(opc2) {
8829      case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
8830         DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
8831         is_load = 1;
8832         break;
8833      case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
8834         DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
8835         break;
8836      default:
8837         vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
8838         return False;
8839      }
8840
8841      if (b0 != 0) {
8842         vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
8843         return False;
8844      }
8845      assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
8846      break;
8847   case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
8848      DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
8849      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
8850      is_load = 1;
8851      break;
8852   case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
8853      DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
8854      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
8855      break;
8856   default:   // immediate offset
8857      vex_printf("dis_fp_pair(ppc)(instr)\n");
8858      return False;
8859   }
8860
8861   if (mode64)
8862      assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
8863   else
8864      assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
8865
8866   assign( frT_hi, getFReg(frT_hi_addr) );
8867   assign( frT_lo, getFReg(frT_lo_addr) );
8868
8869   if (is_load) {
8870      putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) );
8871      putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) );
8872   } else {
8873      storeBE( mkexpr(EA_hi), mkexpr(frT_hi) );
8874      storeBE( mkexpr(EA_lo), mkexpr(frT_lo) );
8875   }
8876
8877   return True;
8878}
8879
8880
8881/*
8882  Floating Point Merge Instructions
8883*/
8884static Bool dis_fp_merge ( UInt theInstr )
8885{
8886   /* X-Form */
8887   UInt  opc2     = ifieldOPClo10(theInstr);
8888   UChar frD_addr = ifieldRegDS(theInstr);
8889   UChar frA_addr = ifieldRegA(theInstr);
8890   UChar frB_addr = ifieldRegB(theInstr);
8891
8892   IRTemp frD = newTemp(Ity_F64);
8893   IRTemp frA = newTemp(Ity_F64);
8894   IRTemp frB = newTemp(Ity_F64);
8895
8896   assign( frA, getFReg(frA_addr));
8897   assign( frB, getFReg(frB_addr));
8898
8899   switch (opc2) {
8900   case 0x3c6: // fmrgew floating merge even word
8901      DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
8902
8903      assign( frD, unop( Iop_ReinterpI64asF64,
8904                         binop( Iop_32HLto64,
8905                                unop( Iop_64HIto32,
8906                                      unop( Iop_ReinterpF64asI64,
8907                                            mkexpr(frA) ) ),
8908                                unop( Iop_64HIto32,
8909                                      unop( Iop_ReinterpF64asI64,
8910                                            mkexpr(frB) ) ) ) ) );
8911   break;
8912
8913   case 0x346: // fmrgow floating merge odd word
8914      DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
8915
8916      assign( frD, unop( Iop_ReinterpI64asF64,
8917                         binop( Iop_32HLto64,
8918                                unop( Iop_64to32,
8919                                      unop( Iop_ReinterpF64asI64,
8920                                            mkexpr(frA) ) ),
8921                                unop( Iop_64to32,
8922                                      unop( Iop_ReinterpF64asI64,
8923                                            mkexpr(frB) ) ) ) ) );
8924   break;
8925
8926   default:
8927      vex_printf("dis_fp_merge(ppc)(opc2)\n");
8928      return False;
8929   }
8930
8931   putFReg( frD_addr, mkexpr(frD) );
8932   return True;
8933}
8934
8935/*
8936  Floating Point Move Instructions
8937*/
8938static Bool dis_fp_move ( UInt theInstr )
8939{
8940   /* X-Form */
8941   UChar opc1     = ifieldOPC(theInstr);
8942   UChar frD_addr = ifieldRegDS(theInstr);
8943   UChar frA_addr = ifieldRegA(theInstr);
8944   UChar frB_addr = ifieldRegB(theInstr);
8945   UInt  opc2     = ifieldOPClo10(theInstr);
8946   UChar flag_rC  = ifieldBIT0(theInstr);
8947
8948   IRTemp frD = newTemp(Ity_F64);
8949   IRTemp frB = newTemp(Ity_F64);
8950   IRTemp itmpB = newTemp(Ity_F64);
8951   IRTemp frA;
8952   IRTemp signA;
8953   IRTemp hiD;
8954
8955   if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
8956      vex_printf("dis_fp_move(ppc)(instr)\n");
8957      return False;
8958   }
8959
8960   assign( frB, getFReg(frB_addr));
8961
8962   switch (opc2) {
8963   case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
8964      DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
8965          frB_addr);
8966      signA = newTemp(Ity_I32);
8967      hiD = newTemp(Ity_I32);
8968      itmpB = newTemp(Ity_I64);
8969      frA = newTemp(Ity_F64);
8970      assign( frA, getFReg(frA_addr) );
8971
8972      /* get A's sign bit */
8973      assign(signA, binop(Iop_And32,
8974                          unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
8975                                                  mkexpr(frA))),
8976                          mkU32(0x80000000)) );
8977
8978      assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
8979
8980      /* mask off B's sign bit and or in A's sign bit */
8981      assign(hiD, binop(Iop_Or32,
8982                        binop(Iop_And32,
8983                              unop(Iop_64HIto32,
8984                                   mkexpr(itmpB)),  /* frB's high 32 bits */
8985                              mkU32(0x7fffffff)),
8986                        mkexpr(signA)) );
8987
8988      /* combine hiD/loB into frD */
8989      assign( frD, unop(Iop_ReinterpI64asF64,
8990                        binop(Iop_32HLto64,
8991                              mkexpr(hiD),
8992                              unop(Iop_64to32,
8993                                   mkexpr(itmpB)))) );   /* frB's low 32 bits */
8994      break;
8995
8996   case 0x028: // fneg (Floating Negate, PPC32 p416)
8997      DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8998      assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
8999      break;
9000
9001   case 0x048: // fmr (Floating Move Register, PPC32 p410)
9002      DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9003      assign( frD, mkexpr(frB) );
9004      break;
9005
9006   case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
9007      DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9008      assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
9009      break;
9010
9011   case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
9012      DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9013      assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
9014      break;
9015
9016   default:
9017      vex_printf("dis_fp_move(ppc)(opc2)\n");
9018      return False;
9019   }
9020
9021   putFReg( frD_addr, mkexpr(frD) );
9022
9023   /* None of these change FPRF.  cr1 is set in the usual way though,
9024      if flag_rC is set. */
9025
9026   if (flag_rC) {
9027      putCR321( 1, mkU8(0) );
9028      putCR0( 1, mkU8(0) );
9029   }
9030
9031   return True;
9032}
9033
9034
9035
9036/*
9037  Floating Point Status/Control Register Instructions
9038*/
9039static Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
9040{
9041   /* Many forms - see each switch case */
9042   UChar opc1    = ifieldOPC(theInstr);
9043   UInt  opc2    = ifieldOPClo10(theInstr);
9044   UChar flag_rC = ifieldBIT0(theInstr);
9045
9046   if (opc1 != 0x3F) {
9047      vex_printf("dis_fp_scr(ppc)(instr)\n");
9048      return False;
9049   }
9050
9051   switch (opc2) {
9052   case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
9053      // Bit crbD of the FPSCR is set.
9054      UChar crbD    = ifieldRegDS(theInstr);
9055      UInt  b11to20 = IFIELD(theInstr, 11, 10);
9056
9057      if (b11to20 != 0) {
9058         vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
9059         return False;
9060      }
9061      DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
9062      putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
9063		     1ULL << ( 31 - crbD ) );
9064      break;
9065   }
9066
9067   case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
9068      UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
9069      UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
9070      UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
9071      UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
9072      IRTemp  tmp     = newTemp(Ity_I32);
9073      IRExpr* fpscr_all;
9074      if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
9075         vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
9076         return False;
9077      }
9078      DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
9079      vassert(crfD < 8);
9080      vassert(crfS < 8);
9081      fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9082      assign( tmp, binop(Iop_And32,
9083                         binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
9084                        mkU32(0xF)) );
9085      putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
9086      break;
9087   }
9088
9089   case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
9090      // Bit crbD of the FPSCR is cleared.
9091      UChar crbD    = ifieldRegDS(theInstr);
9092      UInt  b11to20 = IFIELD(theInstr, 11, 10);
9093
9094      if (b11to20 != 0) {
9095         vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
9096         return False;
9097      }
9098      DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
9099      putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
9100      break;
9101   }
9102
9103   case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
9104      UInt crfD     = IFIELD( theInstr, 23, 3 );
9105      UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
9106      UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
9107      UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
9108      UChar Wbit;
9109
9110      if (b16to22 != 0 || b11 != 0) {
9111         vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
9112         return False;
9113      }
9114      DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM);
9115      if (GX_level) {
9116         /* This implies that Decimal Floating Point is supported, and the
9117          * FPSCR must be managed as a 64-bit register.
9118          */
9119         Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9120      } else {
9121         Wbit = 0;
9122      }
9123      crfD = crfD + (8 * (1 - Wbit) );
9124      putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
9125      break;
9126   }
9127
9128   case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
9129      UChar   frD_addr  = ifieldRegDS(theInstr);
9130      UInt    b11to20   = IFIELD(theInstr, 11, 10);
9131      IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9132      IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR,
9133                                                 MASK_FPSCR_DRN );
9134
9135      if (b11to20 != 0) {
9136         vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
9137         return False;
9138      }
9139      DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
9140      putFReg( frD_addr,
9141          unop( Iop_ReinterpI64asF64,
9142                binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
9143      break;
9144   }
9145
9146   case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
9147      UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
9148      UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
9149      UChar frB_addr = ifieldRegB(theInstr);
9150      IRTemp frB   = newTemp(Ity_F64);
9151      IRTemp rB_64 = newTemp( Ity_I64 );
9152      Int i;
9153      ULong mask;
9154      UChar Wbit;
9155#define BFP_MASK_SEED 0x3000000000000000ULL
9156#define DFP_MASK_SEED 0x7000000000000000ULL
9157
9158      if (GX_level) {
9159         /* This implies that Decimal Floating Point is supported, and the
9160          * FPSCR must be managed as a 64-bit register.
9161          */
9162         Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9163      } else {
9164         Wbit = 0;
9165      }
9166
9167      if (b25 == 1) {
9168         /* new 64 bit move variant for power 6.  If L field (bit 25) is
9169          * a one do a full 64 bit move.  Note, the FPSCR is not really
9170          * properly modeled.  This instruciton only changes the value of
9171          * the rounding mode.  The HW exception bits do not get set in
9172          * the simulator.  1/12/09
9173          */
9174         DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
9175         mask = 0xFF;
9176
9177      } else {
9178         DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
9179         // Build 32bit mask from FM:
9180         mask = 0;
9181         for (i=0; i<8; i++) {
9182            if ((FM & (1<<(7-i))) == 1) {
9183               /* FPSCR field k is set to the contents of the corresponding
9184                * field of register FRB, where k = i+8x(1-W).  In the Power
9185                * ISA, register field numbering is from left to right, so field
9186                * 15 is the least significant field in a 64-bit register.  To
9187                * generate the mask, we set all the appropriate rounding mode
9188                * bits in the highest order nibble (field 0) and shift right
9189                * 'k x nibble length'.
9190                */
9191               if (Wbit)
9192                  mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
9193               else
9194                  mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
9195            }
9196         }
9197      }
9198      assign( frB, getFReg(frB_addr));
9199      assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
9200      putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
9201      break;
9202   }
9203
9204   default:
9205      vex_printf("dis_fp_scr(ppc)(opc2)\n");
9206      return False;
9207   }
9208   return True;
9209}
9210
9211/*------------------------------------------------------------*/
9212/*--- Decimal Floating Point (DFP)  Helper functions       ---*/
9213/*------------------------------------------------------------*/
9214#define DFP_LONG  1
9215#define DFP_EXTND 2
9216#define DFP_LONG_BIAS   398
9217#define DFP_LONG_ENCODED_FIELD_MASK  0x1F00
9218#define DFP_EXTND_BIAS  6176
9219#define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
9220#define DFP_LONG_EXP_MSK   0XFF
9221#define DFP_EXTND_EXP_MSK  0XFFF
9222
9223#define DFP_G_FIELD_LONG_MASK     0x7FFC0000  // upper 32-bits only
9224#define DFP_LONG_GFIELD_RT_SHIFT  (63 - 13 - 32) // adj for upper 32-bits
9225#define DFP_G_FIELD_EXTND_MASK    0x7FFFC000  // upper 32-bits only
9226#define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
9227#define DFP_T_FIELD_LONG_MASK     0x3FFFF  // mask for upper 32-bits
9228#define DFP_T_FIELD_EXTND_MASK    0x03FFFF // mask for upper 32-bits
9229#define DFP_LONG_EXP_MAX          369      // biased max
9230#define DFP_LONG_EXP_MIN          0        // biased min
9231#define DFP_EXTND_EXP_MAX         6111     // biased max
9232#define DFP_EXTND_EXP_MIN         0        // biased min
9233#define DFP_LONG_MAX_SIG_DIGITS   16
9234#define DFP_EXTND_MAX_SIG_DIGITS  34
9235#define MAX_DIGITS_IN_STRING      8
9236
9237
9238#define  AND(x, y) binop( Iop_And32, x, y )
9239#define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
9240#define   OR(x, y) binop( Iop_Or32,  x, y )
9241#define  OR3(x, y, z)    OR( x, OR( y, z ) )
9242#define  OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
9243#define  NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1,  mkexpr( x ) ) ) )
9244
9245#define  SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
9246#define  SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
9247
9248#define BITS5(_b4,_b3,_b2,_b1,_b0) \
9249   (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
9250    ((_b1) << 1) | ((_b0) << 0))
9251
9252static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
9253{
9254   IRTemp lmd_07_mask   = newTemp( Ity_I32 );
9255   IRTemp lmd_8_mask    = newTemp( Ity_I32 );
9256   IRTemp lmd_9_mask    = newTemp( Ity_I32 );
9257   IRTemp lmexp_00_mask = newTemp( Ity_I32 );
9258   IRTemp lmexp_01_mask = newTemp( Ity_I32 );
9259   IRTemp lmexp_10_mask = newTemp( Ity_I32 );
9260   IRTemp lmd_07_val    = newTemp( Ity_I32 );
9261   IRTemp lmd_8_val     = newTemp( Ity_I32 );
9262   IRTemp lmd_9_val     = newTemp( Ity_I32 );
9263
9264   /* The encodig is as follows:
9265    * lmd - left most digit
9266    * lme - left most 2-bits of the exponent
9267    *
9268    *    lmd
9269    *   0 - 7    (lmexp << 3) | lmd
9270    *     8      0b11000 (24 decimal) if lme=0b00;
9271    *            0b11010 (26 decimal) if lme=0b01;
9272    *            0b11100 (28 decimal) if lme=0b10;
9273    *     9      0b11001 (25 decimal) if lme=0b00;
9274    *            0b11011 (27 decimal) if lme=0b01;
9275    *            0b11101 (29 decimal) if lme=0b10;
9276    */
9277
9278   /* Generate the masks for each condition */
9279   assign( lmd_07_mask,
9280           unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
9281   assign( lmd_8_mask,
9282           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
9283   assign( lmd_9_mask,
9284           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
9285   assign( lmexp_00_mask,
9286           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
9287   assign( lmexp_01_mask,
9288           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
9289   assign( lmexp_10_mask,
9290           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
9291
9292   /* Generate the values for each LMD condition, assuming the condition
9293    * is TRUE.
9294    */
9295   assign( lmd_07_val,
9296           binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
9297   assign( lmd_8_val,
9298           binop( Iop_Or32,
9299                  binop( Iop_Or32,
9300                         binop( Iop_And32,
9301                                mkexpr( lmexp_00_mask ),
9302                                mkU32( 24 ) ),
9303                         binop( Iop_And32,
9304                                mkexpr( lmexp_01_mask ),
9305                                mkU32( 26 ) ) ),
9306                  binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
9307   assign( lmd_9_val,
9308           binop( Iop_Or32,
9309                  binop( Iop_Or32,
9310                         binop( Iop_And32,
9311                                mkexpr( lmexp_00_mask ),
9312                                mkU32( 25 ) ),
9313                         binop( Iop_And32,
9314                                mkexpr( lmexp_01_mask ),
9315                                mkU32( 27 ) ) ),
9316                  binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
9317
9318   /* generate the result from the possible LMD values */
9319   return binop( Iop_Or32,
9320                 binop( Iop_Or32,
9321                        binop( Iop_And32,
9322                               mkexpr( lmd_07_mask ),
9323                               mkexpr( lmd_07_val ) ),
9324                        binop( Iop_And32,
9325                               mkexpr( lmd_8_mask ),
9326                               mkexpr( lmd_8_val ) ) ),
9327                 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
9328}
9329
9330static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
9331{
9332   /* Extract the exponent and the left most digit of the mantissa
9333    * from the G field bits [0:4].
9334    */
9335   IRTemp lmd_07_mask   = newTemp( Ity_I32 );
9336   IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
9337   IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
9338   IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
9339   IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
9340   IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
9341   IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
9342
9343   IRTemp lmd_07_val = newTemp( Ity_I32 );
9344   IRTemp lmd_8_val  = newTemp( Ity_I32 );
9345   IRTemp lmd_9_val  = newTemp( Ity_I32 );
9346
9347   /* The left most digit (LMD) encoding is as follows:
9348    *    lmd
9349    *   0 - 7    (lmexp << 3) | lmd
9350    *     8      0b11000 (24 decimal) if lme=0b00;
9351    *            0b11010 (26 decimal) if lme=0b01;
9352    *            0b11100 (28 decimal) if lme=0b10
9353    *     9      0b11001 (25 decimal) if lme=0b00;
9354    *            0b11011 (27 decimal) if lme=0b01;
9355    *            0b11101 (29 decimal) if lme=0b10;
9356    */
9357
9358   /* Generate the masks for each condition of LMD and exponent bits */
9359   assign( lmd_07_mask,
9360           unop( Iop_1Sto32, binop( Iop_CmpLE32U,
9361                                    gfield_0_4,
9362                                    mkU32( BITS5(1,0,1,1,1) ) ) ) );
9363   assign( lmd_8_00_mask,
9364           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9365                                    gfield_0_4,
9366                                    mkU32( BITS5(1,1,0,0,0) ) ) ) );
9367   assign( lmd_8_01_mask,
9368           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9369                                    gfield_0_4,
9370                                    mkU32( BITS5(1,1,0,1,0) ) ) ) );
9371   assign( lmd_8_10_mask,
9372           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9373                                    gfield_0_4,
9374                                    mkU32( BITS5(1,1,1,0,0) ) ) ) );
9375   assign( lmd_9_00_mask,
9376           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9377                                    gfield_0_4,
9378                                    mkU32( BITS5(1,1,0,0,1) ) ) ) );
9379   assign( lmd_9_01_mask,
9380           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9381                                    gfield_0_4,
9382                                    mkU32( BITS5(1,1,0,1,1) ) ) ) );
9383   assign( lmd_9_10_mask,
9384           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9385                                    gfield_0_4,
9386                                    mkU32( BITS5(1,1,1,0,1) ) ) ) );
9387
9388   /* Generate the values for each LMD condition, assuming the condition
9389    * is TRUE.
9390    */
9391   assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
9392   assign( lmd_8_val, mkU32( 0x8 ) );
9393   assign( lmd_9_val, mkU32( 0x9 ) );
9394
9395   assign( *lmd,
9396           OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
9397                     AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
9398                     AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
9399                     OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
9400                          AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
9401                          AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
9402                          AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
9403                     ) ) );
9404}
9405
9406#define DIGIT1_SHR 4    // shift digit 1 to bottom 4 bits
9407#define DIGIT2_SHR 8    // shift digit 2 to bottom 4 bits
9408#define DIGIT3_SHR 12
9409#define DIGIT4_SHR 16
9410#define DIGIT5_SHR 20
9411#define DIGIT6_SHR 24
9412#define DIGIT7_SHR 28
9413
9414static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
9415{
9416   /* 60-bit BCD string stored in two 32-bit values.  Check that each,
9417    * digit is a valid BCD number, i.e. less then 9.
9418    */
9419   IRTemp valid = newTemp( Ity_I32 );
9420
9421   assign( valid,
9422           AND4( AND4 ( unop( Iop_1Sto32,
9423                              binop( Iop_CmpLE32U,
9424                                     binop( Iop_And32,
9425                                            bcd_l,
9426                                            mkU32 ( 0xF ) ),
9427                                      mkU32( 0x9 ) ) ),
9428                        unop( Iop_1Sto32,
9429                              binop( Iop_CmpLE32U,
9430                                     binop( Iop_And32,
9431                                            binop( Iop_Shr32,
9432                                                   bcd_l,
9433                                                   mkU8 ( DIGIT1_SHR ) ),
9434                                             mkU32 ( 0xF ) ),
9435                                      mkU32( 0x9 ) ) ),
9436                        unop( Iop_1Sto32,
9437                              binop( Iop_CmpLE32U,
9438                                     binop( Iop_And32,
9439                                            binop( Iop_Shr32,
9440                                                   bcd_l,
9441                                                   mkU8 ( DIGIT2_SHR ) ),
9442                                            mkU32 ( 0xF ) ),
9443                                      mkU32( 0x9 ) ) ),
9444                        unop( Iop_1Sto32,
9445                              binop( Iop_CmpLE32U,
9446                                     binop( Iop_And32,
9447                                            binop( Iop_Shr32,
9448                                                   bcd_l,
9449                                                   mkU8 ( DIGIT3_SHR ) ),
9450                                             mkU32 ( 0xF ) ),
9451                                      mkU32( 0x9 ) ) ) ),
9452                 AND4 ( unop( Iop_1Sto32,
9453                              binop( Iop_CmpLE32U,
9454                                     binop( Iop_And32,
9455                                            binop( Iop_Shr32,
9456                                                   bcd_l,
9457                                                   mkU8 ( DIGIT4_SHR ) ),
9458                                            mkU32 ( 0xF ) ),
9459                                     mkU32( 0x9 ) ) ),
9460                        unop( Iop_1Sto32,
9461                              binop( Iop_CmpLE32U,
9462                                     binop( Iop_And32,
9463                                            binop( Iop_Shr32,
9464                                                   bcd_l,
9465                                                   mkU8 ( DIGIT5_SHR ) ),
9466                                            mkU32 ( 0xF ) ),
9467                                     mkU32( 0x9 ) ) ),
9468                        unop( Iop_1Sto32,
9469                              binop( Iop_CmpLE32U,
9470                                     binop( Iop_And32,
9471                                            binop( Iop_Shr32,
9472                                                   bcd_l,
9473                                                   mkU8 ( DIGIT6_SHR ) ),
9474                                            mkU32 ( 0xF ) ),
9475                                     mkU32( 0x9 ) ) ),
9476                        unop( Iop_1Sto32,
9477                              binop( Iop_CmpLE32U,
9478                                     binop( Iop_And32,
9479                                            binop( Iop_Shr32,
9480                                                   bcd_l,
9481                                                   mkU8 ( DIGIT7_SHR ) ),
9482                                            mkU32 ( 0xF ) ),
9483                                     mkU32( 0x9 ) ) ) ),
9484                 AND4( unop( Iop_1Sto32,
9485                             binop( Iop_CmpLE32U,
9486                                    binop( Iop_And32,
9487                                           bcd_u,
9488                                           mkU32 ( 0xF ) ),
9489                                    mkU32( 0x9 ) ) ),
9490                       unop( Iop_1Sto32,
9491                             binop( Iop_CmpLE32U,
9492                                    binop( Iop_And32,
9493                                           binop( Iop_Shr32,
9494                                                  bcd_u,
9495                                                  mkU8 ( DIGIT1_SHR ) ),
9496                                           mkU32 ( 0xF ) ),
9497                                    mkU32( 0x9 ) ) ),
9498                       unop( Iop_1Sto32,
9499                             binop( Iop_CmpLE32U,
9500                                    binop( Iop_And32,
9501                                           binop( Iop_Shr32,
9502                                                  bcd_u,
9503                                                  mkU8 ( DIGIT2_SHR ) ),
9504                                           mkU32 ( 0xF ) ),
9505                                    mkU32( 0x9 ) ) ),
9506                       unop( Iop_1Sto32,
9507                             binop( Iop_CmpLE32U,
9508                                    binop( Iop_And32,
9509                                           binop( Iop_Shr32,
9510                                                  bcd_u,
9511                                                  mkU8 ( DIGIT3_SHR ) ),
9512                                           mkU32 ( 0xF ) ),
9513                                    mkU32( 0x9 ) ) ) ),
9514                 AND4( unop( Iop_1Sto32,
9515                             binop( Iop_CmpLE32U,
9516                                    binop( Iop_And32,
9517                                           binop( Iop_Shr32,
9518                                                  bcd_u,
9519                                                  mkU8 ( DIGIT4_SHR ) ),
9520                                           mkU32 ( 0xF ) ),
9521                                    mkU32( 0x9 ) ) ),
9522                       unop( Iop_1Sto32,
9523                             binop( Iop_CmpLE32U,
9524                                    binop( Iop_And32,
9525                                           binop( Iop_Shr32,
9526                                                  bcd_u,
9527                                                  mkU8 ( DIGIT5_SHR ) ),
9528                                           mkU32 ( 0xF ) ),
9529                                    mkU32( 0x9 ) ) ),
9530                       unop( Iop_1Sto32,
9531                             binop( Iop_CmpLE32U,
9532                                    binop( Iop_And32,
9533                                           binop( Iop_Shr32,
9534                                                  bcd_u,
9535                                                  mkU8 ( DIGIT6_SHR ) ),
9536                                           mkU32 ( 0xF ) ),
9537                                    mkU32( 0x9 ) ) ),
9538                       unop( Iop_1Sto32,
9539                             binop( Iop_CmpLE32U,
9540                                    binop( Iop_And32,
9541                                           binop( Iop_Shr32,
9542                                                  bcd_u,
9543                                                  mkU8 ( DIGIT7_SHR ) ),
9544                                           mkU32 ( 0xF ) ),
9545                                    mkU32( 0x9 ) ) ) ) ) );
9546
9547   return unop( Iop_Not32, mkexpr( valid ) );
9548}
9549#undef DIGIT1_SHR
9550#undef DIGIT2_SHR
9551#undef DIGIT3_SHR
9552#undef DIGIT4_SHR
9553#undef DIGIT5_SHR
9554#undef DIGIT6_SHR
9555#undef DIGIT7_SHR
9556
9557static IRExpr * Generate_neg_sign_mask( IRExpr * sign )
9558{
9559   return binop( Iop_Or32,
9560                 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
9561                 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
9562               );
9563}
9564
9565static IRExpr * Generate_pos_sign_mask( IRExpr * sign )
9566{
9567   return binop( Iop_Or32,
9568                 binop( Iop_Or32,
9569                        unop( Iop_1Sto32,
9570                              binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
9571                        unop( Iop_1Sto32,
9572                              binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
9573                 binop( Iop_Or32,
9574                        unop( Iop_1Sto32,
9575                              binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
9576                        unop( Iop_1Sto32,
9577                              binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
9578}
9579
9580static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
9581                                   IRExpr * neg_sign_mask )
9582{
9583   return binop( Iop_Or32,
9584                 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
9585                 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
9586}
9587
9588static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
9589                                   IRExpr * pos_sign_mask,
9590                                   IRExpr * neg_sign_mask )
9591/* first argument is all 1's if the BCD string had an invalid digit in it. */
9592{
9593   return binop( Iop_Or32,
9594                 invalid_bcd_mask,
9595                 unop( Iop_1Sto32,
9596                       binop( Iop_CmpEQ32,
9597                              binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
9598                              mkU32( 0x0 ) ) ) );
9599}
9600
9601static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
9602                                         IRTemp * top_12_l, IRTemp * mid_60_u,
9603                                         IRTemp * mid_60_l, IRTemp * low_60_u,
9604                                         IRTemp * low_60_l)
9605{
9606   IRTemp tmplow60 = newTemp( Ity_I64 );
9607   IRTemp tmpmid60 = newTemp( Ity_I64 );
9608   IRTemp tmptop12 = newTemp( Ity_I64 );
9609   IRTemp low_50   = newTemp( Ity_I64 );
9610   IRTemp mid_50   = newTemp( Ity_I64 );
9611   IRTemp top_10   = newTemp( Ity_I64 );
9612   IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
9613
9614   /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
9615
9616   /* low_50[49:0] = ((frBI64_lo[49:32]  << 14) | frBI64_lo[31:0]) */
9617   assign( low_50,
9618           binop( Iop_32HLto64,
9619                  binop( Iop_And32,
9620                         unop( Iop_64HIto32, frBI64_lo ),
9621                         mkU32( 0x3FFFF ) ),
9622                         unop( Iop_64to32, frBI64_lo ) ) );
9623
9624   /* Convert the 50 bit densely packed BCD string to a 60 bit
9625    * BCD string.
9626    */
9627   assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
9628   assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
9629   assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
9630
9631   /* mid_50[49:0] =  ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
9632    *                 ((frBI64_hi[17:0]  << 14) | frBI64_lo[63:50])
9633    */
9634   assign( mid_50,
9635           binop( Iop_32HLto64,
9636                  binop( Iop_Or32,
9637                         binop( Iop_Shl32,
9638                                binop( Iop_And32,
9639                                       unop( Iop_64HIto32, frBI64_hi ),
9640                                       mkU32( 0xF ) ),
9641                                mkU8( 14 ) ),
9642                         binop( Iop_Shr32,
9643                                unop( Iop_64to32, frBI64_hi ),
9644                                mkU8( 18 ) ) ),
9645                  binop( Iop_Or32,
9646                         binop( Iop_Shl32,
9647                                unop( Iop_64to32, frBI64_hi ),
9648                                mkU8( 14 ) ),
9649                         binop( Iop_Shr32,
9650                                unop( Iop_64HIto32, frBI64_lo ),
9651                                mkU8( 18 ) ) ) ) );
9652
9653   /* Convert the 50 bit densely packed BCD string to a 60 bit
9654    * BCD string.
9655    */
9656   assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
9657   assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
9658   assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
9659
9660   /* top_10[49:0] = frBI64_hi[45:36]) |  */
9661   assign( top_10,
9662           binop( Iop_32HLto64,
9663                  mkU32( 0 ),
9664                  binop( Iop_And32,
9665                         binop( Iop_Shr32,
9666                                unop( Iop_64HIto32, frBI64_hi ),
9667                                mkU8( 4 ) ),
9668                         mkU32( 0x3FF ) ) ) );
9669
9670   /* Convert the 10 bit densely packed BCD string to a 12 bit
9671    * BCD string.
9672    */
9673   assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
9674   assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
9675   assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
9676}
9677
9678static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
9679                         IRTemp * final_cnt, IRTemp * final_flag,
9680                         IRExpr * string )
9681{
9682   IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
9683   int digits = MAX_DIGITS_IN_STRING;
9684   int i;
9685
9686   cnt[start-1] = newTemp( Ity_I8 );
9687   flag[start-1] = newTemp( Ity_I8 );
9688   assign( cnt[start-1], init_cnt);
9689   assign( flag[start-1], init_flag);
9690
9691   for ( i = start; i <= digits; i++) {
9692      cnt[i] = newTemp( Ity_I8 );
9693      flag[i] = newTemp( Ity_I8 );
9694      assign( cnt[i],
9695              binop( Iop_Add8,
9696                     mkexpr( cnt[i-1] ),
9697                     binop(Iop_And8,
9698                           unop( Iop_1Uto8,
9699                                 binop(Iop_CmpEQ32,
9700                                       binop(Iop_And32,
9701                                             string,
9702                                             mkU32( 0xF <<
9703                                                    ( ( digits - i ) * 4) ) ),
9704                                       mkU32( 0 ) ) ),
9705                           binop( Iop_Xor8, /* complement flag */
9706                                  mkexpr( flag[i - 1] ),
9707                                  mkU8( 0xFF ) ) ) ) );
9708
9709      /* set flag to 1 if digit was not a zero */
9710      assign( flag[i],
9711              binop(Iop_Or8,
9712                    unop( Iop_1Sto8,
9713                          binop(Iop_CmpNE32,
9714                                binop(Iop_And32,
9715                                      string,
9716                                      mkU32( 0xF <<
9717                                             ( (digits - i) * 4) ) ),
9718                                mkU32( 0 ) ) ),
9719                    mkexpr( flag[i - 1] ) ) );
9720   }
9721
9722   *final_cnt = cnt[digits];
9723   *final_flag = flag[digits];
9724}
9725
9726static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
9727                                        IRExpr * low_32 )
9728{
9729   IRTemp num_lmd    = newTemp( Ity_I8 );
9730   IRTemp num_upper  = newTemp( Ity_I8 );
9731   IRTemp num_low    = newTemp( Ity_I8 );
9732   IRTemp lmd_flag   = newTemp( Ity_I8 );
9733   IRTemp upper_flag = newTemp( Ity_I8 );
9734   IRTemp low_flag   = newTemp( Ity_I8 );
9735
9736   assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
9737   assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
9738
9739   Count_zeros( 2,
9740                mkexpr( num_lmd ),
9741                mkexpr( lmd_flag ),
9742                &num_upper,
9743                &upper_flag,
9744                upper_28 );
9745
9746   Count_zeros( 1,
9747                mkexpr( num_upper ),
9748                mkexpr( upper_flag ),
9749                &num_low,
9750                &low_flag,
9751                low_32 );
9752
9753   return mkexpr( num_low );
9754}
9755
9756static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
9757                                         IRExpr * mid_60_u, IRExpr * mid_60_l,
9758                                         IRExpr * low_60_u, IRExpr * low_60_l)
9759{
9760   IRTemp num_lmd   = newTemp( Ity_I8 );
9761   IRTemp num_top   = newTemp( Ity_I8 );
9762   IRTemp num_mid_u = newTemp( Ity_I8 );
9763   IRTemp num_mid_l = newTemp( Ity_I8 );
9764   IRTemp num_low_u = newTemp( Ity_I8 );
9765   IRTemp num_low_l = newTemp( Ity_I8 );
9766
9767   IRTemp lmd_flag   = newTemp( Ity_I8 );
9768   IRTemp top_flag   = newTemp( Ity_I8 );
9769   IRTemp mid_u_flag = newTemp( Ity_I8 );
9770   IRTemp mid_l_flag = newTemp( Ity_I8 );
9771   IRTemp low_u_flag = newTemp( Ity_I8 );
9772   IRTemp low_l_flag = newTemp( Ity_I8 );
9773
9774   /* Check the LMD, digit 16, to see if it is zero. */
9775   assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
9776
9777   assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
9778
9779   Count_zeros( 6,
9780                mkexpr( num_lmd ),
9781                mkexpr( lmd_flag ),
9782                &num_top,
9783                &top_flag,
9784                top_12_l );
9785
9786   Count_zeros( 1,
9787                mkexpr( num_top ),
9788                mkexpr( top_flag ),
9789                &num_mid_u,
9790                &mid_u_flag,
9791                binop( Iop_Or32,
9792                       binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
9793                       binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
9794
9795   Count_zeros( 2,
9796                mkexpr( num_mid_u ),
9797                mkexpr( mid_u_flag ),
9798                &num_mid_l,
9799                &mid_l_flag,
9800                mid_60_l );
9801
9802   Count_zeros( 1,
9803                mkexpr( num_mid_l ),
9804                mkexpr( mid_l_flag ),
9805                &num_low_u,
9806                &low_u_flag,
9807                binop( Iop_Or32,
9808                       binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
9809                       binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
9810
9811   Count_zeros( 2,
9812                mkexpr( num_low_u ),
9813                mkexpr( low_u_flag ),
9814                &num_low_l,
9815                &low_l_flag,
9816                low_60_l );
9817
9818   return mkexpr( num_low_l );
9819}
9820
9821static IRExpr * Check_unordered(IRExpr * val)
9822{
9823   IRTemp gfield0to5 = newTemp( Ity_I32 );
9824
9825   /* Extract G[0:4] */
9826   assign( gfield0to5,
9827           binop( Iop_And32,
9828                  binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
9829                  mkU32( 0x1F ) ) );
9830
9831   /* Check for unordered, return all 1'x if true */
9832   return binop( Iop_Or32, /* QNaN check */
9833                 unop( Iop_1Sto32,
9834                       binop( Iop_CmpEQ32,
9835                              mkexpr( gfield0to5 ),
9836                              mkU32( 0x1E ) ) ),
9837                              unop( Iop_1Sto32, /* SNaN check */
9838                                    binop( Iop_CmpEQ32,
9839                                           mkexpr( gfield0to5 ),
9840                                           mkU32( 0x1F ) ) ) );
9841}
9842
9843#undef AND
9844#undef AND4
9845#undef OR
9846#undef OR3
9847#undef OR4
9848#undef NOT
9849#undef SHR
9850#undef SHL
9851#undef BITS5
9852
9853/*------------------------------------------------------------*/
9854/*--- Decimal Floating Point (DFP) instruction translation ---*/
9855/*------------------------------------------------------------*/
9856
9857/* DFP Arithmetic instructions */
9858static Bool dis_dfp_arith(UInt theInstr)
9859{
9860   UInt opc2 = ifieldOPClo10( theInstr );
9861   UChar frS_addr = ifieldRegDS( theInstr );
9862   UChar frA_addr = ifieldRegA( theInstr );
9863   UChar frB_addr = ifieldRegB( theInstr );
9864   UChar flag_rC = ifieldBIT0( theInstr );
9865
9866   IRTemp frA = newTemp( Ity_D64 );
9867   IRTemp frB = newTemp( Ity_D64 );
9868   IRTemp frS = newTemp( Ity_D64 );
9869   IRExpr* round = get_IR_roundingmode_DFP();
9870
9871   /* By default, if flag_RC is set, we will clear cr1 after the
9872    * operation.  In reality we should set cr1 to indicate the
9873    * exception status of the operation, but since we're not
9874    * simulating exceptions, the exception status will appear to be
9875    * zero.  Hence cr1 should be cleared if this is a . form insn.
9876    */
9877   Bool clear_CR1 = True;
9878
9879   assign( frA, getDReg( frA_addr ) );
9880   assign( frB, getDReg( frB_addr ) );
9881
9882   switch (opc2) {
9883   case 0x2: // dadd
9884      DIP( "dadd%s fr%u,fr%u,fr%u\n",
9885           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
9886      assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
9887      break;
9888   case 0x202: // dsub
9889      DIP( "dsub%s fr%u,fr%u,fr%u\n",
9890           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
9891      assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
9892      break;
9893   case 0x22: // dmul
9894      DIP( "dmul%s fr%u,fr%u,fr%u\n",
9895           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
9896      assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
9897      break;
9898   case 0x222: // ddiv
9899      DIP( "ddiv%s fr%u,fr%u,fr%u\n",
9900           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
9901      assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
9902      break;
9903   }
9904
9905   putDReg( frS_addr, mkexpr( frS ) );
9906
9907   if (flag_rC && clear_CR1) {
9908      putCR321( 1, mkU8( 0 ) );
9909      putCR0( 1, mkU8( 0 ) );
9910   }
9911
9912   return True;
9913}
9914
9915/* Quad DFP Arithmetic instructions */
9916static Bool dis_dfp_arithq(UInt theInstr)
9917{
9918   UInt opc2 = ifieldOPClo10( theInstr );
9919   UChar frS_addr = ifieldRegDS( theInstr );
9920   UChar frA_addr = ifieldRegA( theInstr );
9921   UChar frB_addr = ifieldRegB( theInstr );
9922   UChar flag_rC = ifieldBIT0( theInstr );
9923
9924   IRTemp frA = newTemp( Ity_D128 );
9925   IRTemp frB = newTemp( Ity_D128 );
9926   IRTemp frS = newTemp( Ity_D128 );
9927   IRExpr* round = get_IR_roundingmode_DFP();
9928
9929   /* By default, if flag_RC is set, we will clear cr1 after the
9930    * operation.  In reality we should set cr1 to indicate the
9931    * exception status of the operation, but since we're not
9932    * simulating exceptions, the exception status will appear to be
9933    * zero.  Hence cr1 should be cleared if this is a . form insn.
9934    */
9935   Bool clear_CR1 = True;
9936
9937   assign( frA, getDReg_pair( frA_addr ) );
9938   assign( frB, getDReg_pair( frB_addr ) );
9939
9940   switch (opc2) {
9941   case 0x2: // daddq
9942      DIP( "daddq%s fr%u,fr%u,fr%u\n",
9943           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
9944      assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
9945      break;
9946   case 0x202: // dsubq
9947      DIP( "dsubq%s fr%u,fr%u,fr%u\n",
9948           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
9949      assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
9950      break;
9951   case 0x22: // dmulq
9952      DIP( "dmulq%s fr%u,fr%u,fr%u\n",
9953           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
9954      assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
9955      break;
9956   case 0x222: // ddivq
9957      DIP( "ddivq%s fr%u,fr%u,fr%u\n",
9958           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
9959      assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
9960      break;
9961   }
9962
9963   putDReg_pair( frS_addr, mkexpr( frS ) );
9964
9965   if (flag_rC && clear_CR1) {
9966      putCR321( 1, mkU8( 0 ) );
9967      putCR0( 1, mkU8( 0 ) );
9968   }
9969
9970   return True;
9971}
9972
9973/* DFP 64-bit logical shift instructions  */
9974static Bool dis_dfp_shift(UInt theInstr) {
9975   UInt opc2       = ifieldOPClo9( theInstr );
9976   UChar frS_addr  = ifieldRegDS( theInstr );
9977   UChar frA_addr  = ifieldRegA( theInstr );
9978   UChar shift_val = IFIELD(theInstr, 10, 6);
9979   UChar flag_rC   = ifieldBIT0( theInstr );
9980
9981   IRTemp frA = newTemp( Ity_D64 );
9982   IRTemp frS = newTemp( Ity_D64 );
9983   Bool clear_CR1 = True;
9984
9985   assign( frA, getDReg( frA_addr ) );
9986
9987   switch (opc2) {
9988   case 0x42: // dscli
9989      DIP( "dscli%s fr%u,fr%u,%u\n",
9990           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
9991      assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
9992      break;
9993   case 0x62: // dscri
9994      DIP( "dscri%s fr%u,fr%u,%u\n",
9995           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
9996      assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
9997      break;
9998   }
9999
10000   putDReg( frS_addr, mkexpr( frS ) );
10001
10002   if (flag_rC && clear_CR1) {
10003      putCR321( 1, mkU8( 0 ) );
10004      putCR0( 1, mkU8( 0 ) );
10005   }
10006
10007   return True;
10008}
10009
10010/* Quad DFP  logical shift instructions  */
10011static Bool dis_dfp_shiftq(UInt theInstr) {
10012   UInt opc2       = ifieldOPClo9( theInstr );
10013   UChar frS_addr  = ifieldRegDS( theInstr );
10014   UChar frA_addr  = ifieldRegA( theInstr );
10015   UChar shift_val = IFIELD(theInstr, 10, 6);
10016   UChar flag_rC   = ifieldBIT0( theInstr );
10017
10018   IRTemp frA = newTemp( Ity_D128 );
10019   IRTemp frS = newTemp( Ity_D128 );
10020   Bool clear_CR1 = True;
10021
10022   assign( frA, getDReg_pair( frA_addr ) );
10023
10024   switch (opc2) {
10025   case 0x42: // dscliq
10026      DIP( "dscliq%s fr%u,fr%u,%u\n",
10027           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10028      assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
10029      break;
10030   case 0x62: // dscriq
10031      DIP( "dscriq%s fr%u,fr%u,%u\n",
10032           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10033      assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
10034      break;
10035   }
10036
10037   putDReg_pair( frS_addr, mkexpr( frS ) );
10038
10039   if (flag_rC && clear_CR1) {
10040      putCR321( 1, mkU8( 0 ) );
10041      putCR0( 1, mkU8( 0 ) );
10042   }
10043
10044   return True;
10045}
10046
10047/* DFP 64-bit format conversion instructions */
10048static Bool dis_dfp_fmt_conv(UInt theInstr) {
10049   UInt opc2      = ifieldOPClo10( theInstr );
10050   UChar frS_addr = ifieldRegDS( theInstr );
10051   UChar frB_addr = ifieldRegB( theInstr );
10052   IRExpr* round  = get_IR_roundingmode_DFP();
10053   UChar flag_rC  = ifieldBIT0( theInstr );
10054   IRTemp frB;
10055   IRTemp frS;
10056   Bool clear_CR1 = True;
10057
10058   switch (opc2) {
10059   case 0x102: //dctdp
10060      DIP( "dctdp%s fr%u,fr%u\n",
10061           flag_rC ? ".":"", frS_addr, frB_addr );
10062
10063      frB = newTemp( Ity_D32 );
10064      frS = newTemp( Ity_D64 );
10065      assign( frB, getDReg32( frB_addr ) );
10066      assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
10067      putDReg( frS_addr, mkexpr( frS ) );
10068      break;
10069   case 0x302: // drsp
10070      DIP( "drsp%s fr%u,fr%u\n",
10071           flag_rC ? ".":"", frS_addr, frB_addr );
10072      frB = newTemp( Ity_D64 );
10073      frS = newTemp( Ity_D32 );
10074      assign( frB, getDReg( frB_addr ) );
10075      assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
10076      putDReg32( frS_addr, mkexpr( frS ) );
10077      break;
10078   case 0x122: // dctfix
10079      {
10080         IRTemp tmp = newTemp( Ity_I64 );
10081
10082         DIP( "dctfix%s fr%u,fr%u\n",
10083              flag_rC ? ".":"", frS_addr, frB_addr );
10084         frB = newTemp( Ity_D64 );
10085         frS = newTemp( Ity_D64 );
10086         assign( frB, getDReg( frB_addr ) );
10087         assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
10088         assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10089         putDReg( frS_addr, mkexpr( frS ) );
10090      }
10091      break;
10092   case 0x322: // dcffix
10093      DIP( "dcffix%s fr%u,fr%u\n",
10094           flag_rC ? ".":"", frS_addr, frB_addr );
10095      frB = newTemp( Ity_D64 );
10096      frS = newTemp( Ity_D64 );
10097      assign( frB, getDReg( frB_addr ) );
10098      assign( frS, binop( Iop_I64StoD64,
10099                          round,
10100                          unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
10101      putDReg( frS_addr, mkexpr( frS ) );
10102      break;
10103   }
10104
10105   if (flag_rC && clear_CR1) {
10106      putCR321( 1, mkU8( 0 ) );
10107      putCR0( 1, mkU8( 0 ) );
10108   }
10109
10110   return True;
10111}
10112
10113/* Quad DFP format conversion instructions */
10114static Bool dis_dfp_fmt_convq(UInt theInstr) {
10115   UInt opc2      = ifieldOPClo10( theInstr );
10116   UChar frS_addr = ifieldRegDS( theInstr );
10117   UChar frB_addr = ifieldRegB( theInstr );
10118   IRExpr* round  = get_IR_roundingmode_DFP();
10119   IRTemp frB64   = newTemp( Ity_D64 );
10120   IRTemp frB128  = newTemp( Ity_D128 );
10121   IRTemp frS64   = newTemp( Ity_D64 );
10122   IRTemp frS128  = newTemp( Ity_D128 );
10123   UChar flag_rC  = ifieldBIT0( theInstr );
10124   Bool clear_CR1 = True;
10125
10126   switch (opc2) {
10127   case 0x102: // dctqpq
10128      DIP( "dctqpq%s fr%u,fr%u\n",
10129           flag_rC ? ".":"", frS_addr, frB_addr );
10130      assign( frB64, getDReg( frB_addr ) );
10131      assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
10132      putDReg_pair( frS_addr, mkexpr( frS128 ) );
10133      break;
10134   case 0x122: // dctfixq
10135      {
10136         IRTemp tmp = newTemp( Ity_I64 );
10137
10138         DIP( "dctfixq%s fr%u,fr%u\n",
10139              flag_rC ? ".":"", frS_addr, frB_addr );
10140         assign( frB128, getDReg_pair( frB_addr ) );
10141         assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
10142         assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10143         putDReg( frS_addr, mkexpr( frS64 ) );
10144      }
10145      break;
10146   case 0x302: //drdpq
10147      DIP( "drdpq%s fr%u,fr%u\n",
10148           flag_rC ? ".":"", frS_addr, frB_addr );
10149      assign( frB128, getDReg_pair( frB_addr ) );
10150      assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
10151      putDReg( frS_addr, mkexpr( frS64 ) );
10152      break;
10153   case 0x322: // dcffixq
10154     {
10155      /* Have to introduce an IOP for this instruction so it will work
10156       * on POWER 6 because emulating the instruction requires a POWER 7
10157       * DFP instruction in the emulation code.
10158       */
10159      DIP( "dcffixq%s fr%u,fr%u\n",
10160           flag_rC ? ".":"", frS_addr, frB_addr );
10161      assign( frB64, getDReg( frB_addr ) );
10162      assign( frS128, unop( Iop_I64StoD128,
10163                            unop( Iop_ReinterpD64asI64,
10164                                  mkexpr( frB64 ) ) ) );
10165      putDReg_pair( frS_addr, mkexpr( frS128 ) );
10166      break;
10167     }
10168   }
10169
10170   if (flag_rC && clear_CR1) {
10171      putCR321( 1, mkU8( 0 ) );
10172      putCR0( 1, mkU8( 0 ) );
10173   }
10174
10175   return True;
10176}
10177
10178static Bool dis_dfp_round( UInt theInstr ) {
10179   UChar frS_addr = ifieldRegDS(theInstr);
10180   UChar R        = IFIELD(theInstr, 16, 1);
10181   UChar RMC      = IFIELD(theInstr, 9, 2);
10182   UChar frB_addr = ifieldRegB( theInstr );
10183   UChar flag_rC  = ifieldBIT0( theInstr );
10184   IRTemp frB     = newTemp( Ity_D64 );
10185   IRTemp frS     = newTemp( Ity_D64 );
10186   UInt opc2      = ifieldOPClo8( theInstr );
10187   Bool clear_CR1 = True;
10188
10189   switch (opc2) {
10190   /* drintn, is the same as drintx.  The only difference is this
10191    * instruction does not generate an exception for an inexact operation.
10192    * Currently not supporting inexact exceptions.
10193    */
10194   case 0x63: // drintx
10195   case 0xE3: // drintn
10196      DIP( "drintx/drintn%s fr%u,fr%u\n",
10197           flag_rC ? ".":"", frS_addr, frB_addr );
10198
10199      /* NOTE, this instruction takes a DFP value and rounds to the
10200       * neares floating point integer value, i.e. fractional part
10201       * is zero.  The result is a floating point number.
10202       */
10203      /* pass the value of R and RMC in the same field */
10204      assign( frB, getDReg( frB_addr ) );
10205      assign( frS, binop( Iop_RoundD64toInt,
10206                          mkU32( ( R << 3 ) | RMC ),
10207                          mkexpr( frB ) ) );
10208      putDReg( frS_addr, mkexpr( frS ) );
10209      break;
10210   default:
10211      vex_printf("dis_dfp_round(ppc)(opc2)\n");
10212      return False;
10213   }
10214
10215   if (flag_rC && clear_CR1) {
10216      putCR321( 1, mkU8( 0 ) );
10217      putCR0( 1, mkU8( 0 ) );
10218   }
10219
10220   return True;
10221}
10222
10223static Bool dis_dfp_roundq(UInt theInstr) {
10224   UChar frS_addr = ifieldRegDS( theInstr );
10225   UChar frB_addr = ifieldRegB( theInstr );
10226   UChar R = IFIELD(theInstr, 16, 1);
10227   UChar RMC = IFIELD(theInstr, 9, 2);
10228   UChar flag_rC = ifieldBIT0( theInstr );
10229   IRTemp frB = newTemp( Ity_D128 );
10230   IRTemp frS = newTemp( Ity_D128 );
10231   Bool clear_CR1 = True;
10232   UInt opc2 = ifieldOPClo8( theInstr );
10233
10234   switch (opc2) {
10235   /* drintnq, is the same as drintxq.  The only difference is this
10236    * instruction does not generate an exception for an inexact operation.
10237    * Currently not supporting inexact exceptions.
10238    */
10239   case 0x63: // drintxq
10240   case 0xE3: // drintnq
10241      DIP( "drintxq/drintnq%s fr%u,fr%u\n",
10242           flag_rC ? ".":"", frS_addr, frB_addr );
10243
10244      /* pass the value of R and RMC in the same field */
10245      assign( frB, getDReg_pair( frB_addr ) );
10246      assign( frS, binop( Iop_RoundD128toInt,
10247                          mkU32( ( R << 3 ) | RMC ),
10248                          mkexpr( frB ) ) );
10249      putDReg_pair( frS_addr, mkexpr( frS ) );
10250      break;
10251   default:
10252      vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
10253      return False;
10254   }
10255
10256   if (flag_rC && clear_CR1) {
10257      putCR321( 1, mkU8( 0 ) );
10258      putCR0( 1, mkU8( 0 ) );
10259   }
10260
10261   return True;
10262}
10263
10264static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
10265   UInt opc2 = ifieldOPClo8( theInstr );
10266   UChar frS_addr = ifieldRegDS( theInstr );
10267   UChar frA_addr = ifieldRegA( theInstr );
10268   UChar frB_addr = ifieldRegB( theInstr );
10269   UChar flag_rC = ifieldBIT0( theInstr );
10270   UInt TE_value = IFIELD(theInstr, 16, 4);
10271   UInt TE_sign  = IFIELD(theInstr, 20, 1);
10272   UInt RMC = IFIELD(theInstr, 9, 2);
10273   IRTemp frA = newTemp( Ity_D64 );
10274   IRTemp frB = newTemp( Ity_D64 );
10275   IRTemp frS = newTemp( Ity_D64 );
10276   Bool clear_CR1 = True;
10277
10278   assign( frB, getDReg( frB_addr ) );
10279
10280   switch (opc2) {
10281   case 0x43: // dquai
10282      DIP( "dquai%s fr%u,fr%u,fr%u\n",
10283           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10284      IRTemp TE_I64 = newTemp( Ity_I64 );
10285
10286      /* Generate a reference DFP value frA with the desired exponent
10287       * given by TE using significand from frB.  Need to add the bias
10288       * 398 to TE.  TE is stored as a 2's complement number.
10289       */
10290      if (TE_sign == 1) {
10291         /* Take 2's complement of the 5-bit value and subtract from bias.
10292          *  Bias is adjusted for the +1 required when taking 2's complement.
10293          */
10294         assign( TE_I64,
10295                 unop( Iop_32Uto64,
10296                       binop( Iop_Sub32, mkU32( 397 ),
10297                              binop( Iop_And32, mkU32( 0xF ),
10298                                     unop( Iop_Not32, mkU32( TE_value ) )
10299                                     ) ) ) );
10300
10301      } else {
10302          assign( TE_I64,
10303                  unop( Iop_32Uto64,
10304                        binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
10305                        ) );
10306      }
10307
10308      assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
10309                          unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
10310
10311      assign( frS, triop( Iop_QuantizeD64,
10312                          mkU32( RMC ),
10313                          mkexpr( frA ),
10314                          mkexpr( frB ) ) );
10315      break;
10316
10317   case 0x3: // dqua
10318      DIP( "dqua%s fr%u,fr%u,fr%u\n",
10319           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10320      assign( frA, getDReg( frA_addr ) );
10321      assign( frS, triop( Iop_QuantizeD64,
10322                          mkU32( RMC ),
10323                          mkexpr( frA ),
10324                          mkexpr( frB ) ) );
10325      break;
10326   case 0x23: // drrnd
10327      {
10328         IRTemp tmp = newTemp( Ity_I8 );
10329
10330         DIP( "drrnd%s fr%u,fr%u,fr%u\n",
10331              flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10332         assign( frA, getDReg( frA_addr ) );
10333         /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
10334         assign( tmp, unop( Iop_32to8,
10335                            unop( Iop_64to32,
10336                                  unop( Iop_ReinterpD64asI64,
10337                                        mkexpr( frA ) ) ) ) );
10338         assign( frS, triop( Iop_SignificanceRoundD64,
10339                             mkU32( RMC ),
10340                             mkexpr( tmp ),
10341                             mkexpr( frB ) ) );
10342      }
10343      break;
10344   default:
10345      vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
10346      return False;
10347   }
10348   putDReg( frS_addr, mkexpr( frS ) );
10349
10350   if (flag_rC && clear_CR1) {
10351      putCR321( 1, mkU8( 0 ) );
10352      putCR0( 1, mkU8( 0 ) );
10353   }
10354
10355   return True;
10356}
10357
10358static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
10359   UInt opc2 = ifieldOPClo8( theInstr );
10360   UChar frS_addr = ifieldRegDS( theInstr );
10361   UChar frA_addr = ifieldRegA( theInstr );
10362   UChar frB_addr = ifieldRegB( theInstr );
10363   UChar flag_rC = ifieldBIT0( theInstr );
10364   UInt TE_value = IFIELD(theInstr, 16, 4);
10365   UInt TE_sign  = IFIELD(theInstr, 20, 1);
10366   UInt RMC = IFIELD(theInstr, 9, 2);
10367   IRTemp frA = newTemp( Ity_D128 );
10368   IRTemp frB = newTemp( Ity_D128 );
10369   IRTemp frS = newTemp( Ity_D128 );
10370   Bool clear_CR1 = True;
10371
10372   assign( frB, getDReg_pair( frB_addr ) );
10373
10374   switch (opc2) {
10375   case 0x43: // dquaiq
10376      DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10377           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10378      IRTemp TE_I64 = newTemp( Ity_I64 );
10379
10380      /* Generate a reference DFP value frA with the desired exponent
10381       * given by TE using significand of 1.  Need to add the bias
10382       * 6176 to TE.
10383       */
10384      if (TE_sign == 1) {
10385         /* Take 2's complement of the 5-bit value and subtract from bias.
10386          *  Bias adjusted for the +1 required when taking 2's complement.
10387          */
10388         assign( TE_I64,
10389                 unop( Iop_32Uto64,
10390                       binop( Iop_Sub32, mkU32( 6175 ),
10391                              binop( Iop_And32, mkU32( 0xF ),
10392                                     unop( Iop_Not32, mkU32( TE_value ) )
10393                                     ) ) ) );
10394
10395      } else {
10396         assign( TE_I64,
10397                 unop( Iop_32Uto64,
10398                       binop( Iop_Add32,
10399                             mkU32( 6176 ),
10400                             mkU32( TE_value ) ) ) );
10401      }
10402
10403      assign( frA,
10404              binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
10405                     unop( Iop_D64toD128,
10406                           unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
10407      assign( frS, triop( Iop_QuantizeD128,
10408                          mkU32( RMC ),
10409                          mkexpr( frA ),
10410                          mkexpr( frB ) ) );
10411      break;
10412   case 0x3: // dquaq
10413      DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10414           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10415      assign( frA, getDReg_pair( frA_addr ) );
10416      assign( frS, triop( Iop_QuantizeD128,
10417                          mkU32( RMC ),
10418                          mkexpr( frA ),
10419                          mkexpr( frB ) ) );
10420      break;
10421   case 0x23: // drrndq
10422      {
10423         IRTemp tmp = newTemp( Ity_I8 );
10424
10425         DIP( "drrndq%s fr%u,fr%u,fr%u\n",
10426              flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10427         assign( frA, getDReg_pair( frA_addr ) );
10428         assign( tmp, unop( Iop_32to8,
10429                            unop( Iop_64to32,
10430                                  unop( Iop_ReinterpD64asI64,
10431                                        unop( Iop_D128HItoD64,
10432                                              mkexpr( frA ) ) ) ) ) );
10433         assign( frS, triop( Iop_SignificanceRoundD128,
10434                             mkU32( RMC ),
10435                             mkexpr( tmp ),
10436                             mkexpr( frB ) ) );
10437      }
10438      break;
10439   default:
10440      vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
10441      return False;
10442   }
10443   putDReg_pair( frS_addr, mkexpr( frS ) );
10444
10445   if (flag_rC && clear_CR1) {
10446      putCR321( 1, mkU8( 0 ) );
10447      putCR0( 1, mkU8( 0 ) );
10448   }
10449
10450   return True;
10451}
10452
10453static Bool dis_dfp_extract_insert(UInt theInstr) {
10454   UInt opc2 = ifieldOPClo10( theInstr );
10455   UChar frS_addr = ifieldRegDS( theInstr );
10456   UChar frA_addr = ifieldRegA( theInstr );
10457   UChar frB_addr = ifieldRegB( theInstr );
10458   UChar flag_rC = ifieldBIT0( theInstr );
10459   Bool clear_CR1 = True;
10460
10461   IRTemp frA = newTemp( Ity_D64 );
10462   IRTemp frB = newTemp( Ity_D64 );
10463   IRTemp frS = newTemp( Ity_D64 );
10464   IRTemp tmp = newTemp( Ity_I64 );
10465
10466   assign( frA, getDReg( frA_addr ) );
10467   assign( frB, getDReg( frB_addr ) );
10468
10469   switch (opc2) {
10470   case 0x162: // dxex
10471      DIP( "dxex%s fr%u,fr%u,fr%u\n",
10472           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10473      assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
10474      assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10475      break;
10476   case 0x362: // diex
10477      DIP( "diex%s fr%u,fr%u,fr%u\n",
10478           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10479      assign( frS, binop( Iop_InsertExpD64,
10480                          unop( Iop_ReinterpD64asI64,
10481                                mkexpr( frA ) ),
10482                          mkexpr( frB ) ) );
10483      break;
10484   default:
10485      vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
10486      return False;
10487   }
10488
10489   putDReg( frS_addr, mkexpr( frS ) );
10490
10491   if (flag_rC && clear_CR1) {
10492      putCR321( 1, mkU8( 0 ) );
10493      putCR0( 1, mkU8( 0 ) );
10494   }
10495
10496   return True;
10497}
10498
10499static Bool dis_dfp_extract_insertq(UInt theInstr) {
10500   UInt opc2 = ifieldOPClo10( theInstr );
10501   UChar frS_addr = ifieldRegDS( theInstr );
10502   UChar frA_addr = ifieldRegA( theInstr );
10503   UChar frB_addr = ifieldRegB( theInstr );
10504   UChar flag_rC = ifieldBIT0( theInstr );
10505
10506   IRTemp frA   = newTemp( Ity_D64 );
10507   IRTemp frB   = newTemp( Ity_D128 );
10508   IRTemp frS64 = newTemp( Ity_D64 );
10509   IRTemp frS   = newTemp( Ity_D128 );
10510   IRTemp tmp   = newTemp( Ity_I64 );
10511   Bool clear_CR1 = True;
10512
10513   assign( frB, getDReg_pair( frB_addr ) );
10514
10515   switch (opc2) {
10516   case 0x162:  // dxexq
10517      DIP( "dxexq%s fr%u,fr%u\n",
10518           flag_rC ? ".":"", frS_addr,  frB_addr );
10519      /* Instruction actually returns a 64-bit result.  So as to be
10520       * consistent and not have to add a new struct, the emulation returns
10521       * the 64-bit result in the upper and lower register.
10522       */
10523      assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
10524      assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10525      putDReg( frS_addr, mkexpr( frS64 ) );
10526      break;
10527   case 0x362:  // diexq
10528      DIP( "diexq%s fr%u,fr%u,fr%u\n",
10529           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10530      assign( frA, getDReg( frA_addr ) );
10531      assign( frS, binop( Iop_InsertExpD128,
10532                          unop( Iop_ReinterpD64asI64, mkexpr( frA ) ),
10533                          mkexpr( frB ) ) );
10534      putDReg_pair( frS_addr, mkexpr( frS ) );
10535      break;
10536   default:
10537      vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
10538      return False;
10539   }
10540
10541   if (flag_rC && clear_CR1) {
10542      putCR321( 1, mkU8( 0 ) );
10543      putCR0( 1, mkU8( 0 ) );
10544   }
10545
10546   return True;
10547}
10548
10549/* DFP 64-bit comparison instructions */
10550static Bool dis_dfp_compare(UInt theInstr) {
10551   /* X-Form */
10552   UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
10553   UChar frA_addr = ifieldRegA( theInstr );
10554   UChar frB_addr = ifieldRegB( theInstr );
10555   UInt opc1 = ifieldOPC( theInstr );
10556   IRTemp frA;
10557   IRTemp frB;
10558
10559   IRTemp ccIR = newTemp( Ity_I32 );
10560   IRTemp ccPPC32 = newTemp( Ity_I32 );
10561
10562
10563   /* Note: Differences between dcmpu and dcmpo are only in exception
10564    flag settings, which aren't supported anyway. */
10565   switch (opc1) {
10566   case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
10567      DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
10568      frA = newTemp( Ity_D64 );
10569      frB = newTemp( Ity_D64 );
10570
10571      assign( frA, getDReg( frA_addr ) );
10572      assign( frB, getDReg( frB_addr ) );
10573
10574      assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
10575      break;
10576   case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
10577      DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
10578      frA = newTemp( Ity_D128 );
10579      frB = newTemp( Ity_D128 );
10580
10581      assign( frA, getDReg_pair( frA_addr ) );
10582      assign( frB, getDReg_pair( frB_addr ) );
10583      assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
10584      break;
10585   default:
10586      vex_printf("dis_dfp_compare(ppc)(opc2)\n");
10587      return False;
10588   }
10589
10590   /* Map compare result from IR to PPC32 */
10591   /*
10592    FP cmp result | PPC | IR
10593    --------------------------
10594    UN            | 0x1 | 0x45
10595    EQ            | 0x2 | 0x40
10596    GT            | 0x4 | 0x00
10597    LT            | 0x8 | 0x01
10598    */
10599
10600   assign( ccPPC32,
10601           binop( Iop_Shl32,
10602                  mkU32( 1 ),
10603                  unop( Iop_32to8,
10604                        binop( Iop_Or32,
10605                               binop( Iop_And32,
10606                                      unop( Iop_Not32,
10607                                            binop( Iop_Shr32,
10608                                                   mkexpr( ccIR ),
10609                                                   mkU8( 5 ) ) ),
10610                                      mkU32( 2 ) ),
10611                               binop( Iop_And32,
10612                                      binop( Iop_Xor32,
10613                                             mkexpr( ccIR ),
10614                                             binop( Iop_Shr32,
10615                                                    mkexpr( ccIR ),
10616                                                    mkU8( 6 ) ) ),
10617                                      mkU32( 1 ) ) ) ) ) );
10618
10619   putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
10620   return True;
10621}
10622
10623/* Test class/group/exponent/significance instructions. */
10624static Bool dis_dfp_exponent_test ( UInt theInstr )
10625{
10626   UChar frA_addr   = ifieldRegA( theInstr );
10627   UChar frB_addr   = ifieldRegB( theInstr );
10628   UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );
10629   IRTemp frA       = newTemp( Ity_D64 );
10630   IRTemp frB       = newTemp( Ity_D64 );
10631   IRTemp frA128    = newTemp( Ity_D128 );
10632   IRTemp frB128    = newTemp( Ity_D128 );
10633   UInt opc1        = ifieldOPC( theInstr );
10634   IRTemp gfield_A  = newTemp( Ity_I32 );
10635   IRTemp gfield_B  = newTemp( Ity_I32 );
10636   IRTemp gfield_mask   = newTemp( Ity_I32 );
10637   IRTemp exponent_A    = newTemp( Ity_I32 );
10638   IRTemp exponent_B    = newTemp( Ity_I32 );
10639   IRTemp A_NaN_true    = newTemp( Ity_I32 );
10640   IRTemp B_NaN_true    = newTemp( Ity_I32 );
10641   IRTemp A_inf_true    = newTemp( Ity_I32 );
10642   IRTemp B_inf_true    = newTemp( Ity_I32 );
10643   IRTemp A_equals_B    = newTemp( Ity_I32 );
10644   IRTemp finite_number = newTemp( Ity_I32 );
10645   IRTemp cc0 = newTemp( Ity_I32 );
10646   IRTemp cc1 = newTemp( Ity_I32 );
10647   IRTemp cc2 = newTemp( Ity_I32 );
10648   IRTemp cc3 = newTemp( Ity_I32 );
10649
10650   /* The dtstex and dtstexg instructions only differ in the size of the
10651    * exponent field.  The following switch statement takes care of the size
10652    * specific setup.  Once the value of the exponents, the G-field shift
10653    * and mask is setup the remaining code is identical.
10654    */
10655   switch (opc1) {
10656   case 0x3b: // dtstex       Extended instruction setup
10657      DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
10658      assign( frA, getDReg( frA_addr ) );
10659      assign( frB, getDReg( frB_addr ) );
10660      assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
10661      assign(exponent_A, unop( Iop_64to32,
10662                               unop( Iop_ExtractExpD64,
10663                                     mkexpr( frA ) ) ) );
10664      assign(exponent_B, unop( Iop_64to32,
10665                               unop( Iop_ExtractExpD64,
10666                                     mkexpr( frB ) ) ) );
10667      break;
10668
10669   case 0x3F: //  dtstexq      Quad instruction setup
10670      DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
10671      assign( frA128, getDReg_pair( frA_addr ) );
10672      assign( frB128, getDReg_pair( frB_addr ) );
10673      assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
10674      assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
10675      assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
10676      assign( exponent_A, unop( Iop_64to32,
10677                                unop( Iop_ExtractExpD128,
10678                                      mkexpr( frA128 ) ) ) );
10679      assign( exponent_B, unop( Iop_64to32,
10680                                unop( Iop_ExtractExpD128,
10681                                      mkexpr( frB128 ) ) ) );
10682      break;
10683   default:
10684      vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
10685      return False;
10686   }
10687
10688   /* Extract the Gfield */
10689   assign( gfield_A, binop( Iop_And32,
10690                            mkexpr( gfield_mask ),
10691                            unop( Iop_64HIto32,
10692                                  unop( Iop_ReinterpD64asI64,
10693                                        mkexpr(frA) ) ) ) );
10694
10695   assign( gfield_B, binop( Iop_And32,
10696                            mkexpr( gfield_mask ),
10697                            unop( Iop_64HIto32,
10698                                  unop( Iop_ReinterpD64asI64,
10699                                        mkexpr(frB) ) ) ) );
10700
10701   /* check for NAN */
10702   assign( A_NaN_true, binop(Iop_Or32,
10703                             unop( Iop_1Sto32,
10704                                   binop( Iop_CmpEQ32,
10705                                          mkexpr( gfield_A ),
10706                                          mkU32( 0x7C000000 ) ) ),
10707                             unop( Iop_1Sto32,
10708                                   binop( Iop_CmpEQ32,
10709                                          mkexpr( gfield_A ),
10710                                          mkU32( 0x7E000000 ) )
10711                                   ) ) );
10712   assign( B_NaN_true, binop(Iop_Or32,
10713                             unop( Iop_1Sto32,
10714                                   binop( Iop_CmpEQ32,
10715                                          mkexpr( gfield_B ),
10716                                          mkU32( 0x7C000000 ) ) ),
10717                             unop( Iop_1Sto32,
10718                                   binop( Iop_CmpEQ32,
10719                                          mkexpr( gfield_B ),
10720                                          mkU32( 0x7E000000 ) )
10721                             ) ) );
10722
10723   /* check for infinity */
10724   assign( A_inf_true,
10725           unop( Iop_1Sto32,
10726                 binop( Iop_CmpEQ32,
10727                        mkexpr( gfield_A ),
10728                        mkU32( 0x78000000 ) ) ) );
10729
10730   assign( B_inf_true,
10731           unop( Iop_1Sto32,
10732                 binop( Iop_CmpEQ32,
10733                        mkexpr( gfield_B ),
10734                        mkU32( 0x78000000 ) ) ) );
10735
10736   assign( finite_number,
10737           unop( Iop_Not32,
10738                 binop( Iop_Or32,
10739                        binop( Iop_Or32,
10740                               mkexpr( A_NaN_true ),
10741                               mkexpr( B_NaN_true ) ),
10742                        binop( Iop_Or32,
10743                               mkexpr( A_inf_true ),
10744                               mkexpr( B_inf_true ) ) ) ) );
10745
10746   /* Calculate the condition code bits
10747    * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
10748    * regardless of the value of the comparisons and cc3 is 1.  Otherwise,
10749    * cc0, cc1 and cc0 reflect the results of the comparisons.
10750    */
10751   assign( A_equals_B,
10752           binop( Iop_Or32,
10753                  unop( Iop_1Uto32,
10754                  binop( Iop_CmpEQ32,
10755                         mkexpr( exponent_A ),
10756                         mkexpr( exponent_B ) ) ),
10757                  binop( Iop_Or32,
10758                         binop( Iop_And32,
10759                                mkexpr( A_inf_true ),
10760                                mkexpr( B_inf_true ) ),
10761                         binop( Iop_And32,
10762                                mkexpr( A_NaN_true ),
10763                                mkexpr( B_NaN_true ) ) ) ) );
10764
10765   assign( cc0, binop( Iop_And32,
10766                       mkexpr( finite_number ),
10767                       binop( Iop_Shl32,
10768                              unop( Iop_1Uto32,
10769                                    binop( Iop_CmpLT32U,
10770                                           mkexpr( exponent_A ),
10771                                           mkexpr( exponent_B ) ) ),
10772                                           mkU8( 3 ) ) ) );
10773
10774   assign( cc1, binop( Iop_And32,
10775                       mkexpr( finite_number ),
10776                       binop( Iop_Shl32,
10777                              unop( Iop_1Uto32,
10778                                    binop( Iop_CmpLT32U,
10779                                           mkexpr( exponent_B ),
10780                                           mkexpr( exponent_A ) ) ),
10781                                           mkU8( 2 ) ) ) );
10782
10783   assign( cc2, binop( Iop_Shl32,
10784                       binop( Iop_And32,
10785                              mkexpr( A_equals_B ),
10786                              mkU32( 1 ) ),
10787                              mkU8( 1 ) ) );
10788
10789   assign( cc3, binop( Iop_And32,
10790                       unop( Iop_Not32, mkexpr( A_equals_B ) ),
10791                       binop( Iop_And32,
10792                              mkU32( 0x1 ),
10793                              binop( Iop_Or32,
10794                                     binop( Iop_Or32,
10795                                            mkexpr ( A_inf_true ),
10796                                            mkexpr ( B_inf_true ) ),
10797                                            binop( Iop_Or32,
10798                                                   mkexpr ( A_NaN_true ),
10799                                                   mkexpr ( B_NaN_true ) ) )
10800                              ) ) );
10801
10802   /* store the condition code */
10803   putGST_field( PPC_GST_CR,
10804                 binop( Iop_Or32,
10805                        mkexpr( cc0 ),
10806                        binop( Iop_Or32,
10807                               mkexpr( cc1 ),
10808                               binop( Iop_Or32,
10809                                      mkexpr( cc2 ),
10810                                      mkexpr( cc3 ) ) ) ),
10811                 crfD );
10812   return True;
10813}
10814
10815/* Test class/group/exponent/significance instructions. */
10816static Bool dis_dfp_class_test ( UInt theInstr )
10817{
10818   UChar frA_addr   = ifieldRegA( theInstr );
10819   IRTemp frA       = newTemp( Ity_D64 );
10820   IRTemp abs_frA   = newTemp( Ity_D64 );
10821   IRTemp frAI64_hi = newTemp( Ity_I64 );
10822   IRTemp frAI64_lo = newTemp( Ity_I64 );
10823   UInt opc1        = ifieldOPC( theInstr );
10824   UInt opc2        = ifieldOPClo9( theInstr );
10825   UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );  // AKA BF
10826   UInt DCM         = IFIELD( theInstr, 10, 6 );
10827   IRTemp DCM_calc  = newTemp( Ity_I32 );
10828   UInt max_exp     = 0;
10829   UInt min_exp     = 0;
10830   IRTemp min_subnormalD64  = newTemp( Ity_D64 );
10831   IRTemp min_subnormalD128 = newTemp( Ity_D128 );
10832   IRTemp significand64  = newTemp( Ity_D64 );
10833   IRTemp significand128 = newTemp( Ity_D128 );
10834   IRTemp exp_min_normal = newTemp( Ity_I64 );
10835   IRTemp exponent       = newTemp( Ity_I32 );
10836
10837   IRTemp infinity_true  = newTemp( Ity_I32 );
10838   IRTemp SNaN_true      = newTemp( Ity_I32 );
10839   IRTemp QNaN_true      = newTemp( Ity_I32 );
10840   IRTemp subnormal_true = newTemp( Ity_I32 );
10841   IRTemp normal_true    = newTemp( Ity_I32 );
10842   IRTemp extreme_true   = newTemp( Ity_I32 );
10843   IRTemp lmd            = newTemp( Ity_I32 );
10844   IRTemp lmd_zero_true  = newTemp( Ity_I32 );
10845   IRTemp zero_true      = newTemp( Ity_I32 );
10846   IRTemp sign           = newTemp( Ity_I32 );
10847   IRTemp field          = newTemp( Ity_I32 );
10848   IRTemp ccIR_zero      = newTemp( Ity_I32 );
10849   IRTemp ccIR_subnormal = newTemp( Ity_I32 );
10850
10851   /* UInt size     = DFP_LONG;  JRS:unused */
10852   IRTemp gfield = newTemp( Ity_I32 );
10853   IRTemp gfield_0_4_shift  = newTemp( Ity_I8 );
10854   IRTemp gfield_mask       = newTemp( Ity_I32 );
10855   IRTemp dcm0 = newTemp( Ity_I32 );
10856   IRTemp dcm1 = newTemp( Ity_I32 );
10857   IRTemp dcm2 = newTemp( Ity_I32 );
10858   IRTemp dcm3 = newTemp( Ity_I32 );
10859   IRTemp dcm4 = newTemp( Ity_I32 );
10860   IRTemp dcm5 = newTemp( Ity_I32 );
10861
10862   /* The only difference between the dtstdc and dtstdcq instructions is
10863    * size of the T and G fields.  The calculation of the 4 bit field
10864    * is the same.  Setup the parameters and values that are DFP size
10865    * specific.  The rest of the code is independent of the DFP size.
10866    *
10867    * The Io_CmpD64 is used below.  The instruction sets the ccIR values.
10868    * The interpretation of the ccIR values is as follows:
10869    *
10870    *    DFP cmp result | IR
10871    * --------------------------
10872    *	 UN             | 0x45
10873    *	 EQ             | 0x40
10874    *	 GT             | 0x00
10875    *	 LT             | 0x01
10876    */
10877
10878   assign( frA, getDReg( frA_addr ) );
10879   assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
10880
10881   assign( abs_frA, unop( Iop_ReinterpI64asD64,
10882                          binop( Iop_And64,
10883                                 unop( Iop_ReinterpD64asI64,
10884                                       mkexpr( frA ) ),
10885                                 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
10886   assign( gfield_0_4_shift, mkU8( 31 - 5 ) );  // G-field[0:4]
10887   switch (opc1) {
10888   case 0x3b: // dtstdc, dtstdg
10889      DIP("dtstd%s %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g",
10890               crfD, frA_addr, DCM);
10891      /* setup the parameters for the long format of the two instructions */
10892      assign( frAI64_lo, mkU64( 0 ) );
10893      assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
10894      max_exp = DFP_LONG_EXP_MAX;
10895      min_exp = DFP_LONG_EXP_MIN;
10896
10897      assign( exponent, unop( Iop_64to32,
10898                              unop( Iop_ExtractExpD64,
10899                                    mkexpr( frA ) ) ) );
10900      assign( significand64,
10901              unop( Iop_ReinterpI64asD64,
10902                    mkU64( 0x2234000000000001ULL ) ) );  // dfp 1.0
10903      assign( exp_min_normal,mkU64( 398 - 383 ) );
10904      assign( min_subnormalD64,
10905              binop( Iop_InsertExpD64,
10906                     mkexpr( exp_min_normal ),
10907                     mkexpr( significand64 ) ) );
10908
10909      assign( ccIR_subnormal,
10910              binop( Iop_CmpD64,
10911                     mkexpr( abs_frA ),
10912                     mkexpr( min_subnormalD64 ) ) );
10913
10914      /* compare absolute value of frA with zero */
10915      assign( ccIR_zero,
10916              binop( Iop_CmpD64,
10917                     mkexpr( abs_frA ),
10918                     unop( Iop_ReinterpI64asD64,
10919                           mkU64( 0x2238000000000000ULL ) ) ) );
10920
10921      /* size = DFP_LONG; JRS: unused */
10922      break;
10923
10924   case 0x3F:   // dtstdcq, dtstdgq
10925      DIP("dtstd%sq %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g",
10926               crfD, frA_addr, DCM);
10927      /* setup the parameters for the extended format of the
10928       * two instructions
10929       */
10930      assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
10931                               getDReg( frA_addr+1 ) ) );
10932
10933      assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
10934      max_exp = DFP_EXTND_EXP_MAX;
10935      min_exp = DFP_EXTND_EXP_MIN;
10936      assign( exponent, unop( Iop_64to32,
10937                              unop( Iop_ExtractExpD128,
10938                                    getDReg_pair( frA_addr) ) ) );
10939
10940      /* create quand exponent for minimum normal number */
10941      assign( exp_min_normal, mkU64( 6176 - 6143 ) );
10942      assign( significand128,
10943              unop( Iop_D64toD128,
10944                    unop( Iop_ReinterpI64asD64,
10945                          mkU64( 0x2234000000000001ULL ) ) ) );  // dfp 1.0
10946
10947      assign( min_subnormalD128,
10948              binop( Iop_InsertExpD128,
10949                     mkexpr( exp_min_normal ),
10950                     mkexpr( significand128 ) ) );
10951
10952      assign( ccIR_subnormal,
10953              binop( Iop_CmpD128,
10954                     binop( Iop_D64HLtoD128,
10955                            unop( Iop_ReinterpI64asD64,
10956                                  binop( Iop_And64,
10957                                         unop( Iop_ReinterpD64asI64,
10958                                               mkexpr( frA ) ),
10959                                         mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
10960                            getDReg( frA_addr+1 ) ),
10961                     mkexpr( min_subnormalD128 ) ) );
10962      assign( ccIR_zero,
10963              binop( Iop_CmpD128,
10964                     binop( Iop_D64HLtoD128,
10965                            mkexpr( abs_frA ),
10966                            getDReg( frA_addr+1 ) ),
10967                     unop( Iop_D64toD128,
10968                           unop( Iop_ReinterpI64asD64,
10969                                 mkU64( 0x0ULL ) ) ) ) );
10970
10971      /* size = DFP_EXTND; JRS:unused */
10972      break;
10973   default:
10974      vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
10975      return False;
10976   }
10977
10978   /* The G-field is in the upper 32-bits.  The I64 logical operations
10979    * do not seem to be supported in 32-bit mode so keep things as 32-bit
10980    * operations.
10981    */
10982   assign( gfield, binop( Iop_And32,
10983                          mkexpr( gfield_mask ),
10984                          unop( Iop_64HIto32,
10985                                mkexpr(frAI64_hi) ) ) );
10986
10987   /* There is a lot of code that is the same to do the class and group
10988    * instructions.  Later there is an if statement to handle the specific
10989    * instruction.
10990    *
10991    * Will be using I32 values, compares, shifts and logical operations for
10992    * this code as the 64-bit compare, shifts, logical operations are not
10993    * supported in 32-bit mode.
10994    */
10995
10996   /* Check the bits for Infinity, QNaN or Signaling NaN */
10997   assign( infinity_true,
10998           unop( Iop_1Sto32,
10999                 binop( Iop_CmpEQ32,
11000                        binop( Iop_And32,
11001                               mkU32( 0x7C000000 ),
11002                               mkexpr( gfield ) ),
11003                        mkU32( 0x78000000 ) ) ) );
11004
11005   assign( SNaN_true,
11006           unop( Iop_1Sto32,
11007                 binop( Iop_CmpEQ32,
11008                        binop( Iop_And32,
11009                               mkU32( 0x7E000000 ),
11010                               mkexpr( gfield ) ),
11011                        mkU32( 0x7E000000 ) ) ) );
11012
11013   assign( QNaN_true,
11014           binop( Iop_And32,
11015                  unop( Iop_1Sto32,
11016                       binop( Iop_CmpEQ32,
11017                              binop( Iop_And32,
11018                                     mkU32( 0x7E000000 ),
11019                                     mkexpr( gfield ) ),
11020                              mkU32( 0x7C000000 ) ) ),
11021                  unop( Iop_Not32,
11022                        mkexpr( SNaN_true ) ) ) );
11023
11024   assign( zero_true,
11025           binop( Iop_And32,
11026                  unop(Iop_1Sto32,
11027                       binop( Iop_CmpEQ32,
11028                              mkexpr( ccIR_zero ),
11029                              mkU32( 0x40 ) ) ),  // ccIR code for Equal
11030                  unop( Iop_Not32,
11031                        binop( Iop_Or32,
11032                               mkexpr( infinity_true ),
11033                               binop( Iop_Or32,
11034                                      mkexpr( QNaN_true ),
11035                                      mkexpr( SNaN_true ) ) ) ) ) );
11036
11037   /* Do compare of frA the minimum normal value.  Comparison is size
11038    * depenent and was done above to get the ccIR value.
11039    */
11040   assign( subnormal_true,
11041           binop( Iop_And32,
11042                  binop( Iop_Or32,
11043                         unop( Iop_1Sto32,
11044                               binop( Iop_CmpEQ32,
11045                                      mkexpr( ccIR_subnormal ),
11046                                      mkU32( 0x40 ) ) ), // ccIR code for Equal
11047                         unop( Iop_1Sto32,
11048                               binop( Iop_CmpEQ32,
11049                                      mkexpr( ccIR_subnormal ),
11050                                      mkU32( 0x1 ) ) ) ), // ccIR code for LT
11051           unop( Iop_Not32,
11052                 binop( Iop_Or32,
11053                        binop( Iop_Or32,
11054                               mkexpr( infinity_true ),
11055                               mkexpr( zero_true) ),
11056                        binop( Iop_Or32,
11057                               mkexpr( QNaN_true ),
11058                               mkexpr( SNaN_true ) ) ) ) ) );
11059
11060   /* Normal number is not subnormal, infinity, NaN or Zero */
11061   assign( normal_true,
11062           unop( Iop_Not32,
11063                 binop( Iop_Or32,
11064                        binop( Iop_Or32,
11065                               mkexpr( infinity_true ),
11066                               mkexpr( zero_true ) ),
11067                        binop( Iop_Or32,
11068                               mkexpr( subnormal_true ),
11069                               binop( Iop_Or32,
11070                                      mkexpr( QNaN_true ),
11071                                      mkexpr( SNaN_true ) ) ) ) ) );
11072
11073   /* Calculate the DCM bit field based on the tests for the specific
11074    * instruction
11075    */
11076   if (opc2 == 0xC2) {    // dtstdc, dtstdcq
11077      /* DCM[0:5] Bit   Data Class definition
11078       *   0   Zero
11079       *   1   Subnormal
11080       *   2   Normal
11081       *   3   Infinity
11082       *   4   Quiet NaN
11083       *   5   Signaling NaN
11084       */
11085
11086      assign( dcm0, binop( Iop_Shl32,
11087                           mkexpr( zero_true ),
11088                           mkU8( 5 ) ) );
11089      assign( dcm1, binop( Iop_Shl32,
11090                           binop( Iop_And32,
11091                                  mkexpr( subnormal_true ),
11092                                  mkU32( 1 ) ),
11093                           mkU8( 4 ) ) );
11094      assign( dcm2, binop( Iop_Shl32,
11095                           binop( Iop_And32,
11096                                  mkexpr( normal_true ),
11097                                  mkU32( 1 ) ),
11098                           mkU8( 3 ) ) );
11099      assign( dcm3, binop( Iop_Shl32,
11100                           binop( Iop_And32,
11101                                  mkexpr( infinity_true),
11102                                  mkU32( 1 ) ),
11103                           mkU8( 2 ) ) );
11104      assign( dcm4, binop( Iop_Shl32,
11105                           binop( Iop_And32,
11106                                  mkexpr( QNaN_true ),
11107                                  mkU32( 1 ) ),
11108                           mkU8( 1 ) ) );
11109      assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
11110
11111   } else if (opc2 == 0xE2) {   // dtstdg, dtstdgq
11112      /* check if the exponent is extreme */
11113      assign( extreme_true, binop( Iop_Or32,
11114                                   unop( Iop_1Sto32,
11115                                         binop( Iop_CmpEQ32,
11116                                                mkexpr( exponent ),
11117                                                mkU32( max_exp ) ) ),
11118                                   unop( Iop_1Sto32,
11119                                         binop( Iop_CmpEQ32,
11120                                                mkexpr( exponent ),
11121                                                mkU32( min_exp ) ) ) ) );
11122
11123      /* Check if LMD is zero */
11124      Get_lmd( &lmd, binop( Iop_Shr32,
11125                            mkexpr( gfield ), mkU8( 31 - 5 ) ) );
11126
11127      assign( lmd_zero_true, unop( Iop_1Sto32,
11128                                   binop( Iop_CmpEQ32,
11129                                          mkexpr( lmd ),
11130                                          mkU32( 0 ) ) ) );
11131
11132      /* DCM[0:5] Bit   Data Class definition
11133       *  0   Zero with non-extreme exponent
11134       *  1   Zero with extreme exponent
11135       *  2   Subnormal or (Normal with extreme exponent)
11136       *  3   Normal with non-extreme exponent and
11137       *      leftmost zero digit in significand
11138       *  4   Normal with non-extreme exponent and
11139       *      leftmost nonzero digit in significand
11140       *  5   Special symbol (Infinity, QNaN, or SNaN)
11141       */
11142      assign( dcm0, binop( Iop_Shl32,
11143                           binop( Iop_And32,
11144                                  binop( Iop_And32,
11145                                         unop( Iop_Not32,
11146                                               mkexpr( extreme_true ) ),
11147                                         mkexpr( zero_true ) ),
11148                                  mkU32( 0x1 ) ),
11149                           mkU8( 5 ) ) );
11150
11151      assign( dcm1, binop( Iop_Shl32,
11152                           binop( Iop_And32,
11153                                  binop( Iop_And32,
11154                                         mkexpr( extreme_true ),
11155                                         mkexpr( zero_true ) ),
11156                                  mkU32( 0x1 ) ),
11157                           mkU8( 4 ) ) );
11158
11159      assign( dcm2, binop( Iop_Shl32,
11160                           binop( Iop_And32,
11161                                  binop( Iop_Or32,
11162                                         binop( Iop_And32,
11163                                                mkexpr( extreme_true ),
11164                                                mkexpr( normal_true ) ),
11165                                         mkexpr( subnormal_true ) ),
11166                                  mkU32( 0x1 ) ),
11167                           mkU8( 3 ) ) );
11168
11169      assign( dcm3, binop( Iop_Shl32,
11170                           binop( Iop_And32,
11171                                  binop( Iop_And32,
11172                                         binop( Iop_And32,
11173                                                unop( Iop_Not32,
11174                                                      mkexpr( extreme_true ) ),
11175                                                      mkexpr( normal_true ) ),
11176                                         unop( Iop_1Sto32,
11177                                               binop( Iop_CmpEQ32,
11178                                                      mkexpr( lmd ),
11179                                                      mkU32( 0 ) ) ) ),
11180                                  mkU32( 0x1 ) ),
11181                           mkU8( 2 ) ) );
11182
11183      assign( dcm4, binop( Iop_Shl32,
11184                           binop( Iop_And32,
11185                                  binop( Iop_And32,
11186                                         binop( Iop_And32,
11187                                                unop( Iop_Not32,
11188                                                      mkexpr( extreme_true ) ),
11189                                                mkexpr( normal_true ) ),
11190                                          unop( Iop_1Sto32,
11191                                                binop( Iop_CmpNE32,
11192                                                       mkexpr( lmd ),
11193                                                       mkU32( 0 ) ) ) ),
11194                                  mkU32( 0x1 ) ),
11195                           mkU8( 1 ) ) );
11196
11197      assign( dcm5, binop( Iop_And32,
11198                           binop( Iop_Or32,
11199                                  mkexpr( SNaN_true),
11200                                  binop( Iop_Or32,
11201                                         mkexpr( QNaN_true),
11202                                         mkexpr( infinity_true) ) ),
11203                           mkU32( 0x1 ) ) );
11204   }
11205
11206   /* create DCM field */
11207   assign( DCM_calc,
11208           binop( Iop_Or32,
11209                  mkexpr( dcm0 ),
11210                  binop( Iop_Or32,
11211                         mkexpr( dcm1 ),
11212                         binop( Iop_Or32,
11213                                mkexpr( dcm2 ),
11214                                binop( Iop_Or32,
11215                                       mkexpr( dcm3 ),
11216                                       binop( Iop_Or32,
11217                                              mkexpr( dcm4 ),
11218                                              mkexpr( dcm5 ) ) ) ) ) ) );
11219
11220   /* Get the sign of the DFP number, ignore sign for QNaN */
11221   assign( sign,
11222           unop( Iop_1Uto32,
11223                 binop( Iop_CmpEQ32,
11224                        binop( Iop_Shr32,
11225                               unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
11226                               mkU8( 63 - 32 ) ),
11227                        mkU32( 1 ) ) ) );
11228
11229   /* This instruction generates a four bit field to be stored in the
11230    * condition code register.  The condition code register consists of 7
11231    * fields.  The field to be written to is specified by the BF (AKA crfD)
11232    * field.
11233    *
11234    * The field layout is as follows:
11235    *
11236    *      Field          Meaning
11237    *      0000           Operand positive with no match
11238    *      0100           Operand positive with at least one match
11239    *      0001           Operand negative with no match
11240    *      0101           Operand negative with at least one match
11241    */
11242   assign( field, binop( Iop_Or32,
11243                         binop( Iop_Shl32,
11244                                mkexpr( sign ),
11245                                mkU8( 3 ) ),
11246                                binop( Iop_Shl32,
11247                                       unop( Iop_1Uto32,
11248                                             binop( Iop_CmpNE32,
11249                                                    binop( Iop_And32,
11250                                                           mkU32( DCM ),
11251                                                           mkexpr( DCM_calc ) ),
11252                                                     mkU32( 0 ) ) ),
11253                                       mkU8( 1 ) ) ) );
11254
11255   putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
11256   return True;
11257}
11258
11259static Bool dis_dfp_bcd(UInt theInstr) {
11260   UInt opc2        = ifieldOPClo10( theInstr );
11261   ULong sp         = IFIELD(theInstr, 19, 2);
11262   ULong s          = IFIELD(theInstr, 20, 1);
11263   UChar frT_addr   = ifieldRegDS( theInstr );
11264   UChar frB_addr   = ifieldRegB( theInstr );
11265   IRTemp frB       = newTemp( Ity_D64 );
11266   IRTemp frBI64    = newTemp( Ity_I64 );
11267   IRTemp result    = newTemp( Ity_I64 );
11268   IRTemp resultD64 = newTemp( Ity_D64 );
11269   IRTemp bcd64     = newTemp( Ity_I64 );
11270   IRTemp bcd_u     = newTemp( Ity_I32 );
11271   IRTemp bcd_l     = newTemp( Ity_I32 );
11272   IRTemp dbcd_u    = newTemp( Ity_I32 );
11273   IRTemp dbcd_l    = newTemp( Ity_I32 );
11274   IRTemp lmd       = newTemp( Ity_I32 );
11275
11276   assign( frB, getDReg( frB_addr ) );
11277   assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
11278
11279   switch ( opc2 ) {
11280   case 0x142: // ddedpd   DFP Decode DPD to BCD
11281      DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
11282
11283         assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
11284         assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
11285         assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
11286
11287      if ( ( sp == 0 ) || ( sp == 1 ) ) {
11288         /* Unsigned BCD string */
11289         Get_lmd( &lmd,
11290                  binop( Iop_Shr32,
11291                         unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11292                         mkU8( 31 - 5 ) ) ); // G-field[0:4]
11293
11294         assign( result,
11295                 binop( Iop_32HLto64,
11296                        binop( Iop_Or32,
11297                               binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
11298                               mkexpr( bcd_u ) ),
11299                        mkexpr( bcd_l ) ) );
11300
11301      } else {
11302         /* Signed BCD string, the cases for sp 2 and 3 only differ in how
11303          * the positive and negative values are encoded in the least
11304          * significant bits.
11305          */
11306         IRTemp sign = newTemp( Ity_I32 );
11307
11308         if (sp == 2) {
11309            /* Positive sign = 0xC, negative sign = 0xD */
11310
11311            assign( sign,
11312                    binop( Iop_Or32,
11313                           binop( Iop_Shr32,
11314                                  unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11315                                  mkU8( 31 ) ),
11316                           mkU32( 0xC ) ) );
11317
11318         } else if ( sp == 3 ) {
11319            /* Positive sign = 0xF, negative sign = 0xD */
11320            IRTemp tmp32 = newTemp( Ity_I32 );
11321
11322            /* Complement sign bit then OR into bit position 1 */
11323            assign( tmp32,
11324                    binop( Iop_Xor32,
11325                           binop( Iop_Shr32,
11326                                  unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11327                                  mkU8( 30 ) ),
11328                           mkU32( 0x2 ) ) );
11329
11330            assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
11331
11332         } else {
11333            vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
11334         }
11335
11336         /* Put sign in bottom 4 bits, move most significant 4-bits from
11337          * bcd_l to bcd_u.
11338          */
11339         assign( result,
11340                 binop( Iop_32HLto64,
11341                        binop( Iop_Or32,
11342                               binop( Iop_Shr32,
11343                                      mkexpr( bcd_l ),
11344                                      mkU8( 28 ) ),
11345                               binop( Iop_Shl32,
11346                                      mkexpr( bcd_u ),
11347                                      mkU8( 4 ) ) ),
11348                        binop( Iop_Or32,
11349                                      mkexpr( sign ),
11350                               binop( Iop_Shl32,
11351                                      mkexpr( bcd_l ),
11352                                      mkU8( 4 ) ) ) ) );
11353      }
11354
11355      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
11356      break;
11357
11358   case 0x342: // denbcd   DFP Encode BCD to DPD
11359   {
11360      IRTemp valid_mask   = newTemp( Ity_I32 );
11361      IRTemp invalid_mask = newTemp( Ity_I32 );
11362      IRTemp without_lmd  = newTemp( Ity_I64 );
11363      IRTemp tmp64        = newTemp( Ity_I64 );
11364      IRTemp dbcd64       = newTemp( Ity_I64 );
11365      IRTemp left_exp     = newTemp( Ity_I32 );
11366      IRTemp g0_4         = newTemp( Ity_I32 );
11367
11368      DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
11369
11370      if ( s == 0 ) {
11371         /* Unsigned BCD string */
11372         assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
11373         assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
11374         assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
11375
11376         assign( lmd,
11377                 binop( Iop_Shr32,
11378                        binop( Iop_And32,
11379                               unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11380                               mkU32( 0xF0000000 ) ),
11381                        mkU8( 28 ) ) );
11382
11383         assign( invalid_mask,
11384                 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11385                                  unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
11386         assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
11387
11388         assign( without_lmd,
11389                 unop( Iop_ReinterpD64asI64,
11390                       binop( Iop_InsertExpD64,
11391                              mkU64( DFP_LONG_BIAS ),
11392                              unop( Iop_ReinterpI64asD64,
11393                                    binop( Iop_32HLto64,
11394                                           mkexpr( dbcd_u ),
11395                                           mkexpr( dbcd_l ) ) ) ) ) );
11396         assign( left_exp,
11397                 binop( Iop_Shr32,
11398                        binop( Iop_And32,
11399                               unop( Iop_64HIto32, mkexpr( without_lmd ) ),
11400                               mkU32( 0x60000000 ) ),
11401                        mkU8( 29 ) ) );
11402
11403         assign( g0_4,
11404                 binop( Iop_Shl32,
11405                        Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
11406                        mkU8( 26 ) ) );
11407
11408         assign( tmp64,
11409                 binop( Iop_32HLto64,
11410                        binop( Iop_Or32,
11411                               binop( Iop_And32,
11412                                      unop( Iop_64HIto32,
11413                                            mkexpr( without_lmd ) ),
11414                                      mkU32( 0x83FFFFFF ) ),
11415                               mkexpr( g0_4 ) ),
11416                        unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
11417
11418      } else if ( s == 1 ) {
11419         IRTemp sign = newTemp( Ity_I32 );
11420         IRTemp sign_bit = newTemp( Ity_I32 );
11421         IRTemp pos_sign_mask = newTemp( Ity_I32 );
11422         IRTemp neg_sign_mask = newTemp( Ity_I32 );
11423         IRTemp tmp = newTemp( Ity_I64 );
11424
11425         /* Signed BCD string, least significant 4 bits are sign bits
11426          * positive sign = 0xC, negative sign = 0xD
11427          */
11428         assign( tmp, unop( Iop_BCDtoDPB,
11429                            binop( Iop_32HLto64,
11430                                   binop( Iop_Shr32,
11431                                          unop( Iop_64HIto32,
11432                                                mkexpr( frBI64 ) ),
11433                                                mkU8( 4 ) ),
11434                                   binop( Iop_Or32,
11435                                          binop( Iop_Shr32,
11436                                                 unop( Iop_64to32,
11437                                                       mkexpr( frBI64 ) ),
11438                                                  mkU8( 4 ) ),
11439                                          binop( Iop_Shl32,
11440                                                 unop( Iop_64HIto32,
11441                                                       mkexpr( frBI64 ) ),
11442                                                       mkU8( 28 ) ) ) ) ) );
11443
11444         assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
11445         assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
11446
11447         /* Get the sign of the BCD string. */
11448         assign( sign,
11449                 binop( Iop_And32,
11450                        unop( Iop_64to32, mkexpr( frBI64 ) ),
11451                        mkU32( 0xF ) ) );
11452
11453         assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
11454         assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
11455         assign( sign_bit,
11456                 Generate_sign_bit( mkexpr( pos_sign_mask ),
11457                                    mkexpr( neg_sign_mask ) ) );
11458
11459         /* Check for invalid sign and BCD digit.  Don't check the bottom
11460          * four bits of bcd_l as that is the sign value.
11461          */
11462         assign( invalid_mask,
11463                 Generate_inv_mask(
11464                                   bcd_digit_inval( unop( Iop_64HIto32,
11465                                                          mkexpr( frBI64 ) ),
11466                                                    binop( Iop_Shr32,
11467                                                           unop( Iop_64to32,
11468                                                                 mkexpr( frBI64 ) ),
11469                                                           mkU8( 4 ) ) ),
11470                                   mkexpr( pos_sign_mask ),
11471                                   mkexpr( neg_sign_mask ) ) );
11472
11473         assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
11474
11475         /* Generate the result assuming the sign value was valid. */
11476         assign( tmp64,
11477                 unop( Iop_ReinterpD64asI64,
11478                       binop( Iop_InsertExpD64,
11479                              mkU64( DFP_LONG_BIAS ),
11480                              unop( Iop_ReinterpI64asD64,
11481                                    binop( Iop_32HLto64,
11482                                           binop( Iop_Or32,
11483                                                  mkexpr( dbcd_u ),
11484                                                  mkexpr( sign_bit ) ),
11485                                           mkexpr( dbcd_l ) ) ) ) ) );
11486      }
11487
11488      /* Generate the value to store depending on the validity of the
11489       * sign value and the validity of the BCD digits.
11490       */
11491      assign( resultD64,
11492              unop( Iop_ReinterpI64asD64,
11493                    binop( Iop_32HLto64,
11494                           binop( Iop_Or32,
11495                                  binop( Iop_And32,
11496                                         mkexpr( valid_mask ),
11497                                         unop( Iop_64HIto32,
11498                                               mkexpr( tmp64 ) ) ),
11499                                  binop( Iop_And32,
11500                                         mkU32( 0x7C000000 ),
11501                                         mkexpr( invalid_mask ) ) ),
11502                           binop( Iop_Or32,
11503                                  binop( Iop_And32,
11504                                         mkexpr( valid_mask ),
11505                                         unop( Iop_64to32, mkexpr( tmp64 ) ) ),
11506                                  binop( Iop_And32,
11507                                         mkU32( 0x0 ),
11508                                         mkexpr( invalid_mask ) ) ) ) ) );
11509      putDReg( frT_addr, mkexpr( resultD64 ) );
11510   }
11511   break;
11512   default:
11513      vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
11514      return False;
11515   }
11516   return True;
11517}
11518
11519static Bool dis_dfp_bcdq( UInt theInstr )
11520{
11521   UInt opc2        = ifieldOPClo10( theInstr );
11522   ULong sp         = IFIELD(theInstr, 19, 2);
11523   ULong s          = IFIELD(theInstr, 20, 1);
11524   IRTemp frB_hi    = newTemp( Ity_D64 );
11525   IRTemp frB_lo    = newTemp( Ity_D64 );
11526   IRTemp frBI64_hi = newTemp( Ity_I64 );
11527   IRTemp frBI64_lo = newTemp( Ity_I64 );
11528   UChar frT_addr   = ifieldRegDS( theInstr );
11529   UChar frB_addr   = ifieldRegB( theInstr );
11530
11531   IRTemp lmd       = newTemp( Ity_I32 );
11532   IRTemp result_hi = newTemp( Ity_I64 );
11533   IRTemp result_lo = newTemp( Ity_I64 );
11534
11535   assign( frB_hi, getDReg( frB_addr ) );
11536   assign( frB_lo, getDReg( frB_addr + 1 ) );
11537   assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
11538   assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
11539
11540   switch ( opc2 ) {
11541   case 0x142: // ddedpdq   DFP Decode DPD to BCD
11542   {
11543      IRTemp low_60_u = newTemp( Ity_I32 );
11544      IRTemp low_60_l = newTemp( Ity_I32 );
11545      IRTemp mid_60_u = newTemp( Ity_I32 );
11546      IRTemp mid_60_l = newTemp( Ity_I32 );
11547      IRTemp top_12_l = newTemp( Ity_I32 );
11548
11549      DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
11550
11551      /* Note, instruction only stores the lower 32 BCD digits in
11552       * the result
11553       */
11554      Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
11555                                   mkexpr( frBI64_lo ),
11556                                   &top_12_l,
11557                                   &mid_60_u,
11558                                   &mid_60_l,
11559                                   &low_60_u,
11560                                   &low_60_l );
11561
11562      if ( ( sp == 0 ) || ( sp == 1 ) ) {
11563         /* Unsigned BCD string */
11564         assign( result_hi,
11565                 binop( Iop_32HLto64,
11566                        binop( Iop_Or32,
11567                               binop( Iop_Shl32,
11568                                      mkexpr( top_12_l ),
11569                                      mkU8( 24 ) ),
11570                               binop( Iop_Shr32,
11571                                      mkexpr( mid_60_u ),
11572                                      mkU8( 4 ) ) ),
11573                        binop( Iop_Or32,
11574                               binop( Iop_Shl32,
11575                                      mkexpr( mid_60_u ),
11576                                      mkU8( 28 ) ),
11577                               binop( Iop_Shr32,
11578                                      mkexpr( mid_60_l ),
11579                                      mkU8( 4 ) ) ) ) );
11580
11581         assign( result_lo,
11582                 binop( Iop_32HLto64,
11583                        binop( Iop_Or32,
11584                               binop( Iop_Shl32,
11585                                      mkexpr( mid_60_l ),
11586                                      mkU8( 28 ) ),
11587                               mkexpr( low_60_u ) ),
11588                        mkexpr( low_60_l ) ) );
11589
11590      } else {
11591         /* Signed BCD string, the cases for sp 2 and 3 only differ in how
11592          * the positive and negative values are encoded in the least
11593          * significant bits.
11594          */
11595         IRTemp sign = newTemp( Ity_I32 );
11596
11597         if ( sp == 2 ) {
11598            /* Positive sign = 0xC, negative sign = 0xD */
11599            assign( sign,
11600                    binop( Iop_Or32,
11601                           binop( Iop_Shr32,
11602                                  unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
11603                                  mkU8( 31 ) ),
11604                           mkU32( 0xC ) ) );
11605
11606         } else if ( sp == 3 ) {
11607            IRTemp tmp32 = newTemp( Ity_I32 );
11608
11609            /* Positive sign = 0xF, negative sign = 0xD.
11610             * Need to complement sign bit then OR into bit position 1.
11611             */
11612            assign( tmp32,
11613                    binop( Iop_Xor32,
11614                           binop( Iop_Shr32,
11615                                  unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
11616                                  mkU8( 30 ) ),
11617                           mkU32( 0x2 ) ) );
11618
11619            assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
11620
11621         } else {
11622            vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
11623         }
11624
11625         assign( result_hi,
11626                 binop( Iop_32HLto64,
11627                        binop( Iop_Or32,
11628                               binop( Iop_Shl32,
11629                                      mkexpr( top_12_l ),
11630                                      mkU8( 28 ) ),
11631                               mkexpr( mid_60_u ) ),
11632                        mkexpr( mid_60_l ) ) );
11633
11634         assign( result_lo,
11635                 binop( Iop_32HLto64,
11636                        binop( Iop_Or32,
11637                               binop( Iop_Shl32,
11638                                      mkexpr( low_60_u ),
11639                                      mkU8( 4 ) ),
11640                               binop( Iop_Shr32,
11641                                      mkexpr( low_60_l ),
11642                                      mkU8( 28 ) ) ),
11643                        binop( Iop_Or32,
11644                               binop( Iop_Shl32,
11645                                      mkexpr( low_60_l ),
11646                                      mkU8( 4 ) ),
11647                               mkexpr( sign ) ) ) );
11648      }
11649
11650      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
11651      putDReg( frT_addr + 1,
11652               unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
11653   }
11654   break;
11655   case 0x342: // denbcdq   DFP Encode BCD to DPD
11656   {
11657      IRTemp valid_mask      = newTemp( Ity_I32 );
11658      IRTemp invalid_mask    = newTemp( Ity_I32 );
11659      IRTemp result128       = newTemp( Ity_D128 );
11660      IRTemp dfp_significand = newTemp( Ity_D128 );
11661      IRTemp tmp_hi          = newTemp( Ity_I64 );
11662      IRTemp tmp_lo          = newTemp( Ity_I64 );
11663      IRTemp dbcd_top_l      = newTemp( Ity_I32 );
11664      IRTemp dbcd_mid_u      = newTemp( Ity_I32 );
11665      IRTemp dbcd_mid_l      = newTemp( Ity_I32 );
11666      IRTemp dbcd_low_u      = newTemp( Ity_I32 );
11667      IRTemp dbcd_low_l      = newTemp( Ity_I32 );
11668      IRTemp bcd_top_8       = newTemp( Ity_I64 );
11669      IRTemp bcd_mid_60      = newTemp( Ity_I64 );
11670      IRTemp bcd_low_60      = newTemp( Ity_I64 );
11671      IRTemp sign_bit        = newTemp( Ity_I32 );
11672      IRTemp tmptop10        = newTemp( Ity_I64 );
11673      IRTemp tmpmid50        = newTemp( Ity_I64 );
11674      IRTemp tmplow50        = newTemp( Ity_I64 );
11675      IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
11676
11677      DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
11678
11679      if ( s == 0 ) {
11680         /* Unsigned BCD string */
11681         assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
11682
11683         assign( bcd_top_8,
11684                 binop( Iop_32HLto64,
11685                        mkU32( 0 ),
11686                        binop( Iop_And32,
11687                               binop( Iop_Shr32,
11688                                      unop( Iop_64HIto32,
11689                                            mkexpr( frBI64_hi ) ),
11690                                      mkU8( 24 ) ),
11691                               mkU32( 0xFF ) ) ) );
11692         assign( bcd_mid_60,
11693                 binop( Iop_32HLto64,
11694                        binop( Iop_Or32,
11695                               binop( Iop_Shr32,
11696                                      unop( Iop_64to32,
11697                                            mkexpr( frBI64_hi ) ),
11698                                      mkU8( 28 ) ),
11699                               binop( Iop_Shl32,
11700                                      unop( Iop_64HIto32,
11701                                            mkexpr( frBI64_hi ) ),
11702                                      mkU8( 4 ) ) ),
11703                        binop( Iop_Or32,
11704                               binop( Iop_Shl32,
11705                                      unop( Iop_64to32,
11706                                            mkexpr( frBI64_hi ) ),
11707                                      mkU8( 4 ) ),
11708                               binop( Iop_Shr32,
11709                                      unop( Iop_64HIto32,
11710                                            mkexpr( frBI64_lo ) ),
11711                                      mkU8( 28 ) ) ) ) );
11712
11713         /* Note, the various helper functions ignores top 4-bits */
11714         assign( bcd_low_60, mkexpr( frBI64_lo ) );
11715
11716         assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
11717         assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
11718
11719         assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
11720         assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
11721         assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
11722
11723         assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
11724         assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
11725         assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
11726
11727         /* The entire BCD string fits in lower 110-bits.  The LMD = 0,
11728          * value is not part of the final result. Only the right most
11729          * BCD digits are stored.
11730          */
11731         assign( lmd, mkU32( 0 ) );
11732
11733         assign( invalid_mask,
11734                 binop( Iop_Or32,
11735                        bcd_digit_inval( mkU32( 0 ),
11736                                         unop( Iop_64to32,
11737                                               mkexpr( bcd_top_8 ) ) ),
11738                        binop( Iop_Or32,
11739                               bcd_digit_inval( unop( Iop_64HIto32,
11740                                                      mkexpr( bcd_mid_60 ) ),
11741                                                unop( Iop_64to32,
11742                                                      mkexpr( bcd_mid_60 ) ) ),
11743                               bcd_digit_inval( unop( Iop_64HIto32,
11744                                                      mkexpr( bcd_low_60 ) ),
11745                                                unop( Iop_64to32,
11746                                                      mkexpr( bcd_low_60 ) )
11747                                                ) ) ) );
11748
11749      } else if ( s == 1 ) {
11750         IRTemp sign          = newTemp( Ity_I32 );
11751         IRTemp zero          = newTemp( Ity_I32 );
11752         IRTemp pos_sign_mask = newTemp( Ity_I32 );
11753         IRTemp neg_sign_mask = newTemp( Ity_I32 );
11754
11755         /* The sign of the BCD string is stored in lower 4 bits */
11756         assign( sign,
11757                 binop( Iop_And32,
11758                        unop( Iop_64to32, mkexpr( frBI64_lo ) ),
11759                        mkU32( 0xF ) ) );
11760         assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
11761         assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
11762         assign( sign_bit,
11763                 Generate_sign_bit( mkexpr( pos_sign_mask ),
11764                                    mkexpr( neg_sign_mask ) ) );
11765
11766         /* Generate the value assuminig the sign and BCD digits are vaild */
11767         assign( bcd_top_8,
11768                 binop( Iop_32HLto64,
11769                        mkU32( 0x0 ),
11770                        binop( Iop_Shr32,
11771                               unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
11772                               mkU8( 28 ) ) ) );
11773
11774         /* The various helper routines ignore the upper 4-bits */
11775         assign( bcd_mid_60, mkexpr( frBI64_hi ) );
11776
11777         /* Remove bottom four sign bits */
11778         assign( bcd_low_60,
11779                 binop( Iop_32HLto64,
11780                        binop( Iop_Shr32,
11781                               unop( Iop_64HIto32,
11782                                     mkexpr( frBI64_lo ) ),
11783                               mkU8( 4 ) ),
11784                               binop( Iop_Or32,
11785                                      binop( Iop_Shl32,
11786                                             unop( Iop_64HIto32,
11787                                                   mkexpr( frBI64_lo ) ),
11788                                             mkU8( 28 ) ),
11789                                      binop( Iop_Shr32,
11790                                             unop( Iop_64to32,
11791                                                   mkexpr( frBI64_lo ) ),
11792                                             mkU8( 4 ) ) ) ) );
11793         assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
11794         assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
11795
11796         assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
11797         assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
11798         assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
11799
11800         assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
11801         assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
11802         assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
11803
11804         /* The entire BCD string fits in lower 110-bits.  The LMD value
11805          * is not stored in the final result for the DFP Long instruction.
11806          */
11807         assign( lmd, mkU32( 0 ) );
11808
11809         /* Check for invalid sign and invalid BCD digit.  Don't check the
11810          *  bottom four bits of frBI64_lo as that is the sign value.
11811          */
11812         assign( zero, mkU32( 0 ) );
11813         assign( inval_bcd_digit_mask,
11814                 binop( Iop_Or32,
11815                        bcd_digit_inval( mkexpr( zero ),
11816                                         unop( Iop_64to32,
11817                                               mkexpr( bcd_top_8 ) ) ),
11818                        binop( Iop_Or32,
11819                               bcd_digit_inval( unop( Iop_64HIto32,
11820                                                     mkexpr( bcd_mid_60 ) ),
11821                                               unop( Iop_64to32,
11822                                                     mkexpr( bcd_mid_60 ) ) ),
11823                               bcd_digit_inval( unop( Iop_64HIto32,
11824                                                     mkexpr( frBI64_lo ) ),
11825                                               binop( Iop_Shr32,
11826                                                      unop( Iop_64to32,
11827                                                            mkexpr( frBI64_lo ) ),
11828                                                        mkU8( 4 ) ) ) ) ) );
11829         assign( invalid_mask,
11830                 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
11831                                    mkexpr( pos_sign_mask ),
11832                                    mkexpr( neg_sign_mask ) ) );
11833
11834      }
11835
11836      assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
11837
11838      /* Calculate the value of the result assuming sign and BCD digits
11839       * are all valid.
11840       */
11841      assign( dfp_significand,
11842              binop( Iop_D64HLtoD128,
11843                     unop( Iop_ReinterpI64asD64,
11844                           binop( Iop_32HLto64,
11845                                  binop( Iop_Or32,
11846                                         mkexpr( sign_bit ),
11847                                         mkexpr( dbcd_top_l ) ),
11848                                  binop( Iop_Or32,
11849                                         binop( Iop_Shl32,
11850                                                mkexpr( dbcd_mid_u ),
11851                                                mkU8( 18 ) ),
11852                                         binop( Iop_Shr32,
11853                                                mkexpr( dbcd_mid_l ),
11854                                                mkU8( 14 ) ) ) ) ),
11855                     unop( Iop_ReinterpI64asD64,
11856                           binop( Iop_32HLto64,
11857                                  binop( Iop_Or32,
11858                                         mkexpr( dbcd_low_u ),
11859                                         binop( Iop_Shl32,
11860                                                mkexpr( dbcd_mid_l ),
11861                                                mkU8( 18 ) ) ),
11862                                  mkexpr( dbcd_low_l ) ) ) ) );
11863
11864      /* Break the result back down to 32-bit chunks and replace chunks.
11865       * If there was an invalid BCD digit or invalid sign value, replace
11866       * the calculated result with the invalid bit string.
11867       */
11868      assign( result128,
11869              binop( Iop_InsertExpD128,
11870                     mkU64( DFP_EXTND_BIAS ),
11871                     mkexpr( dfp_significand ) ) );
11872
11873      assign( tmp_hi,
11874              unop( Iop_ReinterpD64asI64,
11875                    unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
11876
11877      assign( tmp_lo,
11878              unop( Iop_ReinterpD64asI64,
11879                    unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
11880
11881      assign( result_hi,
11882              binop( Iop_32HLto64,
11883                     binop( Iop_Or32,
11884                            binop( Iop_And32,
11885                                   mkexpr( valid_mask ),
11886                                   unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
11887                            binop( Iop_And32,
11888                                   mkU32( 0x7C000000 ),
11889                                   mkexpr( invalid_mask ) ) ),
11890                     binop( Iop_Or32,
11891                            binop( Iop_And32,
11892                                   mkexpr( valid_mask ),
11893                                   unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
11894                            binop( Iop_And32,
11895                                   mkU32( 0x0 ),
11896                                   mkexpr( invalid_mask ) ) ) ) );
11897
11898      assign( result_lo,
11899              binop( Iop_32HLto64,
11900                     binop( Iop_Or32,
11901                            binop( Iop_And32,
11902                                   mkexpr( valid_mask ),
11903                                   unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
11904                            binop( Iop_And32,
11905                                   mkU32( 0x0 ),
11906                                   mkexpr( invalid_mask ) ) ),
11907                     binop( Iop_Or32,
11908                            binop( Iop_And32,
11909                                   mkexpr( valid_mask ),
11910                                   unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
11911                            binop( Iop_And32,
11912                                   mkU32( 0x0 ),
11913                                   mkexpr( invalid_mask ) ) ) ) );
11914
11915      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
11916      putDReg( frT_addr + 1,
11917               unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
11918
11919   }
11920   break;
11921   default:
11922      vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
11923      break;
11924   }
11925   return True;
11926}
11927
11928static Bool dis_dfp_significant_digits( UInt theInstr )
11929{
11930   UChar frA_addr = ifieldRegA( theInstr );
11931   UChar frB_addr = ifieldRegB( theInstr );
11932   IRTemp frA     = newTemp( Ity_D64 );
11933   UInt opc1      = ifieldOPC( theInstr );
11934   IRTemp B_sig   = newTemp( Ity_I8 );
11935   IRTemp K       = newTemp( Ity_I8 );
11936   IRTemp lmd_B   = newTemp( Ity_I32 );
11937   IRTemp field   = newTemp( Ity_I32 );
11938   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
11939   IRTemp Unordered_true     = newTemp( Ity_I32 );
11940   IRTemp Eq_true_mask       = newTemp( Ity_I32 );
11941   IRTemp Lt_true_mask       = newTemp( Ity_I32 );
11942   IRTemp Gt_true_mask       = newTemp( Ity_I32 );
11943   IRTemp KisZero_true_mask  = newTemp( Ity_I32 );
11944   IRTemp KisZero_false_mask = newTemp( Ity_I32 );
11945
11946   /* Get the reference singificance stored in frA */
11947   assign( frA, getDReg( frA_addr ) );
11948
11949   /* Convert from 64 bit to 8 bits in two steps.  The Iop_64to8 is not
11950    * supported in 32-bit mode.
11951    */
11952   assign( K, unop( Iop_32to8,
11953                    binop( Iop_And32,
11954                           unop( Iop_64to32,
11955                                 unop( Iop_ReinterpD64asI64,
11956                                       mkexpr( frA ) ) ),
11957                           mkU32( 0x3F ) ) ) );
11958
11959   switch ( opc1 ) {
11960   case 0x3b: // dtstsf   DFP Test Significance
11961   {
11962      IRTemp frB     = newTemp( Ity_D64 );
11963      IRTemp frBI64  = newTemp( Ity_I64 );
11964      IRTemp B_bcd_u = newTemp( Ity_I32 );
11965      IRTemp B_bcd_l = newTemp( Ity_I32 );
11966      IRTemp tmp64   = newTemp( Ity_I64 );
11967
11968      DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
11969
11970      assign( frB, getDReg( frB_addr ) );
11971      assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
11972
11973      /* Get the BCD string for the value stored in a series of I32 values.
11974       * Count the number of leading zeros.  Subtract the number of leading
11975       * zeros from 16 (maximum number of significant digits in DFP
11976       * Long).
11977       */
11978      Get_lmd( &lmd_B,
11979               binop( Iop_Shr32,
11980                      unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11981                      mkU8( 31 - 5 ) ) ); // G-field[0:4]
11982
11983      assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
11984      assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
11985      assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
11986
11987      assign( B_sig,
11988              binop( Iop_Sub8,
11989                     mkU8( DFP_LONG_MAX_SIG_DIGITS ),
11990                     Count_leading_zeros_60( mkexpr( lmd_B ),
11991                                             mkexpr( B_bcd_u ),
11992                                             mkexpr( B_bcd_l ) ) ) );
11993      assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) );
11994   }
11995   break;
11996   case 0x3F: // dtstsfq     DFP Test Significance
11997   {
11998      IRTemp frB_hi     = newTemp( Ity_D64 );
11999      IRTemp frB_lo     = newTemp( Ity_D64 );
12000      IRTemp frBI64_hi  = newTemp( Ity_I64 );
12001      IRTemp frBI64_lo  = newTemp( Ity_I64 );
12002      IRTemp B_low_60_u = newTemp( Ity_I32 );
12003      IRTemp B_low_60_l = newTemp( Ity_I32 );
12004      IRTemp B_mid_60_u = newTemp( Ity_I32 );
12005      IRTemp B_mid_60_l = newTemp( Ity_I32 );
12006      IRTemp B_top_12_l = newTemp( Ity_I32 );
12007
12008      DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
12009
12010      assign( frB_hi, getDReg( frB_addr ) );
12011      assign( frB_lo, getDReg( frB_addr + 1 ) );
12012
12013      assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
12014      assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
12015
12016      /* Get the BCD string for the value stored in a series of I32 values.
12017       * Count the number of leading zeros.  Subtract the number of leading
12018       * zeros from 32 (maximum number of significant digits in DFP
12019       * extended).
12020       */
12021      Get_lmd( &lmd_B,
12022               binop( Iop_Shr32,
12023                      unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12024                      mkU8( 31 - 5 ) ) ); // G-field[0:4]
12025
12026      Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
12027                                   mkexpr( frBI64_lo ),
12028                                   &B_top_12_l,
12029                                   &B_mid_60_u,
12030                                   &B_mid_60_l,
12031                                   &B_low_60_u,
12032                                   &B_low_60_l );
12033
12034      assign( B_sig,
12035              binop( Iop_Sub8,
12036                     mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
12037                     Count_leading_zeros_128( mkexpr( lmd_B ),
12038                                              mkexpr( B_top_12_l ),
12039                                              mkexpr( B_mid_60_u ),
12040                                              mkexpr( B_mid_60_l ),
12041                                              mkexpr( B_low_60_u ),
12042                                              mkexpr( B_low_60_l ) ) ) );
12043
12044      assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) );
12045   }
12046   break;
12047   }
12048
12049   /* Compare (16 - cnt[0]) against K and set the condition code field
12050    * accordingly.
12051    *
12052    * The field layout is as follows:
12053    *
12054    * bit[3:0]    Description
12055    *    3     K != 0 and K < Number of significant digits if FRB
12056    *    2     K != 0 and K > Number of significant digits if FRB OR K = 0
12057    *    1     K != 0 and K = Number of significant digits if FRB
12058    *    0     K ? Number of significant digits if FRB
12059    */
12060   assign( Eq_true_mask,
12061           unop( Iop_1Sto32,
12062                 binop( Iop_CmpEQ32,
12063                        unop( Iop_8Uto32, mkexpr( K ) ),
12064                        unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
12065   assign( Lt_true_mask,
12066           unop( Iop_1Sto32,
12067                 binop( Iop_CmpLT32U,
12068                        unop( Iop_8Uto32, mkexpr( K ) ),
12069                        unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
12070   assign( Gt_true_mask,
12071           unop( Iop_1Sto32,
12072                 binop( Iop_CmpLT32U,
12073                        unop( Iop_8Uto32, mkexpr( B_sig ) ),
12074                        unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
12075
12076   assign( KisZero_true_mask,
12077           unop( Iop_1Sto32,
12078                 binop( Iop_CmpEQ32,
12079                        unop( Iop_8Uto32, mkexpr( K ) ),
12080                        mkU32( 0 ) ) ) );
12081   assign( KisZero_false_mask,
12082           unop( Iop_1Sto32,
12083                 binop( Iop_CmpNE32,
12084                        unop( Iop_8Uto32, mkexpr( K ) ),
12085                        mkU32( 0 ) ) ) );
12086
12087   assign( field,
12088           binop( Iop_Or32,
12089                  binop( Iop_And32,
12090                         mkexpr( KisZero_false_mask ),
12091                         binop( Iop_Or32,
12092                                binop( Iop_And32,
12093                                       mkexpr( Lt_true_mask ),
12094                                       mkU32( 0x8 ) ),
12095                                binop( Iop_Or32,
12096                                       binop( Iop_And32,
12097                                              mkexpr( Gt_true_mask ),
12098                                              mkU32( 0x4 ) ),
12099                                       binop( Iop_And32,
12100                                              mkexpr( Eq_true_mask ),
12101                                              mkU32( 0x2 ) ) ) ) ),
12102                  binop( Iop_And32,
12103                         mkexpr( KisZero_true_mask ),
12104                         mkU32( 0x4 ) ) ) );
12105
12106   putGST_field( PPC_GST_CR,
12107                 binop( Iop_Or32,
12108                        binop( Iop_And32,
12109                               mkexpr( Unordered_true ),
12110                               mkU32( 0x1 ) ),
12111                        binop( Iop_And32,
12112                               unop( Iop_Not32, mkexpr( Unordered_true ) ),
12113                               mkexpr( field ) ) ),
12114                 crfD );
12115
12116   return True;
12117}
12118
12119/*------------------------------------------------------------*/
12120/*--- AltiVec Instruction Translation                      ---*/
12121/*------------------------------------------------------------*/
12122
12123/*
12124  Altivec Cache Control Instructions (Data Streams)
12125*/
12126static Bool dis_av_datastream ( UInt theInstr )
12127{
12128   /* X-Form */
12129   UChar opc1     = ifieldOPC(theInstr);
12130   UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
12131   UChar flag_A   = flag_T;
12132   UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
12133   UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
12134   UChar rA_addr  = ifieldRegA(theInstr);
12135   UChar rB_addr  = ifieldRegB(theInstr);
12136   UInt  opc2     = ifieldOPClo10(theInstr);
12137   UChar b0       = ifieldBIT0(theInstr);
12138
12139   if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
12140      vex_printf("dis_av_datastream(ppc)(instr)\n");
12141      return False;
12142   }
12143
12144   switch (opc2) {
12145   case 0x156: // dst (Data Stream Touch, AV p115)
12146      DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
12147                                rA_addr, rB_addr, STRM);
12148      break;
12149
12150   case 0x176: // dstst (Data Stream Touch for Store, AV p117)
12151      DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
12152                                  rA_addr, rB_addr, STRM);
12153      break;
12154
12155   case 0x336: // dss (Data Stream Stop, AV p114)
12156      if (rA_addr != 0 || rB_addr != 0) {
12157         vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
12158         return False;
12159      }
12160      if (flag_A == 0) {
12161         DIP("dss %d\n", STRM);
12162      } else {
12163         DIP("dssall\n");
12164      }
12165      break;
12166
12167   default:
12168      vex_printf("dis_av_datastream(ppc)(opc2)\n");
12169      return False;
12170   }
12171   return True;
12172}
12173
12174/*
12175  AltiVec Processor Control Instructions
12176*/
12177static Bool dis_av_procctl ( UInt theInstr )
12178{
12179   /* VX-Form */
12180   UChar opc1    = ifieldOPC(theInstr);
12181   UChar vD_addr = ifieldRegDS(theInstr);
12182   UChar vA_addr = ifieldRegA(theInstr);
12183   UChar vB_addr = ifieldRegB(theInstr);
12184   UInt  opc2    = IFIELD( theInstr, 0, 11 );
12185
12186   if (opc1 != 0x4) {
12187      vex_printf("dis_av_procctl(ppc)(instr)\n");
12188      return False;
12189   }
12190
12191   switch (opc2) {
12192   case 0x604: // mfvscr (Move from VSCR, AV p129)
12193      if (vA_addr != 0 || vB_addr != 0) {
12194         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
12195         return False;
12196      }
12197      DIP("mfvscr v%d\n", vD_addr);
12198      putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
12199      break;
12200
12201   case 0x644: { // mtvscr (Move to VSCR, AV p130)
12202      IRTemp vB = newTemp(Ity_V128);
12203      if (vD_addr != 0 || vA_addr != 0) {
12204         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
12205         return False;
12206      }
12207      DIP("mtvscr v%d\n", vB_addr);
12208      assign( vB, getVReg(vB_addr));
12209      putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
12210      break;
12211   }
12212   default:
12213      vex_printf("dis_av_procctl(ppc)(opc2)\n");
12214      return False;
12215   }
12216   return True;
12217}
12218
12219/*
12220 * VSX scalar and vector convert instructions
12221 */
12222static Bool
12223dis_vx_conv ( UInt theInstr, UInt opc2 )
12224{
12225   /* XX2-Form */
12226   UChar opc1 = ifieldOPC( theInstr );
12227   UChar XT = ifieldRegXT( theInstr );
12228   UChar XB = ifieldRegXB( theInstr );
12229   IRTemp xB, xB2;
12230   IRTemp b3, b2, b1, b0;
12231   xB = xB2 = IRTemp_INVALID;
12232
12233   if (opc1 != 0x3C) {
12234      vex_printf( "dis_vx_conv(ppc)(instr)\n" );
12235      return False;
12236   }
12237
12238   /* Create and assign temps only as needed for the given instruction. */
12239   switch (opc2) {
12240      // scalar double-precision floating point argument
12241      case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
12242         xB = newTemp(Ity_F64);
12243         assign( xB,
12244                 unop( Iop_ReinterpI64asF64,
12245                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12246         break;
12247      // vector double-precision floating point arguments
12248      case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
12249
12250         xB = newTemp(Ity_F64);
12251         xB2 = newTemp(Ity_F64);
12252         assign( xB,
12253                 unop( Iop_ReinterpI64asF64,
12254                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12255         assign( xB2,
12256                 unop( Iop_ReinterpI64asF64,
12257                       unop( Iop_V128to64, getVSReg( XB ) ) ) );
12258         break;
12259      // vector single precision or [un]signed integer word arguments
12260      case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
12261      case 0x1f0: case 0x1d0:
12262         b3 = b2 = b1 = b0 = IRTemp_INVALID;
12263         breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
12264         break;
12265         // vector [un]signed integer doubleword argument
12266      case 0x3f0: case 0x370: case 0x3d0: case 0x350:
12267         xB = newTemp(Ity_I64);
12268         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12269         xB2 = newTemp(Ity_I64);
12270         assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
12271         break;
12272      // scalar [un]signed integer doubleword argument
12273      case 0x250: case 0x270: case 0x2D0: case 0x2F0:
12274         xB = newTemp(Ity_I64);
12275         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12276         break;
12277      // scalar single precision argument
12278      case 0x292: // xscvspdp
12279         xB  = newTemp(Ity_I32);
12280
12281         assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
12282                                                  unop( Iop_V128HIto64,
12283                                                        getVSReg( XB ) ) ) ) );
12284         break;
12285      case 0x296: // xscvspdpn (non signaling version of xscvpdp)
12286         xB = newTemp(Ity_I32);
12287         assign( xB,
12288                 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12289         break;
12290
12291      /* Certain instructions have their complete implementation in the main switch statement
12292       * that follows this one; thus we have a "do nothing" case for those instructions here.
12293       */
12294      case 0x170: case 0x150:
12295         break; // do nothing
12296
12297      default:
12298         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
12299         return False;
12300   }
12301
12302
12303   switch (opc2) {
12304      case 0x2B0:
12305         // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
12306         //             to Signed Integer Doubleword format with Saturate)
12307         DIP("xscvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12308         putVSReg( XT,
12309                   binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
12310                                                 mkU32( Irrm_ZERO ),
12311                                                 mkexpr( xB ) ), mkU64( 0 ) ) );
12312         break;
12313      case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
12314                  //             Convert to Signed Integer Word format with Saturate)
12315         DIP("xscvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
12316         putVSReg( XT,
12317                   binop( Iop_64HLtoV128,
12318                          unop( Iop_32Sto64,
12319                                binop( Iop_F64toI32S,
12320                                       mkU32( Irrm_ZERO ),
12321                                       mkexpr( xB ) ) ),
12322                                       mkU64( 0ULL ) ) );
12323         break;
12324      case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
12325                  //             to Unsigned Integer Doubleword format with Saturate)
12326         DIP("xscvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12327         putVSReg( XT,
12328                   binop( Iop_64HLtoV128,
12329                          binop( Iop_F64toI64U,
12330                                 mkU32( Irrm_ZERO ),
12331                                 mkexpr( xB ) ),
12332                                 mkU64( 0ULL ) ) );
12333         break;
12334      case 0x270:
12335         // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
12336         //             to Single-Precision format)
12337         DIP("xscvsxdsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12338         putVSReg( XT,
12339                   binop( Iop_64HLtoV128,
12340                          unop( Iop_ReinterpF64asI64,
12341                                binop( Iop_RoundF64toF32,
12342                                       get_IR_roundingmode(),
12343                                       binop( Iop_I64StoF64,
12344                                              get_IR_roundingmode(),
12345                                              mkexpr( xB ) ) ) ),
12346                          mkU64( 0 ) ) );
12347         break;
12348      case 0x2F0:
12349         // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
12350         //            Double-Precision format)
12351         DIP("xscvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12352         putVSReg( XT,
12353                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
12354                                                binop( Iop_I64StoF64, get_IR_roundingmode(),
12355                                                       mkexpr( xB ) ) ),
12356                                                       mkU64( 0 ) ) );
12357         break;
12358      case 0x250:
12359         // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
12360         //            Doubleword to Singel-Precision format)
12361         DIP("xscvuxdsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12362         putVSReg( XT,
12363                   binop( Iop_64HLtoV128,
12364                          unop( Iop_ReinterpF64asI64,
12365                                binop( Iop_RoundF64toF32,
12366                                       get_IR_roundingmode(),
12367                                       binop( Iop_I64UtoF64,
12368                                              get_IR_roundingmode(),
12369                                              mkexpr( xB ) ) ) ),
12370                          mkU64( 0 ) ) );
12371         break;
12372      case 0x2D0:
12373         // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
12374         //            Double-Precision format)
12375         DIP("xscvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12376         putVSReg( XT,
12377                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
12378                                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
12379                                                       mkexpr( xB ) ) ),
12380                                                       mkU64( 0 ) ) );
12381         break;
12382      case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
12383                  //             to Signed Integer Word format with Saturate)
12384      {
12385         IRTemp hiResult_32 = newTemp(Ity_I32);
12386         IRTemp loResult_32 = newTemp(Ity_I32);
12387         IRExpr* rmZero = mkU32(Irrm_ZERO);
12388
12389         DIP("xvcvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
12390         assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
12391         assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
12392         putVSReg( XT,
12393                   binop( Iop_64HLtoV128,
12394                          unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
12395                          unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
12396         break;
12397      }
12398      case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
12399         //  (VSX Vector truncate Single-Precision to integer and
12400         //   Convert to [Un]signed Integer Word format with Saturate)
12401      {
12402         IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
12403         IRTemp tempResult = newTemp(Ity_V128);
12404         IRTemp res0 = newTemp(Ity_I32);
12405         IRTemp res1 = newTemp(Ity_I32);
12406         IRTemp res2 = newTemp(Ity_I32);
12407         IRTemp res3 = newTemp(Ity_I32);
12408         IRTemp hi64 = newTemp(Ity_I64);
12409         IRTemp lo64 = newTemp(Ity_I64);
12410         Bool un_signed = (opc2 == 0x110);
12411         IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
12412
12413         DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB);
12414         /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
12415          * then result is set to 0x80000000.  */
12416         assign(tempResult, unop(op, getVSReg(XB)));
12417         assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
12418         assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
12419         assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
12420         assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
12421         assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
12422         assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
12423
12424         b3_result = IRExpr_ITE(is_NaN_32(b3),
12425                                // then: result is 0x{8|0}80000000
12426                                mkU32(un_signed ? 0x00000000 : 0x80000000),
12427                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12428                                mkexpr(res3));
12429         b2_result = IRExpr_ITE(is_NaN_32(b2),
12430                                // then: result is 0x{8|0}80000000
12431                                mkU32(un_signed ? 0x00000000 : 0x80000000),
12432                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12433                                mkexpr(res2));
12434         b1_result = IRExpr_ITE(is_NaN_32(b1),
12435                                // then: result is 0x{8|0}80000000
12436                                mkU32(un_signed ? 0x00000000 : 0x80000000),
12437                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12438                                mkexpr(res1));
12439         b0_result = IRExpr_ITE(is_NaN_32(b0),
12440                                // then: result is 0x{8|0}80000000
12441                                mkU32(un_signed ? 0x00000000 : 0x80000000),
12442                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12443                                mkexpr(res0));
12444
12445         putVSReg( XT,
12446                   binop( Iop_64HLtoV128,
12447                          binop( Iop_32HLto64, b3_result, b2_result ),
12448                          binop( Iop_32HLto64, b1_result, b0_result ) ) );
12449         break;
12450      }
12451      case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
12452                  //           Convert to Single-Precision format
12453         DIP("xscvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12454         putVSReg( XT,
12455                   binop( Iop_64HLtoV128,
12456                          binop( Iop_32HLto64,
12457                                 unop( Iop_ReinterpF32asI32,
12458                                       unop( Iop_TruncF64asF32,
12459                                             binop( Iop_RoundF64toF32,
12460                                                    get_IR_roundingmode(),
12461                                                    mkexpr( xB ) ) ) ),
12462                                 mkU32( 0 ) ),
12463                          mkU64( 0ULL ) ) );
12464         break;
12465      case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
12466                              vector Single-Precision non-signalling */
12467         DIP("xscvdpspn v%u,v%u\n",  (UInt)XT, (UInt)XB);
12468         putVSReg( XT,
12469                   binop( Iop_64HLtoV128,
12470                          binop( Iop_32HLto64,
12471                                 unop( Iop_ReinterpF32asI32,
12472                                       unop( Iop_TruncF64asF32,
12473                                             mkexpr( xB ) ) ),
12474                                 mkU32( 0 ) ),
12475                          mkU64( 0ULL ) ) );
12476         break;
12477      case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
12478                  //             and Convert to Unsigned Integer Word format with Saturate)
12479         DIP("xscvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
12480         putVSReg( XT,
12481                   binop( Iop_64HLtoV128,
12482                          binop( Iop_32HLto64,
12483                                 mkU32( 0 ),
12484                                 binop( Iop_F64toI32U,
12485                                        mkU32( Irrm_ZERO ),
12486                                        mkexpr( xB ) ) ),
12487                          mkU64( 0ULL ) ) );
12488         break;
12489      case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
12490         DIP("xscvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12491         putVSReg( XT,
12492                   binop( Iop_64HLtoV128,
12493                          unop( Iop_ReinterpF64asI64,
12494                                unop( Iop_F32toF64,
12495                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
12496                          mkU64( 0ULL ) ) );
12497         break;
12498      case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
12499         DIP("xscvspdpn v%u,v%u\n",  (UInt)XT, (UInt)XB);
12500         putVSReg( XT,
12501                   binop( Iop_64HLtoV128,
12502                          unop( Iop_ReinterpF64asI64,
12503                                unop( Iop_F32toF64,
12504                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
12505                                      mkU64( 0ULL ) ) );
12506         break;
12507      case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
12508                  //           and Convert to Single-Precision format)
12509         DIP("xvcvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12510         putVSReg( XT,
12511                   binop( Iop_64HLtoV128,
12512                          binop( Iop_32HLto64,
12513                                 unop( Iop_ReinterpF32asI32,
12514                                       unop( Iop_TruncF64asF32,
12515                                             binop( Iop_RoundF64toF32,
12516                                                    get_IR_roundingmode(),
12517                                                    mkexpr( xB ) ) ) ),
12518                                 mkU32( 0 ) ),
12519                          binop( Iop_32HLto64,
12520                                 unop( Iop_ReinterpF32asI32,
12521                                       unop( Iop_TruncF64asF32,
12522                                             binop( Iop_RoundF64toF32,
12523                                                    get_IR_roundingmode(),
12524                                                    mkexpr( xB2 ) ) ) ),
12525                                 mkU32( 0 ) ) ) );
12526         break;
12527      case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
12528                  //             and Convert to Unsigned Integer Doubleword format
12529                  //             with Saturate)
12530         DIP("xvcvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12531         putVSReg( XT,
12532                   binop( Iop_64HLtoV128,
12533                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
12534                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
12535         break;
12536      case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
12537                  //             Convert to Unsigned Integer Word format with Saturate)
12538         DIP("xvcvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
12539         putVSReg( XT,
12540                   binop( Iop_64HLtoV128,
12541                          binop( Iop_32HLto64,
12542                                 binop( Iop_F64toI32U,
12543                                        mkU32( Irrm_ZERO ),
12544                                        mkexpr( xB ) ),
12545                                 mkU32( 0 ) ),
12546                          binop( Iop_32HLto64,
12547                                 binop( Iop_F64toI32U,
12548                                        mkU32( Irrm_ZERO ),
12549                                        mkexpr( xB2 ) ),
12550                                 mkU32( 0 ) ) ) );
12551         break;
12552      case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
12553         DIP("xvcvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12554         putVSReg( XT,
12555                   binop( Iop_64HLtoV128,
12556                          unop( Iop_ReinterpF64asI64,
12557                                unop( Iop_F32toF64,
12558                                      unop( Iop_ReinterpI32asF32,
12559                                            handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
12560                          unop( Iop_ReinterpF64asI64,
12561                                unop( Iop_F32toF64,
12562                                      unop( Iop_ReinterpI32asF32,
12563                                            handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
12564         break;
12565      case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
12566                  //           Convert to Signed Integer Doubleword format with Saturate)
12567         DIP("xvcvspsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12568         putVSReg( XT,
12569                   binop( Iop_64HLtoV128,
12570                          binop( Iop_F64toI64S,
12571                                 mkU32( Irrm_ZERO ),
12572                                 unop( Iop_F32toF64,
12573                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
12574                          binop( Iop_F64toI64S,
12575                                 mkU32( Irrm_ZERO ),
12576                                 unop( Iop_F32toF64,
12577                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
12578         break;
12579      case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
12580                  //            Convert to Unsigned Integer Doubleword format with Saturate)
12581         DIP("xvcvspuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12582         putVSReg( XT,
12583                   binop( Iop_64HLtoV128,
12584                          binop( Iop_F64toI64U,
12585                                 mkU32( Irrm_ZERO ),
12586                                 unop( Iop_F32toF64,
12587                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
12588                          binop( Iop_F64toI64U,
12589                                 mkU32( Irrm_ZERO ),
12590                                 unop( Iop_F32toF64,
12591                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
12592         break;
12593      case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
12594                  //             Convert to Signed Integer Doubleword format with Saturate)
12595         DIP("xvcvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12596         putVSReg( XT,
12597                   binop( Iop_64HLtoV128,
12598                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
12599                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
12600         break;
12601      case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
12602                  //            to Double-Precision format)
12603         DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12604         putVSReg( XT,
12605                   binop( Iop_64HLtoV128,
12606                          unop( Iop_ReinterpF64asI64,
12607                                binop( Iop_I64StoF64,
12608                                       get_IR_roundingmode(),
12609                                       mkexpr( xB ) ) ),
12610                          unop( Iop_ReinterpF64asI64,
12611                                binop( Iop_I64StoF64,
12612                                       get_IR_roundingmode(),
12613                                       mkexpr( xB2 ) ) ) ) );
12614         break;
12615      case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
12616                  //            to Double-Precision format)
12617         DIP("xvcvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12618         putVSReg( XT,
12619                   binop( Iop_64HLtoV128,
12620                          unop( Iop_ReinterpF64asI64,
12621                                binop( Iop_I64UtoF64,
12622                                       get_IR_roundingmode(),
12623                                       mkexpr( xB ) ) ),
12624                          unop( Iop_ReinterpF64asI64,
12625                                binop( Iop_I64UtoF64,
12626                                       get_IR_roundingmode(),
12627                                       mkexpr( xB2 ) ) ) ) );
12628
12629         break;
12630      case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
12631                  //            to Single-Precision format)
12632         DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12633         putVSReg( XT,
12634                   binop( Iop_64HLtoV128,
12635                          binop( Iop_32HLto64,
12636                                 unop( Iop_ReinterpF32asI32,
12637                                       unop( Iop_TruncF64asF32,
12638                                             binop( Iop_RoundF64toF32,
12639                                                    get_IR_roundingmode(),
12640                                                    binop( Iop_I64StoF64,
12641                                                           get_IR_roundingmode(),
12642                                                           mkexpr( xB ) ) ) ) ),
12643                                 mkU32( 0 ) ),
12644                          binop( Iop_32HLto64,
12645                                 unop( Iop_ReinterpF32asI32,
12646                                       unop( Iop_TruncF64asF32,
12647                                             binop( Iop_RoundF64toF32,
12648                                                    get_IR_roundingmode(),
12649                                                    binop( Iop_I64StoF64,
12650                                                           get_IR_roundingmode(),
12651                                                           mkexpr( xB2 ) ) ) ) ),
12652                                 mkU32( 0 ) ) ) );
12653         break;
12654      case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
12655                  //            to Single-Precision format)
12656         DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
12657         putVSReg( XT,
12658                   binop( Iop_64HLtoV128,
12659                          binop( Iop_32HLto64,
12660                                 unop( Iop_ReinterpF32asI32,
12661                                       unop( Iop_TruncF64asF32,
12662                                             binop( Iop_RoundF64toF32,
12663                                                    get_IR_roundingmode(),
12664                                                    binop( Iop_I64UtoF64,
12665                                                           get_IR_roundingmode(),
12666                                                           mkexpr( xB ) ) ) ) ),
12667                                 mkU32( 0 ) ),
12668                          binop( Iop_32HLto64,
12669                                 unop( Iop_ReinterpF32asI32,
12670                                       unop( Iop_TruncF64asF32,
12671                                             binop( Iop_RoundF64toF32,
12672                                                    get_IR_roundingmode(),
12673                                                    binop( Iop_I64UtoF64,
12674                                                           get_IR_roundingmode(),
12675                                                           mkexpr( xB2 ) ) ) ) ),
12676                                 mkU32( 0 ) ) ) );
12677         break;
12678
12679      case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
12680         DIP("xvcvsxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12681         putVSReg( XT,
12682                   binop( Iop_64HLtoV128,
12683                          unop( Iop_ReinterpF64asI64,
12684                                binop( Iop_I64StoF64, get_IR_roundingmode(),
12685                                       unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
12686                          unop( Iop_ReinterpF64asI64,
12687                                binop( Iop_I64StoF64, get_IR_roundingmode(),
12688                                       unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
12689         break;
12690      case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
12691         DIP("xvcvuxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12692         putVSReg( XT,
12693                   binop( Iop_64HLtoV128,
12694                          unop( Iop_ReinterpF64asI64,
12695                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
12696                                       unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
12697                          unop( Iop_ReinterpF64asI64,
12698                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
12699                                       unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
12700         break;
12701      case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
12702         DIP("xvcvsxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12703         putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
12704         break;
12705      case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
12706         DIP("xvcvuxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12707         putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
12708         break;
12709
12710      default:
12711         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
12712         return False;
12713   }
12714   return True;
12715}
12716
12717/*
12718 * VSX vector Double Precision Floating Point Arithmetic Instructions
12719 */
12720static Bool
12721dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
12722{
12723   /* XX3-Form */
12724   UChar opc1 = ifieldOPC( theInstr );
12725   UChar XT = ifieldRegXT( theInstr );
12726   UChar XA = ifieldRegXA( theInstr );
12727   UChar XB = ifieldRegXB( theInstr );
12728   IRExpr* rm = get_IR_roundingmode();
12729   IRTemp frA = newTemp(Ity_F64);
12730   IRTemp frB = newTemp(Ity_F64);
12731   IRTemp frA2 = newTemp(Ity_F64);
12732   IRTemp frB2 = newTemp(Ity_F64);
12733
12734   if (opc1 != 0x3C) {
12735      vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
12736      return False;
12737   }
12738
12739   assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
12740   assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
12741   assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
12742   assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
12743
12744   switch (opc2) {
12745      case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
12746      case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
12747      case 0x180: // xvadddp (VSX Vector Add Double-Precision)
12748      case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
12749      {
12750         IROp mOp;
12751         const HChar * oper_name;
12752         switch (opc2) {
12753            case 0x1E0:
12754               mOp = Iop_DivF64;
12755               oper_name = "div";
12756               break;
12757            case 0x1C0:
12758               mOp = Iop_MulF64;
12759               oper_name = "mul";
12760               break;
12761            case 0x180:
12762               mOp = Iop_AddF64;
12763               oper_name = "add";
12764               break;
12765            case 0x1A0:
12766               mOp = Iop_SubF64;
12767               oper_name = "sub";
12768               break;
12769
12770            default:
12771               vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
12772         }
12773         IRTemp hiResult = newTemp(Ity_I64);
12774         IRTemp loResult = newTemp(Ity_I64);
12775         DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB);
12776
12777         assign( hiResult,
12778                 unop( Iop_ReinterpF64asI64,
12779                       triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
12780         assign( loResult,
12781                 unop( Iop_ReinterpF64asI64,
12782                       triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
12783         putVSReg( XT,
12784                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
12785         break;
12786      }
12787      case 0x196: // xvsqrtdp
12788      {
12789         IRTemp hiResult = newTemp(Ity_I64);
12790         IRTemp loResult = newTemp(Ity_I64);
12791         DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
12792
12793         assign( hiResult,
12794                 unop( Iop_ReinterpF64asI64,
12795                       binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
12796         assign( loResult,
12797                 unop( Iop_ReinterpF64asI64,
12798                       binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
12799         putVSReg( XT,
12800                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
12801         break;
12802      }
12803      case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
12804      case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
12805      case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
12806      case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
12807      {
12808         /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
12809          *    XT == FRC
12810          *    XA == FRA
12811          *    XB == FRB
12812          *
12813          * and for xvm{add|sub}adp . . .
12814          *    XT == FRB
12815          *    XA == FRA
12816          *    XB == FRC
12817          */
12818         Bool negate;
12819         IROp mOp = Iop_INVALID;
12820         const HChar * oper_name = NULL;
12821         Bool mdp = False;
12822
12823         switch (opc2) {
12824            case 0x184: case 0x1A4:
12825            case 0x384: case 0x3A4:
12826               mOp = Iop_MAddF64;
12827               oper_name = "add";
12828               mdp = (opc2 & 0x0FF) == 0x0A4;
12829               break;
12830
12831            case 0x1C4: case 0x1E4:
12832            case 0x3C4: case 0x3E4:
12833               mOp = Iop_MSubF64;
12834               oper_name = "sub";
12835               mdp = (opc2 & 0x0FF) == 0x0E4;
12836               break;
12837
12838            default:
12839               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
12840         }
12841
12842         switch (opc2) {
12843            case 0x384: case 0x3A4:
12844            case 0x3C4: case 0x3E4:
12845               negate = True;
12846               break;
12847            default:
12848               negate = False;
12849         }
12850         IRTemp hiResult = newTemp(Ity_I64);
12851         IRTemp loResult = newTemp(Ity_I64);
12852         IRTemp frT = newTemp(Ity_F64);
12853         IRTemp frT2 = newTemp(Ity_F64);
12854         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
12855             (UInt)XT, (UInt)XA, (UInt)XB);
12856         assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
12857         assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
12858
12859         assign( hiResult,
12860                 unop( Iop_ReinterpF64asI64,
12861                       qop( mOp,
12862                            rm,
12863                            mkexpr( frA ),
12864                            mkexpr( mdp ? frT : frB ),
12865                            mkexpr( mdp ? frB : frT ) ) ) );
12866         assign( loResult,
12867                 unop( Iop_ReinterpF64asI64,
12868                       qop( mOp,
12869                            rm,
12870                            mkexpr( frA2 ),
12871                            mkexpr( mdp ? frT2 : frB2 ),
12872                            mkexpr( mdp ? frB2 : frT2 ) ) ) );
12873         putVSReg( XT,
12874                   binop( Iop_64HLtoV128,
12875                          mkexpr( negate ? getNegatedResult( hiResult )
12876                                         : hiResult ),
12877                          mkexpr( negate ? getNegatedResult( loResult )
12878                                         : loResult ) ) );
12879         break;
12880      }
12881      case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
12882      {
12883         IRTemp frBHi_I64 = newTemp(Ity_I64);
12884         IRTemp frBLo_I64 = newTemp(Ity_I64);
12885         IRTemp flagsHi = newTemp(Ity_I32);
12886         IRTemp flagsLo = newTemp(Ity_I32);
12887         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
12888         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
12889         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
12890
12891         DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
12892         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
12893         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
12894         do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
12895         do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
12896         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
12897          * where fl_flag == 1 on ppc64.
12898          */
12899         assign( flagsHi,
12900                 binop( Iop_Or32,
12901                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
12902                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
12903                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
12904         assign( flagsLo,
12905                 binop( Iop_Or32,
12906                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
12907                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
12908                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
12909         putGST_field( PPC_GST_CR,
12910                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
12911                       crfD );
12912         break;
12913      }
12914      case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
12915      {
12916         IRTemp frBHi_I64 = newTemp(Ity_I64);
12917         IRTemp frBLo_I64 = newTemp(Ity_I64);
12918         IRTemp frAHi_I64 = newTemp(Ity_I64);
12919         IRTemp frALo_I64 = newTemp(Ity_I64);
12920         IRTemp flagsHi = newTemp(Ity_I32);
12921         IRTemp flagsLo = newTemp(Ity_I32);
12922         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
12923         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
12924         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
12925
12926         DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
12927         assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
12928         assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
12929         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
12930         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
12931
12932         _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
12933         _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
12934         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
12935          * where fl_flag == 1 on ppc64.
12936          */
12937         assign( flagsHi,
12938                 binop( Iop_Or32,
12939                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
12940                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
12941                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
12942         assign( flagsLo,
12943                 binop( Iop_Or32,
12944                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
12945                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
12946                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
12947         putGST_field( PPC_GST_CR,
12948                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
12949                       crfD );
12950         break;
12951      }
12952
12953      default:
12954         vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
12955         return False;
12956   }
12957   return True;
12958}
12959
12960/*
12961 * VSX vector Single Precision Floating Point Arithmetic Instructions
12962 */
12963static Bool
12964dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
12965{
12966   /* XX3-Form */
12967   UChar opc1 = ifieldOPC( theInstr );
12968   UChar XT = ifieldRegXT( theInstr );
12969   UChar XA = ifieldRegXA( theInstr );
12970   UChar XB = ifieldRegXB( theInstr );
12971   IRExpr* rm = get_IR_roundingmode();
12972   IRTemp a3, a2, a1, a0;
12973   IRTemp b3, b2, b1, b0;
12974   IRTemp res0 = newTemp(Ity_I32);
12975   IRTemp res1 = newTemp(Ity_I32);
12976   IRTemp res2 = newTemp(Ity_I32);
12977   IRTemp res3 = newTemp(Ity_I32);
12978
12979   a3 = a2 = a1 = a0 = IRTemp_INVALID;
12980   b3 = b2 = b1 = b0 = IRTemp_INVALID;
12981
12982   if (opc1 != 0x3C) {
12983      vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
12984      return False;
12985   }
12986
12987   switch (opc2) {
12988      case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
12989         DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
12990         // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
12991         putVSReg( XT, triop(Iop_Add32Fx4, rm,
12992                             getVSReg( XA ), getVSReg( XB )) );
12993         break;
12994
12995      case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
12996         DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
12997         // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
12998         putVSReg( XT, triop(Iop_Mul32Fx4, rm,
12999                             getVSReg( XA ), getVSReg( XB )) );
13000         break;
13001
13002      case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
13003         DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
13004         // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
13005         putVSReg( XT, triop(Iop_Sub32Fx4, rm,
13006                             getVSReg( XA ), getVSReg( XB )) );
13007         break;
13008
13009      case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
13010      {
13011         /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
13012          * So there are two choices:
13013          *   1. Implement the xvdivsp with a native insn; or
13014          *   2. Extract the 4 single precision floats from each vector
13015          *      register inputs and perform fdivs on each pair
13016          * I will do the latter, due to the general philosophy of
13017          * reusing existing implementations when practical.
13018          */
13019         DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
13020         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13021         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13022
13023         assign( res0,
13024              unop( Iop_ReinterpF32asI32,
13025                    unop( Iop_TruncF64asF32,
13026                          triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
13027         assign( res1,
13028                 unop( Iop_ReinterpF32asI32,
13029                       unop( Iop_TruncF64asF32,
13030                             triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
13031         assign( res2,
13032                 unop( Iop_ReinterpF32asI32,
13033                       unop( Iop_TruncF64asF32,
13034                             triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
13035         assign( res3,
13036                 unop( Iop_ReinterpF32asI32,
13037                       unop( Iop_TruncF64asF32,
13038                             triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
13039
13040         putVSReg( XT,
13041                   binop( Iop_64HLtoV128,
13042                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13043                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13044         break;
13045      }
13046      case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
13047      {
13048         DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
13049         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13050         /* Note: The native xvsqrtsp insruction does not always give the same precision
13051          * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
13052          * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
13053          * to the actual instruction.
13054          */
13055
13056         assign( res0,
13057                 unop( Iop_ReinterpF32asI32,
13058                       unop( Iop_TruncF64asF32,
13059                             binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
13060         assign( res1,
13061                 unop( Iop_ReinterpF32asI32,
13062                       unop( Iop_TruncF64asF32,
13063                             binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
13064         assign( res2,
13065                 unop( Iop_ReinterpF32asI32,
13066                       unop( Iop_TruncF64asF32,
13067                             binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
13068         assign( res3,
13069                 unop( Iop_ReinterpF32asI32,
13070                       unop( Iop_TruncF64asF32,
13071                             binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
13072
13073         putVSReg( XT,
13074                   binop( Iop_64HLtoV128,
13075                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13076                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13077         break;
13078      }
13079
13080      case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
13081      case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
13082      case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
13083      case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
13084      {
13085         IRTemp t3, t2, t1, t0;
13086         Bool msp = False;
13087         Bool negate;
13088         const HChar * oper_name = NULL;
13089         IROp mOp = Iop_INVALID;
13090         switch (opc2) {
13091            case 0x104: case 0x124:
13092            case 0x304: case 0x324:
13093               msp = (opc2 & 0x0FF) == 0x024;
13094               mOp = Iop_MAddF64r32;
13095               oper_name = "madd";
13096               break;
13097
13098            case 0x144: case 0x164:
13099            case 0x344: case 0x364:
13100               msp = (opc2 & 0x0FF) == 0x064;
13101               mOp = Iop_MSubF64r32;
13102               oper_name = "sub";
13103               break;
13104
13105            default:
13106               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
13107         }
13108
13109         switch (opc2) {
13110            case 0x304: case 0x324:
13111            case 0x344: case 0x364:
13112               negate = True;
13113               break;
13114
13115            default:
13116               negate = False;
13117         }
13118
13119         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp",
13120             (UInt)XT, (UInt)XA, (UInt)XB);
13121
13122         t3 = t2 = t1 = t0 = IRTemp_INVALID;
13123         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13124         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13125         breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
13126
13127         assign( res0,
13128                 unop( Iop_ReinterpF32asI32,
13129                       unop( Iop_TruncF64asF32,
13130                             qop( mOp,
13131                                  rm,
13132                                  mkexpr( a0 ),
13133                                  mkexpr( msp ? t0 : b0 ),
13134                                  mkexpr( msp ? b0 : t0 ) ) ) ) );
13135         assign( res1,
13136                 unop( Iop_ReinterpF32asI32,
13137                       unop( Iop_TruncF64asF32,
13138                             qop( mOp,
13139                                  rm,
13140                                  mkexpr( a1 ),
13141                                  mkexpr( msp ? t1 : b1 ),
13142                                  mkexpr( msp ? b1 : t1 ) ) ) ) );
13143         assign( res2,
13144                 unop( Iop_ReinterpF32asI32,
13145                       unop( Iop_TruncF64asF32,
13146                             qop( mOp,
13147                                  rm,
13148                                  mkexpr( a2 ),
13149                                  mkexpr( msp ? t2 : b2 ),
13150                                  mkexpr( msp ? b2 : t2 ) ) ) ) );
13151         assign( res3,
13152                 unop( Iop_ReinterpF32asI32,
13153                       unop( Iop_TruncF64asF32,
13154                             qop( mOp,
13155                                  rm,
13156                                  mkexpr( a3 ),
13157                                  mkexpr( msp ? t3 : b3 ),
13158                                  mkexpr( msp ? b3 : t3 ) ) ) ) );
13159
13160         putVSReg( XT,
13161                   binop( Iop_64HLtoV128,
13162                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
13163                                 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
13164                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
13165                                 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
13166
13167         break;
13168      }
13169      case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
13170      {
13171         IRTemp flags0 = newTemp(Ity_I32);
13172         IRTemp flags1 = newTemp(Ity_I32);
13173         IRTemp flags2 = newTemp(Ity_I32);
13174         IRTemp flags3 = newTemp(Ity_I32);
13175         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13176         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13177         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13178         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13179         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13180         DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
13181
13182         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13183         do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13184         do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13185         do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13186         do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13187
13188         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13189          * where fl_flag == 1 on ppc64.
13190          */
13191         assign( flags0,
13192                 binop( Iop_Or32,
13193                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13194                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13195                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13196         assign( flags1,
13197                 binop( Iop_Or32,
13198                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13199                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13200                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13201         assign( flags2,
13202                 binop( Iop_Or32,
13203                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13204                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13205                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13206         assign( flags3,
13207                 binop( Iop_Or32,
13208                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13209                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13210                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13211         putGST_field( PPC_GST_CR,
13212                       binop( Iop_Or32,
13213                              mkexpr( flags0 ),
13214                              binop( Iop_Or32,
13215                                     mkexpr( flags1 ),
13216                                     binop( Iop_Or32,
13217                                            mkexpr( flags2 ),
13218                                            mkexpr( flags3 ) ) ) ),
13219                       crfD );
13220
13221         break;
13222      }
13223      case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
13224      {
13225         IRTemp flags0 = newTemp(Ity_I32);
13226         IRTemp flags1 = newTemp(Ity_I32);
13227         IRTemp flags2 = newTemp(Ity_I32);
13228         IRTemp flags3 = newTemp(Ity_I32);
13229         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13230         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13231         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13232         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13233         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13234         DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
13235
13236         breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13237         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13238         _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13239         _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13240         _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13241         _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13242
13243         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13244          * where fl_flag == 1 on ppc64.
13245          */
13246         assign( flags0,
13247                 binop( Iop_Or32,
13248                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13249                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13250                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13251         assign( flags1,
13252                 binop( Iop_Or32,
13253                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13254                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13255                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13256         assign( flags2,
13257                 binop( Iop_Or32,
13258                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13259                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13260                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13261         assign( flags3,
13262                 binop( Iop_Or32,
13263                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13264                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13265                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13266         putGST_field( PPC_GST_CR,
13267                       binop( Iop_Or32,
13268                              mkexpr( flags0 ),
13269                              binop( Iop_Or32,
13270                                     mkexpr( flags1 ),
13271                                     binop( Iop_Or32,
13272                                            mkexpr( flags2 ),
13273                                            mkexpr( flags3 ) ) ) ),
13274                       crfD );
13275
13276         break;
13277      }
13278
13279      default:
13280         vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
13281         return False;
13282   }
13283   return True;
13284}
13285
13286/*
13287 * Vector Population Count/bit matrix transpose
13288 */
13289static Bool
13290dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
13291{
13292   UChar vRB_addr = ifieldRegB(theInstr);
13293   UChar vRT_addr = ifieldRegDS(theInstr);
13294   UChar opc1 = ifieldOPC( theInstr );
13295   IRTemp vB = newTemp(Ity_V128);
13296   assign( vB, getVReg(vRB_addr));
13297
13298   if (opc1 != 0x4) {
13299      vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
13300      return False;
13301   }
13302
13303   switch (opc2) {
13304      case 0x702:    // vclzb
13305         DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
13306         putVReg( vRT_addr, unop(Iop_Clz8Sx16, mkexpr( vB ) ) );
13307         break;
13308
13309      case 0x742:    // vclzh
13310         DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
13311         putVReg( vRT_addr, unop(Iop_Clz16Sx8, mkexpr( vB ) ) );
13312         break;
13313
13314      case 0x782:    // vclzw
13315         DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
13316         putVReg( vRT_addr, unop(Iop_Clz32Sx4, mkexpr( vB ) ) );
13317         break;
13318
13319      case 0x7C2:    // vclzd
13320         DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
13321         putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
13322         break;
13323
13324      case 0x703:    // vpopcntb
13325      {
13326         /* Break vector into 32-bit words and do the population count
13327          * on byte in the words
13328          */
13329         IRType ty = Ity_I32;
13330         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13331         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13332         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13333         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13334
13335         DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
13336         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13337         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   BYTE);
13338         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  BYTE);
13339         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  BYTE);
13340         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
13341
13342         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13343                                         cnt_bits32_63, cnt_bits0_31) );
13344         break;
13345      }
13346
13347      case 0x743:    // vpopcnth
13348      {
13349         /* Break vector into 32-bit words and do the population count
13350          * for each half word
13351          */
13352         IRType ty = Ity_I32;
13353         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13354         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13355         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13356         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13357
13358         DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
13359         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13360
13361         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   HWORD);
13362         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  HWORD);
13363         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  HWORD);
13364         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
13365
13366         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13367                                         cnt_bits32_63, cnt_bits0_31) );
13368         break;
13369      }
13370
13371      case 0x783:    // vpopcntw
13372      {
13373         /* Break vector into 32-bit words and do the population count
13374          * on each word.
13375          */
13376         IRType ty = Ity_I32;
13377         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13378         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13379         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13380         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13381
13382         DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
13383         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13384
13385         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   WORD);
13386         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  WORD);
13387         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  WORD);
13388         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
13389
13390         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13391                                         cnt_bits32_63, cnt_bits0_31) );
13392         break;
13393      }
13394
13395      case 0x7C3:    // vpopcntd
13396      {
13397         if (mode64) {
13398            /* Break vector into 64-bit double words and do the population count
13399             * on each double word.
13400             */
13401            IRType ty = Ity_I64;
13402            IRTemp bits0_63   = newTemp(Ity_I64);
13403            IRTemp bits64_127 = newTemp(Ity_I64);
13404            IRTemp cnt_bits0_63   = newTemp(Ity_I64);
13405            IRTemp cnt_bits64_127 = newTemp(Ity_I64);
13406
13407            DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
13408
13409            assign(bits0_63,   unop( Iop_V128to64,   mkexpr( vB ) ) );
13410            assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
13411            cnt_bits0_63   = gen_POPCOUNT(ty, bits0_63,   DWORD);
13412            cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
13413
13414            putVReg( vRT_addr, binop( Iop_64HLtoV128,
13415                                      mkexpr( cnt_bits64_127 ),
13416                                      mkexpr( cnt_bits0_63 ) ) );
13417         } else {
13418            /* Break vector into 32-bit words and do the population count
13419             * on each doubleword.
13420             */
13421            IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13422            bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13423            IRTemp cnt_bits0_63   = newTemp(Ity_I64);
13424            IRTemp cnt_bits64_127  = newTemp(Ity_I64);
13425
13426            DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
13427            breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13428
13429            cnt_bits0_63   = gen_vpopcntd_mode32(bits0_31, bits32_63);
13430            cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
13431
13432            putVReg( vRT_addr, binop( Iop_64HLtoV128,
13433                                      mkexpr( cnt_bits64_127 ),
13434                                      mkexpr( cnt_bits0_63 ) ) );
13435         }
13436         break;
13437      }
13438
13439      case 0x50C:  // vgbbd Vector Gather Bits by Bytes by Doubleword
13440         DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
13441         putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
13442         break;
13443
13444      default:
13445         vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
13446         return False;
13447      break;
13448   }
13449   return True;
13450}
13451
13452typedef enum {
13453   PPC_CMP_EQ = 2,
13454   PPC_CMP_GT = 4,
13455   PPC_CMP_GE = 6,
13456   PPC_CMP_LT = 8
13457} ppc_cmp_t;
13458
13459
13460/*
13461  This helper function takes as input the IRExpr returned
13462  from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
13463  in IR form.  This helper function converts it to PPC form.
13464
13465  Map compare result from IR to PPC
13466
13467  FP cmp result | PPC | IR
13468  --------------------------
13469  UN            | 0x1 | 0x45
13470  EQ            | 0x2 | 0x40
13471  GT            | 0x4 | 0x00
13472  LT            | 0x8 | 0x01
13473
13474 condcode = Shl(1, (~(ccIR>>5) & 2)
13475                    | ((ccIR ^ (ccIR>>6)) & 1)
13476*/
13477static IRTemp
13478get_fp_cmp_CR_val (IRExpr * ccIR_expr)
13479{
13480   IRTemp condcode = newTemp( Ity_I32 );
13481   IRTemp ccIR = newTemp( Ity_I32 );
13482
13483   assign(ccIR, ccIR_expr);
13484   assign( condcode,
13485           binop( Iop_Shl32,
13486                  mkU32( 1 ),
13487                  unop( Iop_32to8,
13488                        binop( Iop_Or32,
13489                               binop( Iop_And32,
13490                                      unop( Iop_Not32,
13491                                            binop( Iop_Shr32,
13492                                                   mkexpr( ccIR ),
13493                                                   mkU8( 5 ) ) ),
13494                                      mkU32( 2 ) ),
13495                               binop( Iop_And32,
13496                                      binop( Iop_Xor32,
13497                                             mkexpr( ccIR ),
13498                                             binop( Iop_Shr32,
13499                                                    mkexpr( ccIR ),
13500                                                    mkU8( 6 ) ) ),
13501                                      mkU32( 1 ) ) ) ) ) );
13502   return condcode;
13503}
13504
13505/*
13506 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
13507 * following these special rules:
13508 *   - The max/min of a QNaN and any value is that value
13509 *     (When two QNaNs are being compared, the frA QNaN is the return value.)
13510 *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
13511 *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
13512 */
13513static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
13514{
13515   IRTemp frA_isNaN = newTemp(Ity_I1);
13516   IRTemp frB_isNaN = newTemp(Ity_I1);
13517   IRTemp frA_isSNaN = newTemp(Ity_I1);
13518   IRTemp frB_isSNaN = newTemp(Ity_I1);
13519   IRTemp frA_isQNaN = newTemp(Ity_I1);
13520   IRTemp frB_isQNaN = newTemp(Ity_I1);
13521
13522   assign( frA_isNaN, is_NaN( frA_I64 ) );
13523   assign( frB_isNaN, is_NaN( frB_I64 ) );
13524   // If operand is a NAN and bit 12 is '0', then it's an SNaN
13525   assign( frA_isSNaN,
13526           mkAND1( mkexpr(frA_isNaN),
13527                   binop( Iop_CmpEQ32,
13528                          binop( Iop_And32,
13529                                 unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
13530                                 mkU32( 0x00080000 ) ),
13531                          mkU32( 0 ) ) ) );
13532   assign( frB_isSNaN,
13533           mkAND1( mkexpr(frB_isNaN),
13534                   binop( Iop_CmpEQ32,
13535                          binop( Iop_And32,
13536                                 unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
13537                                 mkU32( 0x00080000 ) ),
13538                          mkU32( 0 ) ) ) );
13539   assign( frA_isQNaN,
13540           mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
13541   assign( frB_isQNaN,
13542           mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
13543
13544   /* Based on the rules specified in the function prologue, the algorithm is as follows:
13545    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
13546    *   if frA is a SNaN
13547    *     result = frA converted to QNaN
13548    *   else if frB is a SNaN
13549    *     result = frB converted to QNaN
13550    *   else if frB is a QNaN
13551    *     result = frA
13552    *   // One of frA or frB was a NaN in order for this function to be called, so
13553    *   // if we get to this point, we KNOW that frA must be a QNaN.
13554    *   else // frA is a QNaN
13555    *     result = frB
13556    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
13557    */
13558
13559#define SNAN_MASK 0x0008000000000000ULL
13560   return
13561   IRExpr_ITE(mkexpr(frA_isSNaN),
13562              /* then: result = frA converted to QNaN */
13563              binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
13564              /* else:  if frB is a SNaN */
13565              IRExpr_ITE(mkexpr(frB_isSNaN),
13566                         /* then: result = frB converted to QNaN */
13567                         binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
13568                         /* else:  if frB is a QNaN */
13569                         IRExpr_ITE(mkexpr(frB_isQNaN),
13570                                    /* then: result = frA */
13571                                    mkexpr(frA_I64),
13572                                    /* else:  frA is a QNaN, so result = frB */
13573                                    mkexpr(frB_I64))));
13574}
13575
13576/*
13577 * Helper function for get_max_min_fp.
13578 */
13579static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
13580{
13581   IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
13582                                                  unop( Iop_ReinterpI64asF64,
13583                                                        mkexpr( src1 ) ),
13584                                                  unop( Iop_ReinterpI64asF64,
13585                                                        mkexpr( src2 ) ) ) );
13586
13587   return IRExpr_ITE( binop( Iop_CmpEQ32,
13588                               mkexpr( src1cmpsrc2 ),
13589                               mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
13590                      /* then: use src1 */
13591                      mkexpr( src1 ),
13592                      /* else: use src2 */
13593                      mkexpr( src2 ) );
13594}
13595
13596/*
13597 * Helper function for "Maximum/Minimum Double Precision" operations.
13598 * Arguments: frA and frb are Ity_I64
13599 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
13600 */
13601static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
13602{
13603   /* There are three special cases where get_fp_cmp_CR_val is not helpful
13604    * for ascertaining the maximum between two doubles:
13605    *   1. The max/min of +0 and -0 is +0.
13606    *   2. The max/min of a QNaN and any value is that value.
13607    *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
13608    * We perform the check for [+/-]0 here in this function and use the
13609    * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
13610    * to do the standard comparison function.
13611    */
13612   IRTemp anyNaN = newTemp(Ity_I1);
13613   IRTemp frA_isZero = newTemp(Ity_I1);
13614   IRTemp frB_isZero = newTemp(Ity_I1);
13615   assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
13616   assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
13617   assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
13618#define MINUS_ZERO 0x8000000000000000ULL
13619
13620   return IRExpr_ITE( /* If both arguments are zero . . . */
13621                     mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
13622                     /* then: if frA is -0 and isMin==True, return -0;
13623                      *     else if frA is +0 and isMin==False; return +0;
13624                      *     otherwise, simply return frB. */
13625                     IRExpr_ITE( binop( Iop_CmpEQ32,
13626                                        unop( Iop_64HIto32,
13627                                              mkexpr( frA_I64 ) ),
13628                                        mkU32( isMin ? 0x80000000 : 0 ) ),
13629                                 mkU64( isMin ? MINUS_ZERO : 0ULL ),
13630                                 mkexpr( frB_I64 ) ),
13631                     /* else: check if either input is a NaN*/
13632                     IRExpr_ITE( mkexpr( anyNaN ),
13633                                 /* then: use "NaN helper" */
13634                                 _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
13635                                 /* else: use "comparison helper" */
13636                                 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
13637}
13638
13639static const HChar * _get_vsx_rdpi_suffix(UInt opc2)
13640{
13641   switch (opc2 & 0x7F) {
13642      case 0x72:
13643         return "m";
13644      case 0x52:
13645         return "p";
13646      case 0x56:
13647         return "c";
13648      case 0x32:
13649         return "z";
13650      case 0x12:
13651         return "";
13652
13653      default: // Impossible to get here
13654         vex_printf("Unrecognized opcode %x\n", opc2);
13655         vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
13656   }
13657}
13658
13659/*
13660 * Helper function for vector/scalar double precision fp round to integer instructions.
13661 */
13662static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
13663{
13664
13665   /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
13666   IRTemp frB = newTemp(Ity_F64);
13667   IRTemp frD = newTemp(Ity_F64);
13668   IRTemp intermediateResult = newTemp(Ity_I64);
13669   IRTemp is_SNAN = newTemp(Ity_I1);
13670   IRExpr * hi32;
13671   IRExpr * rxpi_rm;
13672   switch (opc2 & 0x7F) {
13673      case 0x72:
13674         rxpi_rm = mkU32(Irrm_NegINF);
13675         break;
13676      case 0x52:
13677         rxpi_rm = mkU32(Irrm_PosINF);
13678         break;
13679      case 0x56:
13680         rxpi_rm = get_IR_roundingmode();
13681         break;
13682      case 0x32:
13683         rxpi_rm = mkU32(Irrm_ZERO);
13684         break;
13685      case 0x12:
13686         rxpi_rm = mkU32(Irrm_NEAREST);
13687         break;
13688
13689      default: // Impossible to get here
13690         vex_printf("Unrecognized opcode %x\n", opc2);
13691         vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
13692   }
13693   assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
13694   assign( intermediateResult,
13695           binop( Iop_F64toI64S, rxpi_rm,
13696                  mkexpr( frB ) ) );
13697
13698   /* don't use the rounded integer if frB is outside -9e18..9e18 */
13699   /* F64 has only log10(2**52) significant digits anyway */
13700   /* need to preserve sign of zero */
13701   /*   frD = (fabs(frB) > 9e18) ? frB :
13702            (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
13703   assign( frD,
13704           IRExpr_ITE(
13705              binop( Iop_CmpNE8,
13706                     unop( Iop_32to8,
13707                           binop( Iop_CmpF64,
13708                                  IRExpr_Const( IRConst_F64( 9e18 ) ),
13709                                  unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
13710                     mkU8(0) ),
13711              mkexpr( frB ),
13712              IRExpr_ITE(
13713                 binop( Iop_CmpNE32,
13714                        binop( Iop_Shr32,
13715                               unop( Iop_64HIto32,
13716                                     mkexpr( frB_I64 ) ),
13717                               mkU8( 31 ) ),
13718                        mkU32(0) ),
13719                 unop( Iop_NegF64,
13720                       unop( Iop_AbsF64,
13721                             binop( Iop_I64StoF64,
13722                                    mkU32( 0 ),
13723                                    mkexpr( intermediateResult ) ) ) ),
13724                 binop( Iop_I64StoF64,
13725                        mkU32( 0 ),
13726                        mkexpr( intermediateResult ) )
13727              )
13728           )
13729   );
13730
13731   /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
13732    * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
13733    */
13734#define SNAN_MASK 0x0008000000000000ULL
13735   hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
13736   assign( is_SNAN,
13737           mkAND1( is_NaN( frB_I64 ),
13738                   binop( Iop_CmpEQ32,
13739                          binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
13740                          mkU32( 0 ) ) ) );
13741
13742   return IRExpr_ITE( mkexpr( is_SNAN ),
13743                        unop( Iop_ReinterpI64asF64,
13744                              binop( Iop_Xor64,
13745                                     mkU64( SNAN_MASK ),
13746                                     mkexpr( frB_I64 ) ) ),
13747                      mkexpr( frD ));
13748}
13749
13750/*
13751 * Miscellaneous VSX vector instructions
13752 */
13753static Bool
13754dis_vxv_misc ( UInt theInstr, UInt opc2 )
13755{
13756   /* XX3-Form */
13757   UChar opc1 = ifieldOPC( theInstr );
13758   UChar XT = ifieldRegXT( theInstr );
13759   UChar XB = ifieldRegXB( theInstr );
13760
13761   if (opc1 != 0x3C) {
13762      vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
13763      return False;
13764   }
13765
13766   switch (opc2) {
13767      case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
13768      case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
13769                   //             Double-Precision)
13770      {
13771         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
13772         IRExpr* rm  = get_IR_roundingmode();
13773         IRTemp frB = newTemp(Ity_I64);
13774         IRTemp frB2 = newTemp(Ity_I64);
13775         Bool redp = opc2 == 0x1B4;
13776         IRTemp sqrtHi = newTemp(Ity_F64);
13777         IRTemp sqrtLo = newTemp(Ity_F64);
13778         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
13779         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
13780
13781         DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB);
13782         if (!redp) {
13783            assign( sqrtHi,
13784                    binop( Iop_SqrtF64,
13785                           rm,
13786                           unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
13787            assign( sqrtLo,
13788                    binop( Iop_SqrtF64,
13789                           rm,
13790                           unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
13791         }
13792         putVSReg( XT,
13793                   binop( Iop_64HLtoV128,
13794                          unop( Iop_ReinterpF64asI64,
13795                                triop( Iop_DivF64,
13796                                       rm,
13797                                       ieee_one,
13798                                       redp ? unop( Iop_ReinterpI64asF64,
13799                                                    mkexpr( frB ) )
13800                                            : mkexpr( sqrtHi ) ) ),
13801                          unop( Iop_ReinterpF64asI64,
13802                                triop( Iop_DivF64,
13803                                       rm,
13804                                       ieee_one,
13805                                       redp ? unop( Iop_ReinterpI64asF64,
13806                                                    mkexpr( frB2 ) )
13807                                            : mkexpr( sqrtLo ) ) ) ) );
13808         break;
13809
13810      }
13811      case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
13812      case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
13813      {
13814         IRTemp b3, b2, b1, b0;
13815         IRTemp res0 = newTemp(Ity_I32);
13816         IRTemp res1 = newTemp(Ity_I32);
13817         IRTemp res2 = newTemp(Ity_I32);
13818         IRTemp res3 = newTemp(Ity_I32);
13819         IRTemp sqrt3 = newTemp(Ity_F64);
13820         IRTemp sqrt2 = newTemp(Ity_F64);
13821         IRTemp sqrt1 = newTemp(Ity_F64);
13822         IRTemp sqrt0 = newTemp(Ity_F64);
13823         IRExpr* rm  = get_IR_roundingmode();
13824         Bool resp = opc2 == 0x134;
13825
13826         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
13827
13828         b3 = b2 = b1 = b0 = IRTemp_INVALID;
13829         DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB);
13830         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13831
13832         if (!resp) {
13833            assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
13834            assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
13835            assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
13836            assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
13837         }
13838
13839         assign( res0,
13840                 unop( Iop_ReinterpF32asI32,
13841                       unop( Iop_TruncF64asF32,
13842                             triop( Iop_DivF64r32,
13843                                    rm,
13844                                    ieee_one,
13845                                    resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
13846         assign( res1,
13847                 unop( Iop_ReinterpF32asI32,
13848                       unop( Iop_TruncF64asF32,
13849                             triop( Iop_DivF64r32,
13850                                    rm,
13851                                    ieee_one,
13852                                    resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
13853         assign( res2,
13854                 unop( Iop_ReinterpF32asI32,
13855                       unop( Iop_TruncF64asF32,
13856                             triop( Iop_DivF64r32,
13857                                    rm,
13858                                    ieee_one,
13859                                    resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
13860         assign( res3,
13861                 unop( Iop_ReinterpF32asI32,
13862                       unop( Iop_TruncF64asF32,
13863                             triop( Iop_DivF64r32,
13864                                    rm,
13865                                    ieee_one,
13866                                    resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
13867         putVSReg( XT,
13868                   binop( Iop_64HLtoV128,
13869                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13870                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13871         break;
13872      }
13873      case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
13874      case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
13875      {
13876         UChar XA = ifieldRegXA( theInstr );
13877         IRTemp a3, a2, a1, a0;
13878         IRTemp b3, b2, b1, b0;
13879         IRTemp res0 = newTemp( Ity_I32 );
13880         IRTemp res1 = newTemp( Ity_I32 );
13881         IRTemp res2 = newTemp( Ity_I32 );
13882         IRTemp res3 = newTemp( Ity_I32 );
13883         IRTemp a0_I64 = newTemp( Ity_I64 );
13884         IRTemp a1_I64 = newTemp( Ity_I64 );
13885         IRTemp a2_I64 = newTemp( Ity_I64 );
13886         IRTemp a3_I64 = newTemp( Ity_I64 );
13887         IRTemp b0_I64 = newTemp( Ity_I64 );
13888         IRTemp b1_I64 = newTemp( Ity_I64 );
13889         IRTemp b2_I64 = newTemp( Ity_I64 );
13890         IRTemp b3_I64 = newTemp( Ity_I64 );
13891
13892         Bool isMin = opc2 == 0x320 ? True : False;
13893
13894         a3 = a2 = a1 = a0 = IRTemp_INVALID;
13895         b3 = b2 = b1 = b0 = IRTemp_INVALID;
13896         DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB);
13897         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13898         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13899         assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
13900         assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
13901         assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
13902         assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
13903         assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
13904         assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
13905         assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
13906         assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
13907         assign( res0,
13908                 unop( Iop_ReinterpF32asI32,
13909                       unop( Iop_TruncF64asF32,
13910                             unop( Iop_ReinterpI64asF64,
13911                                   get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
13912         assign( res1,
13913                 unop( Iop_ReinterpF32asI32,
13914                       unop( Iop_TruncF64asF32,
13915                             unop( Iop_ReinterpI64asF64,
13916                                   get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
13917         assign( res2,
13918                 unop( Iop_ReinterpF32asI32,
13919                       unop( Iop_TruncF64asF32,
13920                             unop( Iop_ReinterpI64asF64,
13921                                   get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
13922         assign( res3,
13923                 unop( Iop_ReinterpF32asI32,
13924                       unop( Iop_TruncF64asF32,
13925                             unop( Iop_ReinterpI64asF64,
13926                                   get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
13927         putVSReg( XT,
13928                   binop( Iop_64HLtoV128,
13929                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13930                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13931         break;
13932      }
13933      case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
13934      case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
13935      {
13936         UChar XA = ifieldRegXA( theInstr );
13937         IRTemp frA = newTemp(Ity_I64);
13938         IRTemp frB = newTemp(Ity_I64);
13939         IRTemp frA2 = newTemp(Ity_I64);
13940         IRTemp frB2 = newTemp(Ity_I64);
13941         Bool isMin = opc2 == 0x3A0 ? True : False;
13942
13943         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
13944         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
13945         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
13946         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
13947         DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB);
13948         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
13949
13950         break;
13951      }
13952      case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
13953      {
13954         UChar XA = ifieldRegXA( theInstr );
13955         IRTemp frA = newTemp(Ity_I64);
13956         IRTemp frB = newTemp(Ity_I64);
13957         IRTemp frA2 = newTemp(Ity_I64);
13958         IRTemp frB2 = newTemp(Ity_I64);
13959         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
13960         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
13961         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
13962         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
13963
13964         DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
13965         putVSReg( XT,
13966                   binop( Iop_64HLtoV128,
13967                          binop( Iop_Or64,
13968                                 binop( Iop_And64,
13969                                        mkexpr( frA ),
13970                                        mkU64( SIGN_BIT ) ),
13971                                 binop( Iop_And64,
13972                                        mkexpr( frB ),
13973                                        mkU64( SIGN_MASK ) ) ),
13974                          binop( Iop_Or64,
13975                                 binop( Iop_And64,
13976                                        mkexpr( frA2 ),
13977                                        mkU64( SIGN_BIT ) ),
13978                                 binop( Iop_And64,
13979                                        mkexpr( frB2 ),
13980                                        mkU64( SIGN_MASK ) ) ) ) );
13981         break;
13982      }
13983      case 0x340: // xvcpsgnsp
13984      {
13985         UChar XA = ifieldRegXA( theInstr );
13986         IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
13987         IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
13988         IRTemp resHi = newTemp(Ity_I64);
13989         IRTemp resLo = newTemp(Ity_I64);
13990
13991         a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
13992         b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
13993         DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB);
13994         breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
13995         breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
13996
13997         assign( resHi,
13998                 binop( Iop_32HLto64,
13999                        binop( Iop_Or32,
14000                               binop( Iop_And32,
14001                                      unop(Iop_64to32, mkexpr( a3_I64 ) ),
14002                                      mkU32( SIGN_BIT32 ) ),
14003                               binop( Iop_And32,
14004                                      unop(Iop_64to32, mkexpr( b3_I64 ) ),
14005                                      mkU32( SIGN_MASK32) ) ),
14006
14007                        binop( Iop_Or32,
14008                               binop( Iop_And32,
14009                                      unop(Iop_64to32, mkexpr( a2_I64 ) ),
14010                                      mkU32( SIGN_BIT32 ) ),
14011                               binop( Iop_And32,
14012                                      unop(Iop_64to32, mkexpr( b2_I64 ) ),
14013                                      mkU32( SIGN_MASK32 ) ) ) ) );
14014         assign( resLo,
14015                 binop( Iop_32HLto64,
14016                        binop( Iop_Or32,
14017                               binop( Iop_And32,
14018                                      unop(Iop_64to32, mkexpr( a1_I64 ) ),
14019                                      mkU32( SIGN_BIT32 ) ),
14020                               binop( Iop_And32,
14021                                      unop(Iop_64to32, mkexpr( b1_I64 ) ),
14022                                      mkU32( SIGN_MASK32 ) ) ),
14023
14024                        binop( Iop_Or32,
14025                               binop( Iop_And32,
14026                                      unop(Iop_64to32, mkexpr( a0_I64 ) ),
14027                                      mkU32( SIGN_BIT32 ) ),
14028                               binop( Iop_And32,
14029                                      unop(Iop_64to32, mkexpr( b0_I64 ) ),
14030                                      mkU32( SIGN_MASK32 ) ) ) ) );
14031         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
14032         break;
14033      }
14034      case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
14035      case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
14036      {
14037         IRTemp frB = newTemp(Ity_F64);
14038         IRTemp frB2 = newTemp(Ity_F64);
14039         IRTemp abs_resultHi = newTemp(Ity_F64);
14040         IRTemp abs_resultLo = newTemp(Ity_F64);
14041         Bool make_negative = (opc2 == 0x3D2) ? True : False;
14042         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14043         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14044
14045         DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB);
14046         if (make_negative) {
14047            assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
14048            assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
14049
14050         } else {
14051            assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
14052            assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
14053         }
14054         putVSReg( XT, binop( Iop_64HLtoV128,
14055                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
14056                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
14057         break;
14058      }
14059      case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
14060      case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
14061      {
14062         /*
14063          * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
14064          * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
14065          * of this function is so easy using shifts, I choose to emulate this instruction that
14066          * way versus a native instruction method of implementation.
14067          */
14068         Bool make_negative = (opc2 == 0x352) ? True : False;
14069         IRTemp shiftVector = newTemp(Ity_V128);
14070         IRTemp absVal_vector = newTemp(Ity_V128);
14071         assign( shiftVector,
14072                 binop( Iop_64HLtoV128,
14073                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
14074                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
14075         assign( absVal_vector,
14076                   binop( Iop_Shr32x4,
14077                          binop( Iop_Shl32x4,
14078                                 getVSReg( XB ),
14079                                 mkexpr( shiftVector ) ),
14080                          mkexpr( shiftVector ) ) );
14081         if (make_negative) {
14082            IRTemp signBit_vector = newTemp(Ity_V128);
14083            assign( signBit_vector,
14084                    binop( Iop_64HLtoV128,
14085                           binop( Iop_32HLto64,
14086                                  mkU32( 0x80000000 ),
14087                                  mkU32( 0x80000000 ) ),
14088                           binop( Iop_32HLto64,
14089                                  mkU32( 0x80000000 ),
14090                                  mkU32( 0x80000000 ) ) ) );
14091            putVSReg( XT,
14092                      binop( Iop_OrV128,
14093                             mkexpr( absVal_vector ),
14094                             mkexpr( signBit_vector ) ) );
14095         } else {
14096            putVSReg( XT, mkexpr( absVal_vector ) );
14097         }
14098         break;
14099      }
14100      case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
14101      {
14102         IRTemp frB = newTemp(Ity_F64);
14103         IRTemp frB2 = newTemp(Ity_F64);
14104         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14105         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14106         DIP("xvnegdp v%d,v%d\n",  (UInt)XT, (UInt)XB);
14107         putVSReg( XT,
14108                   binop( Iop_64HLtoV128,
14109                          unop( Iop_ReinterpF64asI64,
14110                                unop( Iop_NegF64, mkexpr( frB ) ) ),
14111                          unop( Iop_ReinterpF64asI64,
14112                                unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
14113         break;
14114      }
14115      case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
14116      case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
14117      case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
14118      case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
14119      case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
14120      {
14121         IRTemp frBHi_I64 = newTemp(Ity_I64);
14122         IRTemp frBLo_I64 = newTemp(Ity_I64);
14123         IRExpr * frD_fp_roundHi = NULL;
14124         IRExpr * frD_fp_roundLo = NULL;
14125
14126         assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
14127         frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
14128         assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
14129         frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
14130
14131         DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB);
14132         putVSReg( XT,
14133                   binop( Iop_64HLtoV128,
14134                          unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
14135                          unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
14136         break;
14137      }
14138      case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
14139      case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
14140      case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
14141      case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
14142      case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
14143      {
14144         const HChar * insn_suffix = NULL;
14145         IROp op;
14146         if (opc2 != 0x156) {
14147            // Use pre-defined IRop's for vrfi{m|n|p|z}
14148            switch (opc2) {
14149               case 0x112:
14150                  insn_suffix = "";
14151                  op = Iop_RoundF32x4_RN;
14152                  break;
14153               case 0x172:
14154                  insn_suffix = "m";
14155                  op = Iop_RoundF32x4_RM;
14156                  break;
14157               case 0x152:
14158                  insn_suffix = "p";
14159                  op = Iop_RoundF32x4_RP;
14160                  break;
14161               case 0x132:
14162                  insn_suffix = "z";
14163                  op = Iop_RoundF32x4_RZ;
14164                  break;
14165
14166               default:
14167                  vex_printf("Unrecognized opcode %x\n", opc2);
14168                  vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
14169            }
14170            DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
14171            putVSReg( XT, unop( op, getVSReg(XB) ) );
14172         } else {
14173            // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
14174            IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
14175            IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
14176            IRTemp b3_I64 = newTemp(Ity_I64);
14177            IRTemp b2_I64 = newTemp(Ity_I64);
14178            IRTemp b1_I64 = newTemp(Ity_I64);
14179            IRTemp b0_I64 = newTemp(Ity_I64);
14180
14181            b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
14182            frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
14183            breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
14184            assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
14185            assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
14186            assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
14187            assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
14188            frD_fp_roundb3 = unop(Iop_TruncF64asF32,
14189                                  _do_vsx_fp_roundToInt(b3_I64, opc2));
14190            frD_fp_roundb2 = unop(Iop_TruncF64asF32,
14191                                  _do_vsx_fp_roundToInt(b2_I64, opc2));
14192            frD_fp_roundb1 = unop(Iop_TruncF64asF32,
14193                                  _do_vsx_fp_roundToInt(b1_I64, opc2));
14194            frD_fp_roundb0 = unop(Iop_TruncF64asF32,
14195                                  _do_vsx_fp_roundToInt(b0_I64, opc2));
14196            DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB);
14197            putVSReg( XT,
14198                      binop( Iop_64HLtoV128,
14199                             binop( Iop_32HLto64,
14200                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
14201                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
14202                             binop( Iop_32HLto64,
14203                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
14204                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
14205         }
14206         break;
14207      }
14208
14209      default:
14210         vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
14211         return False;
14212   }
14213   return True;
14214}
14215
14216
14217/*
14218 * VSX Scalar Floating Point Arithmetic Instructions
14219 */
14220static Bool
14221dis_vxs_arith ( UInt theInstr, UInt opc2 )
14222{
14223   /* XX3-Form */
14224   UChar opc1 = ifieldOPC( theInstr );
14225   UChar XT = ifieldRegXT( theInstr );
14226   UChar XA = ifieldRegXA( theInstr );
14227   UChar XB = ifieldRegXB( theInstr );
14228   IRExpr* rm = get_IR_roundingmode();
14229   IRTemp frA = newTemp(Ity_F64);
14230   IRTemp frB = newTemp(Ity_F64);
14231
14232   if (opc1 != 0x3C) {
14233      vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
14234      return False;
14235   }
14236
14237   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
14238   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14239
14240   /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
14241    * of VSX[XT] are undefined after the operation; therefore, we can simply set
14242    * element to zero where it makes sense to do so.
14243    */
14244   switch (opc2) {
14245      case 0x000: // xsaddsp  (VSX Scalar Add Single-Precision)
14246         DIP("xsaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
14247         putVSReg( XT, binop( Iop_64HLtoV128,
14248                              unop( Iop_ReinterpF64asI64,
14249                                    binop( Iop_RoundF64toF32, rm,
14250                                           triop( Iop_AddF64, rm,
14251                                                  mkexpr( frA ),
14252                                                  mkexpr( frB ) ) ) ),
14253                              mkU64( 0 ) ) );
14254         break;
14255      case 0x020: // xssubsp  (VSX Scalar Subtract Single-Precision)
14256         DIP("xssubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
14257         putVSReg( XT, binop( Iop_64HLtoV128,
14258                              unop( Iop_ReinterpF64asI64,
14259                                    binop( Iop_RoundF64toF32, rm,
14260                                           triop( Iop_SubF64, rm,
14261                                                  mkexpr( frA ),
14262                                                  mkexpr( frB ) ) ) ),
14263                              mkU64( 0 ) ) );
14264         break;
14265      case 0x080: // xsadddp (VSX scalar add double-precision)
14266         DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
14267         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14268                                                    triop( Iop_AddF64, rm,
14269                                                           mkexpr( frA ),
14270                                                           mkexpr( frB ) ) ),
14271                              mkU64( 0 ) ) );
14272         break;
14273      case 0x060: // xsdivsp (VSX scalar divide single-precision)
14274         DIP("xsdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
14275         putVSReg( XT, binop( Iop_64HLtoV128,
14276                              unop( Iop_ReinterpF64asI64,
14277                                    binop( Iop_RoundF64toF32, rm,
14278                                           triop( Iop_DivF64, rm,
14279                                                  mkexpr( frA ),
14280                                                  mkexpr( frB ) ) ) ),
14281                               mkU64( 0 ) ) );
14282         break;
14283      case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
14284         DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
14285         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14286                                                    triop( Iop_DivF64, rm,
14287                                                           mkexpr( frA ),
14288                                                           mkexpr( frB ) ) ),
14289                              mkU64( 0 ) ) );
14290         break;
14291      case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
14292                               * single-precision)
14293                               */
14294      {
14295         IRTemp frT = newTemp(Ity_F64);
14296         Bool mdp = opc2 == 0x024;
14297         DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
14298         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14299                                                        getVSReg( XT ) ) ) );
14300         putVSReg( XT,
14301                   binop( Iop_64HLtoV128,
14302                          unop( Iop_ReinterpF64asI64,
14303                                binop( Iop_RoundF64toF32, rm,
14304                                       qop( Iop_MAddF64, rm,
14305                                            mkexpr( frA ),
14306                                            mkexpr( mdp ? frT : frB ),
14307                                            mkexpr( mdp ? frB : frT ) ) ) ),
14308                          mkU64( 0 ) ) );
14309         break;
14310      }
14311      case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
14312      {
14313         IRTemp frT = newTemp(Ity_F64);
14314         Bool mdp = opc2 == 0x0A4;
14315         DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
14316         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14317                                                        getVSReg( XT ) ) ) );
14318         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14319                                                    qop( Iop_MAddF64, rm,
14320                                                         mkexpr( frA ),
14321                                                         mkexpr( mdp ? frT : frB ),
14322                                                         mkexpr( mdp ? frB : frT ) ) ),
14323                              mkU64( 0 ) ) );
14324         break;
14325      }
14326      case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
14327                               * multiply-subtract single-precision)
14328			       */
14329      {
14330         IRTemp frT = newTemp(Ity_F64);
14331         Bool mdp = opc2 == 0x064;
14332         DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
14333         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14334                                                        getVSReg( XT ) ) ) );
14335         putVSReg( XT,
14336                   binop( Iop_64HLtoV128,
14337                          unop( Iop_ReinterpF64asI64,
14338                                binop( Iop_RoundF64toF32, rm,
14339                                       qop( Iop_MSubF64, rm,
14340                                            mkexpr( frA ),
14341                                            mkexpr( mdp ? frT : frB ),
14342                                            mkexpr( mdp ? frB : frT ) ) ) ),
14343                          mkU64( 0 ) ) );
14344         break;
14345      }
14346      case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
14347      {
14348         IRTemp frT = newTemp(Ity_F64);
14349         Bool mdp = opc2 == 0x0E4;
14350         DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
14351         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14352                                                        getVSReg( XT ) ) ) );
14353         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14354                                                    qop( Iop_MSubF64, rm,
14355                                                         mkexpr( frA ),
14356                                                         mkexpr( mdp ? frT : frB ),
14357                                                         mkexpr( mdp ? frB : frT ) ) ),
14358                              mkU64( 0 ) ) );
14359         break;
14360      }
14361      case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
14362      {
14363         /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
14364          * of fnmadd and use pretty much the same code. However, that code has a bug in the
14365          * way it blindly negates the signbit, even if the floating point result is a NaN.
14366          * So, the TODO is to fix fnmadd (which I'll do in a different patch).
14367          * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
14368          * bit for NaN result.
14369          */
14370         Bool mdp = opc2 == 0x2A4;
14371         IRTemp frT = newTemp(Ity_F64);
14372         IRTemp maddResult = newTemp(Ity_I64);
14373
14374         DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
14375         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14376                                                        getVSReg( XT ) ) ) );
14377         assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
14378                                                              mkexpr( frA ),
14379                                                              mkexpr( mdp ? frT : frB ),
14380                                                              mkexpr( mdp ? frB : frT ) ) ) );
14381
14382         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
14383                              mkU64( 0 ) ) );
14384         break;
14385      }
14386      case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
14387                               * multiply-add single-precision)
14388                               */
14389      {
14390         Bool mdp = opc2 == 0x224;
14391         IRTemp frT = newTemp(Ity_F64);
14392         IRTemp maddResult = newTemp(Ity_I64);
14393
14394         DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
14395         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14396                                                        getVSReg( XT ) ) ) );
14397         assign( maddResult,
14398                 unop( Iop_ReinterpF64asI64,
14399                       binop( Iop_RoundF64toF32, rm,
14400                              qop( Iop_MAddF64, rm,
14401                                   mkexpr( frA ),
14402                                   mkexpr( mdp ? frT : frB ),
14403                                   mkexpr( mdp ? frB : frT ) ) ) ) );
14404
14405         putVSReg( XT, binop( Iop_64HLtoV128,
14406                              mkexpr( getNegatedResult(maddResult) ),
14407                              mkU64( 0 ) ) );
14408         break;
14409      }
14410      case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
14411                               * Multiply-Subtract Single-Precision)
14412                               */
14413      {
14414         IRTemp frT = newTemp(Ity_F64);
14415         Bool mdp = opc2 == 0x264;
14416         IRTemp msubResult = newTemp(Ity_I64);
14417
14418         DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
14419         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14420                                                        getVSReg( XT ) ) ) );
14421         assign( msubResult,
14422                 unop( Iop_ReinterpF64asI64,
14423                       binop( Iop_RoundF64toF32, rm,
14424                              qop( Iop_MSubF64, rm,
14425                                   mkexpr( frA ),
14426                                   mkexpr( mdp ? frT : frB ),
14427                                   mkexpr( mdp ? frB : frT ) ) ) ) );
14428
14429         putVSReg( XT, binop( Iop_64HLtoV128,
14430                              mkexpr( getNegatedResult(msubResult) ),
14431                              mkU64( 0 ) ) );
14432
14433         break;
14434      }
14435
14436      case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
14437      {
14438         IRTemp frT = newTemp(Ity_F64);
14439         Bool mdp = opc2 == 0x2E4;
14440         IRTemp msubResult = newTemp(Ity_I64);
14441
14442         DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
14443         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14444                                                        getVSReg( XT ) ) ) );
14445         assign(msubResult, unop( Iop_ReinterpF64asI64,
14446                                      qop( Iop_MSubF64,
14447                                           rm,
14448                                           mkexpr( frA ),
14449                                           mkexpr( mdp ? frT : frB ),
14450                                           mkexpr( mdp ? frB : frT ) ) ));
14451
14452         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
14453
14454         break;
14455      }
14456
14457      case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
14458         DIP("xsmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
14459         putVSReg( XT, binop( Iop_64HLtoV128,
14460                              unop( Iop_ReinterpF64asI64,
14461                                    binop( Iop_RoundF64toF32, rm,
14462                                           triop( Iop_MulF64, rm,
14463                                                   mkexpr( frA ),
14464                                                   mkexpr( frB ) ) ) ),
14465                              mkU64( 0 ) ) );
14466         break;
14467
14468      case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
14469         DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
14470         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14471                                                    triop( Iop_MulF64, rm,
14472                                                           mkexpr( frA ),
14473                                                           mkexpr( frB ) ) ),
14474                              mkU64( 0 ) ) );
14475         break;
14476      case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
14477         DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
14478         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14479                                                    triop( Iop_SubF64, rm,
14480                                                           mkexpr( frA ),
14481                                                           mkexpr( frB ) ) ),
14482                              mkU64( 0 ) ) );
14483         break;
14484
14485      case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
14486         DIP("xssqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
14487         putVSReg( XT,
14488                   binop( Iop_64HLtoV128,
14489                          unop( Iop_ReinterpF64asI64,
14490                                binop( Iop_RoundF64toF32, rm,
14491                                       binop( Iop_SqrtF64, rm,
14492                                              mkexpr( frB ) ) ) ),
14493                          mkU64( 0 ) ) );
14494         break;
14495
14496      case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
14497         DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
14498         putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14499                                                     binop( Iop_SqrtF64, rm,
14500                                                            mkexpr( frB ) ) ),
14501                               mkU64( 0 ) ) );
14502         break;
14503
14504      case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
14505      {
14506         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
14507         IRTemp frA_I64 = newTemp(Ity_I64);
14508         IRTemp frB_I64 = newTemp(Ity_I64);
14509         DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB);
14510         assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
14511         assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
14512         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
14513         break;
14514      }
14515      case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
14516      {
14517         IRTemp frB_I64 = newTemp(Ity_I64);
14518         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
14519         IRTemp flags = newTemp(Ity_I32);
14520         IRTemp  fe_flag, fg_flag;
14521         fe_flag = fg_flag = IRTemp_INVALID;
14522         DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
14523         assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
14524         do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
14525         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
14526          * where fl_flag == 1 on ppc64.
14527          */
14528         assign( flags,
14529                 binop( Iop_Or32,
14530                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
14531                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
14532                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
14533         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
14534         break;
14535      }
14536
14537      default:
14538         vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
14539         return False;
14540   }
14541
14542   return True;
14543}
14544
14545
14546/*
14547 * VSX Floating Point Compare Instructions
14548 */
14549static Bool
14550dis_vx_cmp( UInt theInstr, UInt opc2 )
14551{
14552   /* XX3-Form and XX2-Form */
14553   UChar opc1 = ifieldOPC( theInstr );
14554   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
14555   IRTemp ccPPC32;
14556   UChar XA       = ifieldRegXA ( theInstr );
14557   UChar XB       = ifieldRegXB ( theInstr );
14558   IRTemp frA     = newTemp(Ity_F64);
14559   IRTemp frB     = newTemp(Ity_F64);
14560
14561   if (opc1 != 0x3C) {
14562      vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
14563      return False;
14564   }
14565
14566   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
14567   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14568   switch (opc2) {
14569      case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
14570         /* Note: Differences between xscmpudp and xscmpodp are only in
14571          * exception flag settings, which aren't supported anyway. */
14572         DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
14573                                           crfD, (UInt)XA, (UInt)XB);
14574         ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
14575         putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
14576         break;
14577
14578      default:
14579         vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
14580         return False;
14581   }
14582   return True;
14583}
14584
14585static void
14586do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
14587                 ppc_cmp_t cmp_type )
14588{
14589   IRTemp frA_hi     = newTemp(Ity_F64);
14590   IRTemp frB_hi     = newTemp(Ity_F64);
14591   IRTemp frA_lo     = newTemp(Ity_F64);
14592   IRTemp frB_lo     = newTemp(Ity_F64);
14593   IRTemp ccPPC32    = newTemp(Ity_I32);
14594   IRTemp ccIR_hi;
14595   IRTemp ccIR_lo;
14596
14597   IRTemp hiResult = newTemp(Ity_I64);
14598   IRTemp loResult = newTemp(Ity_I64);
14599   IRTemp hiEQlo = newTemp(Ity_I1);
14600   IRTemp all_elem_true = newTemp(Ity_I32);
14601   IRTemp all_elem_false = newTemp(Ity_I32);
14602
14603   assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
14604   assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
14605   assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
14606   assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
14607
14608   ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
14609                                       mkexpr( frA_hi ),
14610                                       mkexpr( frB_hi ) ) );
14611   ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
14612                                       mkexpr( frA_lo ),
14613                                       mkexpr( frB_lo ) ) );
14614
14615   if (cmp_type != PPC_CMP_GE) {
14616      assign( hiResult,
14617              unop( Iop_1Sto64,
14618                    binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
14619      assign( loResult,
14620              unop( Iop_1Sto64,
14621                    binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
14622   } else {
14623      // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
14624      // the other element compare may return "2" (for "equal to").
14625      IRTemp lo_GE = newTemp(Ity_I1);
14626      IRTemp hi_GE = newTemp(Ity_I1);
14627
14628      assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
14629                           binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
14630      assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
14631
14632      assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
14633                           binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
14634      assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
14635   }
14636
14637   // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
14638   assign( hiEQlo,
14639           binop( Iop_CmpEQ32,
14640                  unop( Iop_64to32, mkexpr( hiResult ) ),
14641                  unop( Iop_64to32, mkexpr( loResult ) ) ) );
14642   putVSReg( XT,
14643             binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
14644
14645   assign( all_elem_true,
14646           unop( Iop_1Uto32,
14647                 mkAND1( mkexpr( hiEQlo ),
14648                         binop( Iop_CmpEQ32,
14649                                mkU32( 0xffffffff ),
14650                                unop( Iop_64to32,
14651                                mkexpr( hiResult ) ) ) ) ) );
14652
14653   assign( all_elem_false,
14654           unop( Iop_1Uto32,
14655                 mkAND1( mkexpr( hiEQlo ),
14656                         binop( Iop_CmpEQ32,
14657                                mkU32( 0 ),
14658                                unop( Iop_64to32,
14659                                mkexpr( hiResult ) ) ) ) ) );
14660   assign( ccPPC32,
14661           binop( Iop_Or32,
14662                  binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
14663                  binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
14664
14665   if (flag_rC) {
14666      putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
14667   }
14668}
14669
14670/*
14671 * VSX Vector Compare Instructions
14672 */
14673static Bool
14674dis_vvec_cmp( UInt theInstr, UInt opc2 )
14675{
14676   /* XX3-Form */
14677   UChar opc1 = ifieldOPC( theInstr );
14678   UChar XT = ifieldRegXT ( theInstr );
14679   UChar XA = ifieldRegXA ( theInstr );
14680   UChar XB = ifieldRegXB ( theInstr );
14681   UChar flag_rC  = ifieldBIT10(theInstr);
14682   IRTemp vA = newTemp( Ity_V128 );
14683   IRTemp vB = newTemp( Ity_V128 );
14684
14685   if (opc1 != 0x3C) {
14686      vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
14687      return False;
14688   }
14689
14690   assign( vA, getVSReg( XA ) );
14691   assign( vB, getVSReg( XB ) );
14692
14693   switch (opc2) {
14694      case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
14695      {
14696         DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
14697             (UInt)XT, (UInt)XA, (UInt)XB);
14698         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
14699         break;
14700      }
14701
14702      case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
14703      {
14704         DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
14705             (UInt)XT, (UInt)XA, (UInt)XB);
14706         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
14707         break;
14708      }
14709
14710      case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
14711      {
14712         DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
14713             (UInt)XT, (UInt)XA, (UInt)XB);
14714         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
14715         break;
14716      }
14717
14718      case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
14719      {
14720         IRTemp vD = newTemp(Ity_V128);
14721
14722         DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
14723             (UInt)XT, (UInt)XA, (UInt)XB);
14724         assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
14725         putVSReg( XT, mkexpr(vD) );
14726         if (flag_rC) {
14727            set_AV_CR6( mkexpr(vD), True );
14728         }
14729         break;
14730      }
14731
14732      case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
14733      {
14734         IRTemp vD = newTemp(Ity_V128);
14735
14736         DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
14737             (UInt)XT, (UInt)XA, (UInt)XB);
14738         assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
14739         putVSReg( XT, mkexpr(vD) );
14740         if (flag_rC) {
14741            set_AV_CR6( mkexpr(vD), True );
14742         }
14743         break;
14744      }
14745
14746      case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
14747      {
14748         IRTemp vD = newTemp(Ity_V128);
14749
14750         DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
14751             (UInt)XT, (UInt)XA, (UInt)XB);
14752         assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
14753         putVSReg( XT, mkexpr(vD) );
14754         if (flag_rC) {
14755            set_AV_CR6( mkexpr(vD), True );
14756         }
14757         break;
14758      }
14759
14760      default:
14761         vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
14762         return False;
14763   }
14764   return True;
14765}
14766/*
14767 * Miscellaneous VSX Scalar Instructions
14768 */
14769static Bool
14770dis_vxs_misc( UInt theInstr, UInt opc2 )
14771{
14772   /* XX3-Form and XX2-Form */
14773   UChar opc1 = ifieldOPC( theInstr );
14774   UChar XT = ifieldRegXT ( theInstr );
14775   UChar XA = ifieldRegXA ( theInstr );
14776   UChar XB = ifieldRegXB ( theInstr );
14777   IRTemp vA = newTemp( Ity_V128 );
14778   IRTemp vB = newTemp( Ity_V128 );
14779
14780   if (opc1 != 0x3C) {
14781      vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
14782      return False;
14783   }
14784
14785   assign( vA, getVSReg( XA ) );
14786   assign( vB, getVSReg( XB ) );
14787
14788   /* For all the VSX move instructions, the contents of doubleword element 1
14789    * of VSX[XT] are undefined after the operation; therefore, we can simply
14790    * move the entire array element where it makes sense to do so.
14791    */
14792
14793   switch (opc2) {
14794      case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
14795      {
14796         /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
14797         IRTemp absVal = newTemp(Ity_V128);
14798         assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1)));
14799         DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
14800         putVSReg(XT, mkexpr(absVal));
14801         break;
14802      }
14803      case 0x2C0: // xscpsgndp
14804      {
14805         /* Scalar copy sign double-precision */
14806         IRTemp vecA_signbit = newTemp(Ity_V128);
14807         IRTemp vecB_no_signbit = newTemp(Ity_V128);
14808         IRTemp vec_result = newTemp(Ity_V128);
14809         DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
14810         assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
14811                                                             mkexpr( vB ),
14812                                                             mkU8( 1 ) ),
14813                                         mkU8( 1 ) ) );
14814         assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128,
14815                                                          mkexpr( vA ),
14816                                                          mkU8( 127 ) ),
14817                                      mkU8( 127 ) ) );
14818         assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) );
14819         putVSReg(XT, mkexpr(vec_result));
14820         break;
14821      }
14822      case 0x2D2: // xsnabsdp
14823      {
14824         /* Scalar negative absolute value double-precision */
14825         IRTemp vec_neg_signbit = newTemp(Ity_V128);
14826         DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
14827         assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128,
14828                                                            mkV128( 0xffff ),
14829                                                            mkU8( 1 ) ) ) );
14830         putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB)));
14831         break;
14832      }
14833      case 0x2F2: // xsnegdp
14834      {
14835         /* Scalar negate double-precision */
14836         IRTemp vecB_no_signbit = newTemp(Ity_V128);
14837         IRTemp vecB_signbit_comp = newTemp(Ity_V128);
14838         DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
14839         assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
14840                                                             mkexpr( vB ),
14841                                                             mkU8( 1 ) ),
14842                                         mkU8( 1 ) ) );
14843         assign( vecB_signbit_comp, binop( Iop_ShlV128,
14844                                           unop( Iop_NotV128,
14845                                                 binop( Iop_ShrV128,
14846                                                        mkexpr( vB ),
14847                                                        mkU8( 127 ) ) ),
14848                                           mkU8( 127 ) ) );
14849         putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ),
14850                              mkexpr( vecB_signbit_comp ) ) );
14851         break;
14852      }
14853      case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
14854      case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
14855      {
14856         IRTemp frA     = newTemp(Ity_I64);
14857         IRTemp frB     = newTemp(Ity_I64);
14858         Bool isMin = opc2 == 0x2A0 ? True : False;
14859         DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB);
14860
14861         assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
14862         assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
14863         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
14864
14865         break;
14866      }
14867      case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
14868      case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
14869      case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
14870      case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
14871      case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
14872      {
14873         IRTemp frB_I64 = newTemp(Ity_I64);
14874         IRExpr * frD_fp_round = NULL;
14875
14876         assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
14877         frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
14878
14879         DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB);
14880         putVSReg( XT,
14881                   binop( Iop_64HLtoV128,
14882                          unop( Iop_ReinterpF64asI64, frD_fp_round),
14883                          mkU64( 0 ) ) );
14884         break;
14885      }
14886      case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
14887      case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
14888                   * single-Precision)
14889                   */
14890      {
14891         IRTemp frB = newTemp(Ity_F64);
14892         IRTemp sqrt = newTemp(Ity_F64);
14893         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
14894         IRExpr* rm  = get_IR_roundingmode();
14895         Bool redp = opc2 == 0x034;
14896         DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", (UInt)XT,
14897             (UInt)XB);
14898
14899         assign( frB,
14900                 unop( Iop_ReinterpI64asF64,
14901                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
14902
14903         if (!redp)
14904            assign( sqrt,
14905                    binop( Iop_SqrtF64,
14906                           rm,
14907                           mkexpr(frB) ) );
14908         putVSReg( XT,
14909                      binop( Iop_64HLtoV128,
14910                             unop( Iop_ReinterpF64asI64,
14911                                   binop( Iop_RoundF64toF32, rm,
14912                                          triop( Iop_DivF64,
14913                                                 rm,
14914                                                 ieee_one,
14915                                                 redp ? mkexpr( frB ) :
14916                                                        mkexpr( sqrt ) ) ) ),
14917                             mkU64( 0 ) ) );
14918         break;
14919      }
14920
14921      case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
14922      case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
14923
14924      {
14925         IRTemp frB = newTemp(Ity_F64);
14926         IRTemp sqrt = newTemp(Ity_F64);
14927         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
14928         IRExpr* rm  = get_IR_roundingmode();
14929         Bool redp = opc2 == 0x0B4;
14930         DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB);
14931         assign( frB,
14932                 unop( Iop_ReinterpI64asF64,
14933                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
14934
14935         if (!redp)
14936            assign( sqrt,
14937                    binop( Iop_SqrtF64,
14938                           rm,
14939                           mkexpr(frB) ) );
14940         putVSReg( XT,
14941                      binop( Iop_64HLtoV128,
14942                             unop( Iop_ReinterpF64asI64,
14943                                   triop( Iop_DivF64,
14944                                          rm,
14945                                          ieee_one,
14946                                          redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
14947                             mkU64( 0 ) ) );
14948         break;
14949      }
14950
14951      case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
14952      {
14953         IRTemp frB = newTemp(Ity_F64);
14954         IRExpr* rm  = get_IR_roundingmode();
14955         DIP("xsrsp v%d, v%d\n", (UInt)XT, (UInt)XB);
14956         assign( frB,
14957                 unop( Iop_ReinterpI64asF64,
14958                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
14959
14960         putVSReg( XT, binop( Iop_64HLtoV128,
14961                              unop( Iop_ReinterpF64asI64,
14962                                    binop( Iop_RoundF64toF32,
14963                                           rm,
14964                                           mkexpr( frB ) ) ),
14965                              mkU64( 0 ) ) );
14966         break;
14967      }
14968
14969      default:
14970         vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
14971         return False;
14972   }
14973   return True;
14974}
14975
14976/*
14977 * VSX Logical Instructions
14978 */
14979static Bool
14980dis_vx_logic ( UInt theInstr, UInt opc2 )
14981{
14982   /* XX3-Form */
14983   UChar opc1 = ifieldOPC( theInstr );
14984   UChar XT = ifieldRegXT ( theInstr );
14985   UChar XA = ifieldRegXA ( theInstr );
14986   UChar XB = ifieldRegXB ( theInstr );
14987   IRTemp vA = newTemp( Ity_V128 );
14988   IRTemp vB = newTemp( Ity_V128 );
14989
14990   if (opc1 != 0x3C) {
14991      vex_printf( "dis_vx_logic(ppc)(instr)\n" );
14992      return False;
14993   }
14994
14995   assign( vA, getVSReg( XA ) );
14996   assign( vB, getVSReg( XB ) );
14997
14998   switch (opc2) {
14999      case 0x268: // xxlxor
15000         DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
15001         putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
15002         break;
15003      case 0x248: // xxlor
15004         DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
15005         putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
15006         break;
15007      case 0x288: // xxlnor
15008         DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
15009         putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
15010                                                 mkexpr( vB ) ) ) );
15011         break;
15012      case 0x208: // xxland
15013         DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
15014         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
15015         break;
15016      case 0x228: //xxlandc
15017         DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
15018         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
15019                                                               mkexpr( vB ) ) ) );
15020         break;
15021      case 0x2A8: // xxlorc (VSX Logical OR with complement)
15022         DIP("xxlorc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
15023         putVSReg( XT, binop( Iop_OrV128,
15024                              mkexpr( vA ),
15025                              unop( Iop_NotV128, mkexpr( vB ) ) ) );
15026         break;
15027      case 0x2C8: // xxlnand (VSX Logical NAND)
15028         DIP("xxlnand v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
15029         putVSReg( XT, unop( Iop_NotV128,
15030                             binop( Iop_AndV128, mkexpr( vA ),
15031                                    mkexpr( vB ) ) ) );
15032         break;
15033      case 0x2E8: // xxleqv (VSX Logical Equivalence)
15034         DIP("xxleqv v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
15035         putVSReg( XT, unop( Iop_NotV128,
15036                             binop( Iop_XorV128,
15037                             mkexpr( vA ), mkexpr( vB ) ) ) );
15038         break;
15039      default:
15040         vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
15041         return False;
15042   }
15043   return True;
15044}
15045
15046/*
15047 * VSX Load Instructions
15048 * NOTE: VSX supports word-aligned storage access.
15049 */
15050static Bool
15051dis_vx_load ( UInt theInstr )
15052{
15053   /* XX1-Form */
15054   UChar opc1 = ifieldOPC( theInstr );
15055   UChar XT = ifieldRegXT ( theInstr );
15056   UChar rA_addr = ifieldRegA( theInstr );
15057   UChar rB_addr = ifieldRegB( theInstr );
15058   UInt opc2 = ifieldOPClo10( theInstr );
15059
15060   IRType ty = mode64 ? Ity_I64 : Ity_I32;
15061   IRTemp EA = newTemp( ty );
15062
15063   if (opc1 != 0x1F) {
15064      vex_printf( "dis_vx_load(ppc)(instr)\n" );
15065      return False;
15066   }
15067
15068   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
15069
15070   switch (opc2) {
15071   case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
15072   {
15073      IRExpr * exp;
15074      DIP("lxsiwzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
15075      exp = unop( Iop_64HIto32, loadBE( Ity_I64, mkexpr( EA ) ) );
15076      putVSReg( XT, binop( Iop_64HLtoV128,
15077                           unop( Iop_32Uto64, exp),
15078                           mkU64(0) ) );
15079      break;
15080   }
15081   case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
15082   {
15083      IRExpr * exp;
15084      DIP("lxsiwax %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
15085      exp = unop( Iop_64HIto32, loadBE( Ity_I64, mkexpr( EA ) ) );
15086      putVSReg( XT, binop( Iop_64HLtoV128,
15087                           unop( Iop_32Sto64, exp),
15088                           mkU64(0) ) );
15089      break;
15090   }
15091   case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
15092   {
15093      IRExpr * exp;
15094      DIP("lxsspx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
15095      /* Take 32-bit floating point value in the upper half of the fetched
15096       * 64-bit value, convert to 64-bit floating point value and load into
15097       * top word of V128.
15098       */
15099      exp = unop( Iop_ReinterpF64asI64,
15100                  unop( Iop_F32toF64,
15101                        unop( Iop_ReinterpI32asF32,
15102                              unop( Iop_64HIto32,
15103                                    loadBE( Ity_I64, mkexpr( EA ) ) ) ) ) );
15104
15105      putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
15106      break;
15107   }
15108   case 0x24C: // lxsdx
15109   {
15110      IRExpr * exp;
15111      DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
15112      exp = loadBE( Ity_I64, mkexpr( EA ) );
15113      // We need to pass an expression of type Ity_V128 with putVSReg, but the load
15114      // we just performed is only a DW.  But since the contents of VSR[XT] element 1
15115      // are undefined after this operation, we can just do a splat op.
15116      putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
15117      break;
15118   }
15119   case 0x34C: // lxvd2x
15120   {
15121      IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
15122      IRExpr * high, *low;
15123      ULong ea_off = 8;
15124      IRExpr* high_addr;
15125      DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
15126      high = loadBE( Ity_I64, mkexpr( EA ) );
15127      high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
15128            : mkU32( ea_off ) );
15129      low = loadBE( Ity_I64, high_addr );
15130      putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
15131      break;
15132   }
15133   case 0x14C: // lxvdsx
15134   {
15135      IRTemp data = newTemp(Ity_I64);
15136      DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
15137      assign( data, loadBE( Ity_I64, mkexpr( EA ) ) );
15138      putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
15139      break;
15140   }
15141   case 0x30C:
15142   {
15143      IRExpr * t3, *t2, *t1, *t0;
15144      UInt ea_off = 0;
15145      IRExpr* irx_addr;
15146
15147      DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
15148      t3 = loadBE( Ity_I32,  mkexpr( EA ) );
15149      ea_off += 4;
15150      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15151                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15152      t2 = loadBE( Ity_I32, irx_addr );
15153      ea_off += 4;
15154      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15155                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15156      t1 = loadBE( Ity_I32, irx_addr );
15157      ea_off += 4;
15158      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15159                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15160      t0 = loadBE( Ity_I32, irx_addr );
15161      putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ),
15162                           binop( Iop_32HLto64, t1, t0 ) ) );
15163      break;
15164   }
15165   default:
15166      vex_printf( "dis_vx_load(ppc)(opc2)\n" );
15167      return False;
15168   }
15169   return True;
15170}
15171
15172/*
15173 * VSX Store Instructions
15174 * NOTE: VSX supports word-aligned storage access.
15175 */
15176static Bool
15177dis_vx_store ( UInt theInstr )
15178{
15179   /* XX1-Form */
15180   UChar opc1 = ifieldOPC( theInstr );
15181   UChar XS = ifieldRegXS( theInstr );
15182   UChar rA_addr = ifieldRegA( theInstr );
15183   UChar rB_addr = ifieldRegB( theInstr );
15184   IRTemp vS = newTemp( Ity_V128 );
15185   UInt opc2 = ifieldOPClo10( theInstr );
15186
15187   IRType ty = mode64 ? Ity_I64 : Ity_I32;
15188   IRTemp EA = newTemp( ty );
15189
15190   if (opc1 != 0x1F) {
15191      vex_printf( "dis_vx_store(ppc)(instr)\n" );
15192      return False;
15193   }
15194
15195   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
15196   assign( vS, getVSReg( XS ) );
15197
15198   switch (opc2) {
15199   case 0x08C:
15200   {
15201     /* Need the next to the most significant 32-bit word from
15202      * the 128-bit vector.
15203      */
15204      IRExpr * high64, * low32;
15205      DIP("stxsiwx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
15206      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15207      low32  = unop( Iop_64to32, high64 );
15208      storeBE( mkexpr( EA ), low32 );
15209      break;
15210   }
15211   case 0x28C:
15212   {
15213      IRTemp high64 = newTemp(Ity_F64);
15214      IRTemp val32  = newTemp(Ity_I32);
15215      DIP("stxsspx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
15216      assign(high64, unop( Iop_ReinterpI64asF64,
15217                           unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
15218      assign(val32, unop( Iop_ReinterpF32asI32,
15219                          unop( Iop_TruncF64asF32,
15220                                mkexpr(high64) ) ) );
15221      storeBE( mkexpr( EA ), mkexpr( val32 ) );
15222      break;
15223   }
15224   case 0x2CC:
15225   {
15226      IRExpr * high64;
15227      DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
15228      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15229      storeBE( mkexpr( EA ), high64 );
15230      break;
15231   }
15232   case 0x3CC:
15233   {
15234      IRExpr * high64, *low64;
15235      DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
15236      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15237      low64 = unop( Iop_V128to64, mkexpr( vS ) );
15238      storeBE( mkexpr( EA ), high64 );
15239      storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 )
15240            : mkU32( 8 ) ), low64 );
15241      break;
15242   }
15243   case 0x38C:
15244   {
15245      UInt ea_off = 0;
15246      IRExpr* irx_addr;
15247      IRTemp hi64 = newTemp( Ity_I64 );
15248      IRTemp lo64 = newTemp( Ity_I64 );
15249
15250      DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
15251
15252      // This instruction supports word-aligned stores, so EA may not be
15253      // quad-word aligned.  Therefore, do 4 individual word-size stores.
15254      assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
15255      assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
15256
15257      storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
15258      ea_off += 4;
15259      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15260                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15261      storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
15262      ea_off += 4;
15263      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15264                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15265      storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
15266      ea_off += 4;
15267      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15268                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15269      storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
15270
15271      break;
15272   }
15273   default:
15274      vex_printf( "dis_vx_store(ppc)(opc2)\n" );
15275      return False;
15276   }
15277   return True;
15278}
15279
15280/*
15281 * VSX permute and other miscealleous instructions
15282 */
15283static Bool
15284dis_vx_permute_misc( UInt theInstr, UInt opc2 )
15285{
15286   /* XX3-Form */
15287   UChar opc1 = ifieldOPC( theInstr );
15288   UChar XT = ifieldRegXT ( theInstr );
15289   UChar XA = ifieldRegXA ( theInstr );
15290   UChar XB = ifieldRegXB ( theInstr );
15291   IRTemp vT = newTemp( Ity_V128 );
15292   IRTemp vA = newTemp( Ity_V128 );
15293   IRTemp vB = newTemp( Ity_V128 );
15294
15295   if (opc1 != 0x3C) {
15296      vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
15297      return False;
15298   }
15299
15300   assign( vA, getVSReg( XA ) );
15301   assign( vB, getVSReg( XB ) );
15302
15303   switch (opc2) {
15304      case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
15305      {
15306         UChar SHW = ifieldSHW ( theInstr );
15307         IRTemp result = newTemp(Ity_V128);
15308         if ( SHW != 0 ) {
15309             IRTemp hi = newTemp(Ity_V128);
15310             IRTemp lo = newTemp(Ity_V128);
15311             assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
15312             assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
15313             assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
15314         } else
15315             assign ( result, mkexpr(vA) );
15316         DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW);
15317         putVSReg( XT, mkexpr(result) );
15318         break;
15319      }
15320      case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
15321      {
15322         UChar DM = ifieldDM ( theInstr );
15323         IRTemp hi = newTemp(Ity_I64);
15324         IRTemp lo = newTemp(Ity_I64);
15325
15326         if (DM & 0x2)
15327           assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
15328         else
15329           assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
15330
15331         if (DM & 0x1)
15332           assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
15333         else
15334           assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
15335
15336         assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
15337
15338         DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM);
15339         putVSReg( XT, mkexpr( vT ) );
15340         break;
15341      }
15342      case 0x48: // xxmrghw (VSX Merge High Word)
15343      case 0xc8: // xxmrglw (VSX Merge Low Word)
15344      {
15345         const HChar type = (opc2 == 0x48) ? 'h' : 'l';
15346         IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
15347         IRTemp a64 = newTemp(Ity_I64);
15348         IRTemp ahi32 = newTemp(Ity_I32);
15349         IRTemp alo32 = newTemp(Ity_I32);
15350         IRTemp b64 = newTemp(Ity_I64);
15351         IRTemp bhi32 = newTemp(Ity_I32);
15352         IRTemp blo32 = newTemp(Ity_I32);
15353
15354         assign( a64, unop(word_op, mkexpr(vA)) );
15355         assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
15356         assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
15357
15358         assign( b64, unop(word_op, mkexpr(vB)) );
15359         assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
15360         assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
15361
15362         assign( vT, binop(Iop_64HLtoV128,
15363                           binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
15364                           binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
15365
15366         DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB);
15367         putVSReg( XT, mkexpr( vT ) );
15368         break;
15369      }
15370      case 0x018: // xxsel (VSX Select)
15371      {
15372         UChar XC = ifieldRegXC(theInstr);
15373         IRTemp vC = newTemp( Ity_V128 );
15374         assign( vC, getVSReg( XC ) );
15375         DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC);
15376         /* vD = (vA & ~vC) | (vB & vC) */
15377         putVSReg( XT, binop(Iop_OrV128,
15378            binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
15379            binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
15380         break;
15381      }
15382      case 0x148: // xxspltw (VSX Splat Word)
15383      {
15384         UChar UIM   = ifieldRegA(theInstr) & 3;
15385         UChar sh_uim = (3 - (UIM)) * 32;
15386         DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM);
15387         putVSReg( XT,
15388                   unop( Iop_Dup32x4,
15389                         unop( Iop_V128to32,
15390                               binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
15391         break;
15392      }
15393
15394      default:
15395         vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
15396         return False;
15397   }
15398   return True;
15399}
15400
15401/*
15402  AltiVec Load Instructions
15403*/
15404static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
15405{
15406   /* X-Form */
15407   UChar opc1     = ifieldOPC(theInstr);
15408   UChar vD_addr  = ifieldRegDS(theInstr);
15409   UChar rA_addr  = ifieldRegA(theInstr);
15410   UChar rB_addr  = ifieldRegB(theInstr);
15411   UInt  opc2     = ifieldOPClo10(theInstr);
15412   UChar b0       = ifieldBIT0(theInstr);
15413
15414   IRType ty         = mode64 ? Ity_I64 : Ity_I32;
15415   IRTemp EA         = newTemp(ty);
15416   IRTemp EA_align16 = newTemp(ty);
15417
15418   if (opc1 != 0x1F || b0 != 0) {
15419      vex_printf("dis_av_load(ppc)(instr)\n");
15420      return False;
15421   }
15422
15423   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
15424   assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
15425
15426   switch (opc2) {
15427
15428   case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
15429      IRDirty* d;
15430      UInt vD_off = vectorGuestRegOffset(vD_addr);
15431      IRExpr** args = mkIRExprVec_4(
15432                         IRExpr_BBPTR(),
15433                         mkU32(vD_off),
15434                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15435                                          mkU32(0xF)),
15436                         mkU32(0)/*left*/ );
15437      if (!mode64) {
15438         d = unsafeIRDirty_0_N (
15439                        0/*regparms*/,
15440                        "ppc32g_dirtyhelper_LVS",
15441                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
15442                        args );
15443      } else {
15444         d = unsafeIRDirty_0_N (
15445                        0/*regparms*/,
15446                        "ppc64g_dirtyhelper_LVS",
15447                        fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
15448                        args );
15449      }
15450      DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15451      /* declare guest state effects */
15452      d->nFxState = 1;
15453      vex_bzero(&d->fxState, sizeof(d->fxState));
15454      d->fxState[0].fx     = Ifx_Write;
15455      d->fxState[0].offset = vD_off;
15456      d->fxState[0].size   = sizeof(U128);
15457
15458      /* execute the dirty call, side-effecting guest state */
15459      stmt( IRStmt_Dirty(d) );
15460      break;
15461   }
15462   case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
15463      IRDirty* d;
15464      UInt vD_off = vectorGuestRegOffset(vD_addr);
15465      IRExpr** args = mkIRExprVec_4(
15466                         IRExpr_BBPTR(),
15467                         mkU32(vD_off),
15468                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15469                                          mkU32(0xF)),
15470                         mkU32(1)/*right*/ );
15471      if (!mode64) {
15472         d = unsafeIRDirty_0_N (
15473                        0/*regparms*/,
15474                        "ppc32g_dirtyhelper_LVS",
15475                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
15476                        args );
15477      } else {
15478         d = unsafeIRDirty_0_N (
15479                        0/*regparms*/,
15480                        "ppc64g_dirtyhelper_LVS",
15481                        fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
15482                        args );
15483      }
15484      DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15485      /* declare guest state effects */
15486      d->nFxState = 1;
15487      vex_bzero(&d->fxState, sizeof(d->fxState));
15488      d->fxState[0].fx     = Ifx_Write;
15489      d->fxState[0].offset = vD_off;
15490      d->fxState[0].size   = sizeof(U128);
15491
15492      /* execute the dirty call, side-effecting guest state */
15493      stmt( IRStmt_Dirty(d) );
15494      break;
15495   }
15496   case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
15497      DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15498      /* loads addressed byte into vector[EA[0:3]
15499         since all other destination bytes are undefined,
15500         can simply load entire vector from 16-aligned EA */
15501      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
15502      break;
15503
15504   case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
15505      DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15506      /* see note for lvebx */
15507      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
15508      break;
15509
15510   case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
15511      DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15512      /* see note for lvebx */
15513      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
15514      break;
15515
15516   case 0x067: // lvx (Load Vector Indexed, AV p127)
15517      DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15518      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
15519      break;
15520
15521   case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
15522      DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15523      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
15524      break;
15525
15526   default:
15527      vex_printf("dis_av_load(ppc)(opc2)\n");
15528      return False;
15529   }
15530   return True;
15531}
15532
15533/*
15534  AltiVec Store Instructions
15535*/
15536static Bool dis_av_store ( UInt theInstr )
15537{
15538   /* X-Form */
15539   UChar opc1     = ifieldOPC(theInstr);
15540   UChar vS_addr  = ifieldRegDS(theInstr);
15541   UChar rA_addr  = ifieldRegA(theInstr);
15542   UChar rB_addr  = ifieldRegB(theInstr);
15543   UInt  opc2     = ifieldOPClo10(theInstr);
15544   UChar b0       = ifieldBIT0(theInstr);
15545
15546   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
15547   IRTemp EA           = newTemp(ty);
15548   IRTemp addr_aligned = newTemp(ty);
15549   IRTemp vS           = newTemp(Ity_V128);
15550   IRTemp eb           = newTemp(Ity_I8);
15551   IRTemp idx          = newTemp(Ity_I8);
15552
15553   if (opc1 != 0x1F || b0 != 0) {
15554      vex_printf("dis_av_store(ppc)(instr)\n");
15555      return False;
15556   }
15557
15558   assign( vS, getVReg(vS_addr));
15559   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
15560
15561   switch (opc2) {
15562   case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
15563      DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
15564      assign( eb, binop(Iop_And8, mkU8(0xF),
15565                        unop(Iop_32to8,
15566                             mkNarrowTo32(ty, mkexpr(EA)) )) );
15567      assign( idx, binop(Iop_Shl8,
15568                         binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
15569                         mkU8(3)) );
15570      storeBE( mkexpr(EA),
15571               unop(Iop_32to8, unop(Iop_V128to32,
15572                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
15573      break;
15574   }
15575   case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
15576      DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
15577      assign( addr_aligned, addr_align(mkexpr(EA), 2) );
15578      assign( eb, binop(Iop_And8, mkU8(0xF),
15579                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
15580      assign( idx, binop(Iop_Shl8,
15581                         binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
15582                         mkU8(3)) );
15583      storeBE( mkexpr(addr_aligned),
15584               unop(Iop_32to16, unop(Iop_V128to32,
15585                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
15586      break;
15587   }
15588   case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
15589      DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
15590      assign( addr_aligned, addr_align(mkexpr(EA), 4) );
15591      assign( eb, binop(Iop_And8, mkU8(0xF),
15592                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
15593      assign( idx, binop(Iop_Shl8,
15594                         binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
15595                         mkU8(3)) );
15596      storeBE( mkexpr(addr_aligned),
15597               unop(Iop_V128to32,
15598                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
15599      break;
15600   }
15601
15602   case 0x0E7: // stvx (Store Vector Indexed, AV p134)
15603      DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
15604      storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
15605      break;
15606
15607   case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
15608      DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
15609      storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
15610      break;
15611
15612   default:
15613      vex_printf("dis_av_store(ppc)(opc2)\n");
15614      return False;
15615   }
15616   return True;
15617}
15618
15619/*
15620  AltiVec Arithmetic Instructions
15621*/
15622static Bool dis_av_arith ( UInt theInstr )
15623{
15624   /* VX-Form */
15625   UChar opc1     = ifieldOPC(theInstr);
15626   UChar vD_addr  = ifieldRegDS(theInstr);
15627   UChar vA_addr  = ifieldRegA(theInstr);
15628   UChar vB_addr  = ifieldRegB(theInstr);
15629   UInt  opc2     = IFIELD( theInstr, 0, 11 );
15630
15631   IRTemp vA = newTemp(Ity_V128);
15632   IRTemp vB = newTemp(Ity_V128);
15633   IRTemp z3 = newTemp(Ity_I64);
15634   IRTemp z2 = newTemp(Ity_I64);
15635   IRTemp z1 = newTemp(Ity_I64);
15636   IRTemp z0 = newTemp(Ity_I64);
15637   IRTemp aEvn, aOdd;
15638   IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
15639   IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
15640   IRTemp b3, b2, b1, b0;
15641
15642   aEvn = aOdd = IRTemp_INVALID;
15643   a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
15644   a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
15645   b3 = b2 = b1 = b0 = IRTemp_INVALID;
15646
15647   assign( vA, getVReg(vA_addr));
15648   assign( vB, getVReg(vB_addr));
15649
15650   if (opc1 != 0x4) {
15651      vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
15652      return False;
15653   }
15654
15655   switch (opc2) {
15656   /* Add */
15657   case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
15658      DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15659      /* unsigned_ov(x+y) = (y >u not(x)) */
15660      putVReg( vD_addr, binop(Iop_ShrN32x4,
15661                              binop(Iop_CmpGT32Ux4, mkexpr(vB),
15662                                    unop(Iop_NotV128, mkexpr(vA))),
15663                              mkU8(31)) );
15664      break;
15665   }
15666   case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
15667      DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15668      putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
15669      break;
15670
15671   case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
15672      DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15673      putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
15674      break;
15675
15676   case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
15677      DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15678      putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
15679      break;
15680
15681   case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
15682      DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15683      putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
15684      break;
15685
15686   case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
15687      DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15688      putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
15689      // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
15690      break;
15691
15692   case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
15693      DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15694      putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
15695      // TODO: set VSCR[SAT]
15696      break;
15697
15698   case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
15699      DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15700      putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
15701      // TODO: set VSCR[SAT]
15702      break;
15703
15704   case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
15705      DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15706      putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
15707      // TODO: set VSCR[SAT]
15708      break;
15709
15710   case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
15711      DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15712      putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
15713      // TODO: set VSCR[SAT]
15714      break;
15715
15716   case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
15717      DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15718      putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
15719      // TODO: set VSCR[SAT]
15720      break;
15721
15722
15723   /* Subtract */
15724   case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
15725      DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15726      /* unsigned_ov(x-y) = (y >u x) */
15727      putVReg( vD_addr, binop(Iop_ShrN32x4,
15728                              unop(Iop_NotV128,
15729                                   binop(Iop_CmpGT32Ux4, mkexpr(vB),
15730                                         mkexpr(vA))),
15731                              mkU8(31)) );
15732      break;
15733   }
15734   case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
15735      DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15736      putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
15737      break;
15738
15739   case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
15740      DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15741      putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
15742      break;
15743
15744   case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
15745      DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15746      putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
15747      break;
15748
15749   case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
15750      DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15751      putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
15752      break;
15753
15754   case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
15755      DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15756      putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
15757      // TODO: set VSCR[SAT]
15758      break;
15759
15760   case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
15761      DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15762      putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
15763      // TODO: set VSCR[SAT]
15764      break;
15765
15766   case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
15767      DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15768      putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
15769      // TODO: set VSCR[SAT]
15770      break;
15771
15772   case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
15773      DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15774      putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
15775      // TODO: set VSCR[SAT]
15776      break;
15777
15778   case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
15779      DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15780      putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
15781      // TODO: set VSCR[SAT]
15782      break;
15783
15784   case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
15785      DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15786      putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
15787      // TODO: set VSCR[SAT]
15788      break;
15789
15790
15791   /* Maximum */
15792   case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
15793      DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15794      putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
15795      break;
15796
15797   case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
15798      DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15799      putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
15800      break;
15801
15802   case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
15803      DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15804      putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
15805      break;
15806
15807   case 0x0C2: // vmaxud (Maximum Unsigned Double word)
15808      DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15809      putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
15810      break;
15811
15812   case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
15813      DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15814      putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
15815      break;
15816
15817   case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
15818      DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15819      putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
15820      break;
15821
15822   case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
15823      DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15824      putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
15825      break;
15826
15827   case 0x1C2: // vmaxsd (Maximum Signed Double word)
15828      DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15829      putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
15830      break;
15831
15832   /* Minimum */
15833   case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
15834      DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15835      putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
15836      break;
15837
15838   case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
15839      DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15840      putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
15841      break;
15842
15843   case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
15844      DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15845      putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
15846      break;
15847
15848   case 0x2C2: // vminud (Minimum Unsigned Double Word)
15849      DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15850      putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
15851      break;
15852
15853   case 0x302: // vminsb (Minimum Signed Byte, AV p188)
15854      DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15855      putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
15856      break;
15857
15858   case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
15859      DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15860      putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
15861      break;
15862
15863   case 0x382: // vminsw (Minimum Signed Word, AV p190)
15864      DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15865      putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
15866      break;
15867
15868   case 0x3C2: // vminsd (Minimum Signed Double Word)
15869      DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15870      putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
15871      break;
15872
15873
15874   /* Average */
15875   case 0x402: // vavgub (Average Unsigned Byte, AV p152)
15876      DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15877      putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
15878      break;
15879
15880   case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
15881      DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15882      putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
15883      break;
15884
15885   case 0x482: // vavguw (Average Unsigned Word, AV p154)
15886      DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15887      putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
15888      break;
15889
15890   case 0x502: // vavgsb (Average Signed Byte, AV p149)
15891      DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15892      putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
15893      break;
15894
15895   case 0x542: // vavgsh (Average Signed Half Word, AV p150)
15896      DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15897      putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
15898      break;
15899
15900   case 0x582: // vavgsw (Average Signed Word, AV p151)
15901      DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15902      putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
15903      break;
15904
15905
15906   /* Multiply */
15907   case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
15908      DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15909      putVReg( vD_addr,
15910               binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
15911      break;
15912
15913   case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
15914      DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15915      putVReg( vD_addr,
15916               binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
15917      break;
15918
15919   case 0x088: // vmulouw (Multiply Odd Unsigned Word)
15920      DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15921      putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
15922      break;
15923
15924   case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
15925      DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15926      putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
15927      break;
15928
15929   case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
15930      DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15931      putVReg( vD_addr,
15932               binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
15933      break;
15934
15935   case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
15936      DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15937      putVReg( vD_addr,
15938               binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
15939      break;
15940
15941   case 0x188: // vmulosw (Multiply Odd Signed Word)
15942      DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15943      putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
15944      break;
15945
15946   case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
15947      DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15948      putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
15949      break;
15950
15951   case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
15952      DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15953      putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
15954      break;
15955
15956   case 0x288: // vmuleuw (Multiply Even Unsigned Word)
15957      DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15958      putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
15959      break;
15960
15961   case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
15962      DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15963      putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
15964      break;
15965
15966   case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
15967      DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15968      putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
15969      break;
15970
15971   case 0x388: // vmulesw (Multiply Even Signed Word)
15972      DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15973      putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
15974      break;
15975
15976   /* Sum Across Partial */
15977   case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
15978      IRTemp aEE, aEO, aOE, aOO;
15979      aEE = aEO = aOE = aOO = IRTemp_INVALID;
15980      DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
15981
15982      /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
15983      expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
15984      expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
15985      expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
15986
15987      /* break V128 to 4xI32's, zero-extending to I64's */
15988      breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
15989      breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
15990      breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
15991      breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
15992      breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
15993
15994      /* add lanes */
15995      assign( z3, binop(Iop_Add64, mkexpr(b3),
15996                     binop(Iop_Add64,
15997                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
15998                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
15999      assign( z2, binop(Iop_Add64, mkexpr(b2),
16000                     binop(Iop_Add64,
16001                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
16002                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
16003      assign( z1, binop(Iop_Add64, mkexpr(b1),
16004                     binop(Iop_Add64,
16005                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
16006                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
16007      assign( z0, binop(Iop_Add64, mkexpr(b0),
16008                     binop(Iop_Add64,
16009                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16010                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16011
16012      /* saturate-narrow to 32bit, and combine to V128 */
16013      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
16014                                         mkexpr(z1), mkexpr(z0)) );
16015      break;
16016   }
16017   case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
16018      IRTemp aEE, aEO, aOE, aOO;
16019      aEE = aEO = aOE = aOO = IRTemp_INVALID;
16020      DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16021
16022      /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
16023      expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
16024      expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
16025      expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
16026
16027      /* break V128 to 4xI32's, sign-extending to I64's */
16028      breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
16029      breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
16030      breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
16031      breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
16032      breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
16033
16034      /* add lanes */
16035      assign( z3, binop(Iop_Add64, mkexpr(b3),
16036                     binop(Iop_Add64,
16037                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
16038                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
16039      assign( z2, binop(Iop_Add64, mkexpr(b2),
16040                     binop(Iop_Add64,
16041                        binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
16042                        binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
16043      assign( z1, binop(Iop_Add64, mkexpr(b1),
16044                     binop(Iop_Add64,
16045                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
16046                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
16047      assign( z0, binop(Iop_Add64, mkexpr(b0),
16048                     binop(Iop_Add64,
16049                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16050                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16051
16052      /* saturate-narrow to 32bit, and combine to V128 */
16053      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
16054                                         mkexpr(z1), mkexpr(z0)) );
16055      break;
16056   }
16057   case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
16058      DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16059
16060      /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
16061      expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
16062
16063      /* break V128 to 4xI32's, sign-extending to I64's */
16064      breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
16065      breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
16066      breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
16067
16068      /* add lanes */
16069      assign( z3, binop(Iop_Add64, mkexpr(b3),
16070                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
16071      assign( z2, binop(Iop_Add64, mkexpr(b2),
16072                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
16073      assign( z1, binop(Iop_Add64, mkexpr(b1),
16074                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
16075      assign( z0, binop(Iop_Add64, mkexpr(b0),
16076                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
16077
16078      /* saturate-narrow to 32bit, and combine to V128 */
16079      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
16080                                         mkexpr(z1), mkexpr(z0)) );
16081      break;
16082   }
16083   case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
16084      DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16085
16086      /* break V128 to 4xI32's, sign-extending to I64's */
16087      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
16088      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
16089
16090      /* add lanes */
16091      assign( z2, binop(Iop_Add64, mkexpr(b2),
16092                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
16093      assign( z0, binop(Iop_Add64, mkexpr(b0),
16094                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
16095
16096      /* saturate-narrow to 32bit, and combine to V128 */
16097      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
16098                                         mkU64(0), mkexpr(z0)) );
16099      break;
16100   }
16101   case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
16102      DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16103
16104      /* break V128 to 4xI32's, sign-extending to I64's */
16105      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
16106      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
16107
16108      /* add lanes */
16109      assign( z0, binop(Iop_Add64, mkexpr(b0),
16110                     binop(Iop_Add64,
16111                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16112                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16113
16114      /* saturate-narrow to 32bit, and combine to V128 */
16115      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
16116                                         mkU64(0), mkexpr(z0)) );
16117      break;
16118   }
16119   default:
16120      vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
16121      return False;
16122   }
16123   return True;
16124}
16125
16126/*
16127  AltiVec Logic Instructions
16128*/
16129static Bool dis_av_logic ( UInt theInstr )
16130{
16131   /* VX-Form */
16132   UChar opc1    = ifieldOPC(theInstr);
16133   UChar vD_addr = ifieldRegDS(theInstr);
16134   UChar vA_addr = ifieldRegA(theInstr);
16135   UChar vB_addr = ifieldRegB(theInstr);
16136   UInt  opc2    = IFIELD( theInstr, 0, 11 );
16137
16138   IRTemp vA = newTemp(Ity_V128);
16139   IRTemp vB = newTemp(Ity_V128);
16140   assign( vA, getVReg(vA_addr));
16141   assign( vB, getVReg(vB_addr));
16142
16143   if (opc1 != 0x4) {
16144      vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
16145      return False;
16146   }
16147
16148   switch (opc2) {
16149   case 0x404: // vand (And, AV p147)
16150      DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16151      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
16152      break;
16153
16154   case 0x444: // vandc (And, AV p148)
16155      DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16156      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
16157                              unop(Iop_NotV128, mkexpr(vB))) );
16158      break;
16159
16160   case 0x484: // vor (Or, AV p217)
16161      DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16162      putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
16163      break;
16164
16165   case 0x4C4: // vxor (Xor, AV p282)
16166      DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16167      putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
16168      break;
16169
16170   case 0x504: // vnor (Nor, AV p216)
16171      DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16172      putVReg( vD_addr,
16173         unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
16174      break;
16175
16176   case 0x544: // vorc (vA Or'd with complement of vb)
16177      DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16178      putVReg( vD_addr, binop( Iop_OrV128,
16179                               mkexpr( vA ),
16180                               unop( Iop_NotV128, mkexpr( vB ) ) ) );
16181      break;
16182
16183   case 0x584: // vnand (Nand)
16184      DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16185      putVReg( vD_addr, unop( Iop_NotV128,
16186                              binop(Iop_AndV128, mkexpr( vA ),
16187                              mkexpr( vB ) ) ) );
16188      break;
16189
16190   case 0x684: // veqv (complemented XOr)
16191      DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16192      putVReg( vD_addr, unop( Iop_NotV128,
16193                              binop( Iop_XorV128, mkexpr( vA ),
16194                              mkexpr( vB ) ) ) );
16195      break;
16196
16197   default:
16198      vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
16199      return False;
16200   }
16201   return True;
16202}
16203
16204/*
16205  AltiVec Compare Instructions
16206*/
16207static Bool dis_av_cmp ( UInt theInstr )
16208{
16209   /* VXR-Form */
16210   UChar opc1     = ifieldOPC(theInstr);
16211   UChar vD_addr  = ifieldRegDS(theInstr);
16212   UChar vA_addr  = ifieldRegA(theInstr);
16213   UChar vB_addr  = ifieldRegB(theInstr);
16214   UChar flag_rC  = ifieldBIT10(theInstr);
16215   UInt  opc2     = IFIELD( theInstr, 0, 10 );
16216
16217   IRTemp vA = newTemp(Ity_V128);
16218   IRTemp vB = newTemp(Ity_V128);
16219   IRTemp vD = newTemp(Ity_V128);
16220   assign( vA, getVReg(vA_addr));
16221   assign( vB, getVReg(vB_addr));
16222
16223   if (opc1 != 0x4) {
16224      vex_printf("dis_av_cmp(ppc)(instr)\n");
16225      return False;
16226   }
16227
16228   switch (opc2) {
16229   case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
16230      DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16231                                      vD_addr, vA_addr, vB_addr);
16232      assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
16233      break;
16234
16235   case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
16236      DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16237                                      vD_addr, vA_addr, vB_addr);
16238      assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
16239      break;
16240
16241   case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
16242      DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16243                                      vD_addr, vA_addr, vB_addr);
16244      assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
16245      break;
16246
16247   case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
16248      DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16249                                      vD_addr, vA_addr, vB_addr);
16250      assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
16251      break;
16252
16253   case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
16254      DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16255                                      vD_addr, vA_addr, vB_addr);
16256      assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
16257      break;
16258
16259   case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
16260      DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16261                                      vD_addr, vA_addr, vB_addr);
16262      assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
16263      break;
16264
16265   case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
16266      DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16267                                       vD_addr, vA_addr, vB_addr);
16268      assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
16269      break;
16270
16271   case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
16272      DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16273                                      vD_addr, vA_addr, vB_addr);
16274      assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
16275      break;
16276
16277   case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
16278      DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16279                                       vD_addr, vA_addr, vB_addr);
16280      assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
16281      break;
16282
16283   case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
16284      DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16285                                      vD_addr, vA_addr, vB_addr);
16286      assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
16287      break;
16288
16289   case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
16290      DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16291                                      vD_addr, vA_addr, vB_addr);
16292      assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
16293      break;
16294
16295   case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
16296      DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16297                                      vD_addr, vA_addr, vB_addr);
16298      assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
16299      break;
16300
16301   default:
16302      vex_printf("dis_av_cmp(ppc)(opc2)\n");
16303      return False;
16304   }
16305
16306   putVReg( vD_addr, mkexpr(vD) );
16307
16308   if (flag_rC) {
16309      set_AV_CR6( mkexpr(vD), True );
16310   }
16311   return True;
16312}
16313
16314/*
16315  AltiVec Multiply-Sum Instructions
16316*/
16317static Bool dis_av_multarith ( UInt theInstr )
16318{
16319   /* VA-Form */
16320   UChar opc1     = ifieldOPC(theInstr);
16321   UChar vD_addr  = ifieldRegDS(theInstr);
16322   UChar vA_addr  = ifieldRegA(theInstr);
16323   UChar vB_addr  = ifieldRegB(theInstr);
16324   UChar vC_addr  = ifieldRegC(theInstr);
16325   UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
16326
16327   IRTemp vA    = newTemp(Ity_V128);
16328   IRTemp vB    = newTemp(Ity_V128);
16329   IRTemp vC    = newTemp(Ity_V128);
16330   IRTemp zeros = newTemp(Ity_V128);
16331   IRTemp aLo   = newTemp(Ity_V128);
16332   IRTemp bLo   = newTemp(Ity_V128);
16333   IRTemp cLo   = newTemp(Ity_V128);
16334   IRTemp zLo   = newTemp(Ity_V128);
16335   IRTemp aHi   = newTemp(Ity_V128);
16336   IRTemp bHi   = newTemp(Ity_V128);
16337   IRTemp cHi   = newTemp(Ity_V128);
16338   IRTemp zHi   = newTemp(Ity_V128);
16339   IRTemp abEvn = newTemp(Ity_V128);
16340   IRTemp abOdd = newTemp(Ity_V128);
16341   IRTemp z3    = newTemp(Ity_I64);
16342   IRTemp z2    = newTemp(Ity_I64);
16343   IRTemp z1    = newTemp(Ity_I64);
16344   IRTemp z0    = newTemp(Ity_I64);
16345   IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
16346   IRTemp c3, c2, c1, c0;
16347
16348   ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
16349   c3 = c2 = c1 = c0 = IRTemp_INVALID;
16350
16351   assign( vA, getVReg(vA_addr));
16352   assign( vB, getVReg(vB_addr));
16353   assign( vC, getVReg(vC_addr));
16354   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
16355
16356   if (opc1 != 0x4) {
16357      vex_printf("dis_av_multarith(ppc)(instr)\n");
16358      return False;
16359   }
16360
16361   switch (opc2) {
16362   /* Multiply-Add */
16363   case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
16364      IRTemp cSigns = newTemp(Ity_V128);
16365      DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
16366          vD_addr, vA_addr, vB_addr, vC_addr);
16367      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
16368      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16369      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16370      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
16371      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16372      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16373      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
16374
16375      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
16376                         binop(Iop_SarN32x4,
16377                               binop(Iop_MullEven16Sx8,
16378                                     mkexpr(aLo), mkexpr(bLo)),
16379                               mkU8(15))) );
16380
16381      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
16382                         binop(Iop_SarN32x4,
16383                               binop(Iop_MullEven16Sx8,
16384                                     mkexpr(aHi), mkexpr(bHi)),
16385                               mkU8(15))) );
16386
16387      putVReg( vD_addr,
16388               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
16389      break;
16390   }
16391   case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
16392      IRTemp zKonst = newTemp(Ity_V128);
16393      IRTemp cSigns = newTemp(Ity_V128);
16394      DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
16395          vD_addr, vA_addr, vB_addr, vC_addr);
16396      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
16397      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16398      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16399      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
16400      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16401      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16402      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
16403
16404      /* shifting our const avoids store/load version of Dup */
16405      assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
16406                            mkU8(14)) );
16407
16408      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
16409                         binop(Iop_SarN32x4,
16410                               binop(Iop_Add32x4, mkexpr(zKonst),
16411                                     binop(Iop_MullEven16Sx8,
16412                                           mkexpr(aLo), mkexpr(bLo))),
16413                               mkU8(15))) );
16414
16415      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
16416                         binop(Iop_SarN32x4,
16417                               binop(Iop_Add32x4, mkexpr(zKonst),
16418                                     binop(Iop_MullEven16Sx8,
16419                                           mkexpr(aHi), mkexpr(bHi))),
16420                               mkU8(15))) );
16421
16422      putVReg( vD_addr,
16423               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
16424      break;
16425   }
16426   case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
16427      DIP("vmladduhm v%d,v%d,v%d,v%d\n",
16428          vD_addr, vA_addr, vB_addr, vC_addr);
16429      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16430      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16431      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
16432      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16433      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16434      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
16435      assign(zLo, binop(Iop_Add32x4,
16436                     binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
16437                     mkexpr(cLo)) );
16438      assign(zHi, binop(Iop_Add32x4,
16439                     binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
16440                     mkexpr(cHi)));
16441      putVReg( vD_addr,
16442               binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
16443      break;
16444   }
16445
16446
16447   /* Multiply-Sum */
16448   case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
16449      IRTemp abEE, abEO, abOE, abOO;
16450      abEE = abEO = abOE = abOO = IRTemp_INVALID;
16451      DIP("vmsumubm v%d,v%d,v%d,v%d\n",
16452          vD_addr, vA_addr, vB_addr, vC_addr);
16453
16454      /* multiply vA,vB (unsigned, widening) */
16455      assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
16456      assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
16457
16458      /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
16459      expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
16460      expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
16461
16462      putVReg( vD_addr,
16463         binop(Iop_Add32x4, mkexpr(vC),
16464               binop(Iop_Add32x4,
16465                     binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
16466                     binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
16467      break;
16468   }
16469   case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
16470      IRTemp aEvn, aOdd, bEvn, bOdd;
16471      IRTemp abEE = newTemp(Ity_V128);
16472      IRTemp abEO = newTemp(Ity_V128);
16473      IRTemp abOE = newTemp(Ity_V128);
16474      IRTemp abOO = newTemp(Ity_V128);
16475      aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
16476      DIP("vmsummbm v%d,v%d,v%d,v%d\n",
16477          vD_addr, vA_addr, vB_addr, vC_addr);
16478
16479      /* sign-extend vA, zero-extend vB, for mixed-sign multiply
16480         (separating out adjacent lanes to different vectors) */
16481      expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
16482      expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
16483
16484      /* multiply vA, vB, again separating adjacent lanes */
16485      assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
16486      assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
16487      assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
16488      assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
16489
16490      /* add results together, + vC */
16491      putVReg( vD_addr,
16492         binop(Iop_QAdd32Sx4, mkexpr(vC),
16493               binop(Iop_QAdd32Sx4,
16494                     binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
16495                     binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
16496      break;
16497   }
16498   case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
16499      DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
16500          vD_addr, vA_addr, vB_addr, vC_addr);
16501      assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
16502      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
16503      putVReg( vD_addr,
16504         binop(Iop_Add32x4, mkexpr(vC),
16505               binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
16506      break;
16507   }
16508   case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
16509      DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
16510          vD_addr, vA_addr, vB_addr, vC_addr);
16511      /* widening multiply, separating lanes */
16512      assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
16513      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
16514
16515      /* break V128 to 4xI32's, zero-extending to I64's */
16516      breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
16517      breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
16518      breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
16519
16520      /* add lanes */
16521      assign( z3, binop(Iop_Add64, mkexpr(c3),
16522                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
16523      assign( z2, binop(Iop_Add64, mkexpr(c2),
16524                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
16525      assign( z1, binop(Iop_Add64, mkexpr(c1),
16526                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
16527      assign( z0, binop(Iop_Add64, mkexpr(c0),
16528                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
16529
16530      /* saturate-narrow to 32bit, and combine to V128 */
16531      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
16532                                         mkexpr(z1), mkexpr(z0)) );
16533
16534      break;
16535   }
16536   case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
16537      DIP("vmsumshm v%d,v%d,v%d,v%d\n",
16538          vD_addr, vA_addr, vB_addr, vC_addr);
16539      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
16540      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
16541      putVReg( vD_addr,
16542         binop(Iop_Add32x4, mkexpr(vC),
16543               binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
16544      break;
16545   }
16546   case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
16547      DIP("vmsumshs v%d,v%d,v%d,v%d\n",
16548          vD_addr, vA_addr, vB_addr, vC_addr);
16549      /* widening multiply, separating lanes */
16550      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
16551      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
16552
16553      /* break V128 to 4xI32's, sign-extending to I64's */
16554      breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
16555      breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
16556      breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
16557
16558      /* add lanes */
16559      assign( z3, binop(Iop_Add64, mkexpr(c3),
16560                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
16561      assign( z2, binop(Iop_Add64, mkexpr(c2),
16562                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
16563      assign( z1, binop(Iop_Add64, mkexpr(c1),
16564                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
16565      assign( z0, binop(Iop_Add64, mkexpr(c0),
16566                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
16567
16568      /* saturate-narrow to 32bit, and combine to V128 */
16569      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
16570                                         mkexpr(z1), mkexpr(z0)) );
16571      break;
16572   }
16573   default:
16574      vex_printf("dis_av_multarith(ppc)(opc2)\n");
16575      return False;
16576   }
16577   return True;
16578}
16579
16580/*
16581  AltiVec Polynomial Multiply-Sum Instructions
16582*/
16583static Bool dis_av_polymultarith ( UInt theInstr )
16584{
16585   /* VA-Form */
16586   UChar opc1     = ifieldOPC(theInstr);
16587   UChar vD_addr  = ifieldRegDS(theInstr);
16588   UChar vA_addr  = ifieldRegA(theInstr);
16589   UChar vB_addr  = ifieldRegB(theInstr);
16590   UChar vC_addr  = ifieldRegC(theInstr);
16591   UInt  opc2     = IFIELD(theInstr, 0, 11);
16592   IRTemp vA    = newTemp(Ity_V128);
16593   IRTemp vB    = newTemp(Ity_V128);
16594   IRTemp vC    = newTemp(Ity_V128);
16595
16596   assign( vA, getVReg(vA_addr));
16597   assign( vB, getVReg(vB_addr));
16598   assign( vC, getVReg(vC_addr));
16599
16600   if (opc1 != 0x4) {
16601      vex_printf("dis_av_polymultarith(ppc)(instr)\n");
16602      return False;
16603   }
16604
16605   switch (opc2) {
16606      /* Polynomial Multiply-Add */
16607      case 0x408:  // vpmsumb   Vector Polynomial Multipy-sum Byte
16608         DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16609         putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
16610                                 mkexpr(vA), mkexpr(vB)) );
16611         break;
16612      case 0x448:  // vpmsumd   Vector Polynomial Multipy-sum Double Word
16613         DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16614         putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
16615                                 mkexpr(vA), mkexpr(vB)) );
16616         break;
16617      case 0x488:  // vpmsumw   Vector Polynomial Multipy-sum Word
16618         DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16619         putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
16620                                 mkexpr(vA), mkexpr(vB)) );
16621         break;
16622      case 0x4C8:  // vpmsumh   Vector Polynomial Multipy-sum Half Word
16623         DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16624         putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
16625                                 mkexpr(vA), mkexpr(vB)) );
16626         break;
16627      default:
16628         vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
16629         return False;
16630   }
16631   return True;
16632}
16633
16634/*
16635  AltiVec Shift/Rotate Instructions
16636*/
16637static Bool dis_av_shift ( UInt theInstr )
16638{
16639   /* VX-Form */
16640   UChar opc1    = ifieldOPC(theInstr);
16641   UChar vD_addr = ifieldRegDS(theInstr);
16642   UChar vA_addr = ifieldRegA(theInstr);
16643   UChar vB_addr = ifieldRegB(theInstr);
16644   UInt  opc2    = IFIELD( theInstr, 0, 11 );
16645
16646   IRTemp vA = newTemp(Ity_V128);
16647   IRTemp vB = newTemp(Ity_V128);
16648   assign( vA, getVReg(vA_addr));
16649   assign( vB, getVReg(vB_addr));
16650
16651   if (opc1 != 0x4){
16652      vex_printf("dis_av_shift(ppc)(instr)\n");
16653      return False;
16654   }
16655
16656   switch (opc2) {
16657   /* Rotate */
16658   case 0x004: // vrlb (Rotate Left Integer B, AV p234)
16659      DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16660      putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
16661      break;
16662
16663   case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
16664      DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16665      putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
16666      break;
16667
16668   case 0x084: // vrlw (Rotate Left Integer W, AV p236)
16669      DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16670      putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
16671      break;
16672
16673   case 0x0C4: // vrld (Rotate Left Integer Double Word)
16674      DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16675      putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
16676      break;
16677
16678
16679   /* Shift Left */
16680   case 0x104: // vslb (Shift Left Integer B, AV p240)
16681      DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16682      putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
16683      break;
16684
16685   case 0x144: // vslh (Shift Left Integer HW, AV p242)
16686      DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16687      putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
16688      break;
16689
16690   case 0x184: // vslw (Shift Left Integer W, AV p244)
16691      DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16692      putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
16693      break;
16694
16695   case 0x5C4: // vsld (Shift Left Integer Double Word)
16696      DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16697      putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
16698      break;
16699
16700   case 0x1C4: { // vsl (Shift Left, AV p239)
16701      IRTemp sh = newTemp(Ity_I8);
16702      DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16703      assign( sh, binop(Iop_And8, mkU8(0x7),
16704                        unop(Iop_32to8,
16705                             unop(Iop_V128to32, mkexpr(vB)))) );
16706      putVReg( vD_addr,
16707               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
16708      break;
16709   }
16710   case 0x40C: { // vslo (Shift Left by Octet, AV p243)
16711      IRTemp sh = newTemp(Ity_I8);
16712      DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16713      assign( sh, binop(Iop_And8, mkU8(0x78),
16714                        unop(Iop_32to8,
16715                             unop(Iop_V128to32, mkexpr(vB)))) );
16716      putVReg( vD_addr,
16717               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
16718      break;
16719   }
16720
16721
16722   /* Shift Right */
16723   case 0x204: // vsrb (Shift Right B, AV p256)
16724      DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16725      putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
16726      break;
16727
16728   case 0x244: // vsrh (Shift Right HW, AV p257)
16729      DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16730      putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
16731      break;
16732
16733   case 0x284: // vsrw (Shift Right W, AV p259)
16734      DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16735      putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
16736      break;
16737
16738   case 0x2C4: { // vsr (Shift Right, AV p251)
16739      IRTemp sh = newTemp(Ity_I8);
16740      DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16741      assign( sh, binop(Iop_And8, mkU8(0x7),
16742                        unop(Iop_32to8,
16743                             unop(Iop_V128to32, mkexpr(vB)))) );
16744      putVReg( vD_addr,
16745               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
16746      break;
16747   }
16748   case 0x304: // vsrab (Shift Right Alg B, AV p253)
16749      DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16750      putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
16751      break;
16752
16753   case 0x344: // vsrah (Shift Right Alg HW, AV p254)
16754      DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16755      putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
16756      break;
16757
16758   case 0x384: // vsraw (Shift Right Alg W, AV p255)
16759      DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16760      putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
16761      break;
16762
16763   case 0x3C4: // vsrad (Shift Right Alg Double Word)
16764      DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16765      putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
16766      break;
16767
16768   case 0x44C: { // vsro (Shift Right by Octet, AV p258)
16769      IRTemp sh = newTemp(Ity_I8);
16770      DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16771      assign( sh, binop(Iop_And8, mkU8(0x78),
16772                        unop(Iop_32to8,
16773                             unop(Iop_V128to32, mkexpr(vB)))) );
16774      putVReg( vD_addr,
16775               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
16776      break;
16777   }
16778
16779   case 0x6C4: // vsrd (Shift Right Double Word)
16780      DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16781      putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
16782      break;
16783
16784
16785   default:
16786      vex_printf("dis_av_shift(ppc)(opc2)\n");
16787      return False;
16788   }
16789   return True;
16790}
16791
16792/*
16793  AltiVec Permute Instructions
16794*/
16795static Bool dis_av_permute ( UInt theInstr )
16796{
16797   /* VA-Form, VX-Form */
16798   UChar opc1      = ifieldOPC(theInstr);
16799   UChar vD_addr   = ifieldRegDS(theInstr);
16800   UChar vA_addr   = ifieldRegA(theInstr);
16801   UChar UIMM_5    = vA_addr;
16802   UChar vB_addr   = ifieldRegB(theInstr);
16803   UChar vC_addr   = ifieldRegC(theInstr);
16804   UChar b10       = ifieldBIT10(theInstr);
16805   UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
16806   UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
16807
16808   UChar SIMM_8 = extend_s_5to8(UIMM_5);
16809
16810   IRTemp vA = newTemp(Ity_V128);
16811   IRTemp vB = newTemp(Ity_V128);
16812   IRTemp vC = newTemp(Ity_V128);
16813   assign( vA, getVReg(vA_addr));
16814   assign( vB, getVReg(vB_addr));
16815   assign( vC, getVReg(vC_addr));
16816
16817   if (opc1 != 0x4) {
16818      vex_printf("dis_av_permute(ppc)(instr)\n");
16819      return False;
16820   }
16821
16822   switch (opc2) {
16823   case 0x2A: // vsel (Conditional Select, AV p238)
16824      DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
16825      /* vD = (vA & ~vC) | (vB & vC) */
16826      putVReg( vD_addr, binop(Iop_OrV128,
16827         binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
16828         binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
16829      return True;
16830
16831   case 0x2B: { // vperm (Permute, AV p218)
16832      /* limited to two args for IR, so have to play games... */
16833      IRTemp a_perm  = newTemp(Ity_V128);
16834      IRTemp b_perm  = newTemp(Ity_V128);
16835      IRTemp mask    = newTemp(Ity_V128);
16836      IRTemp vC_andF = newTemp(Ity_V128);
16837      DIP("vperm v%d,v%d,v%d,v%d\n",
16838          vD_addr, vA_addr, vB_addr, vC_addr);
16839      /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
16840         IR specifies, and also to hide irrelevant bits from
16841         memcheck */
16842      assign( vC_andF,
16843              binop(Iop_AndV128, mkexpr(vC),
16844                                 unop(Iop_Dup8x16, mkU8(0xF))) );
16845      assign( a_perm,
16846              binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
16847      assign( b_perm,
16848              binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
16849      // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
16850      assign( mask, binop(Iop_SarN8x16,
16851                          binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
16852                          mkU8(7)) );
16853      // dst = (a & ~mask) | (b & mask)
16854      putVReg( vD_addr, binop(Iop_OrV128,
16855                              binop(Iop_AndV128, mkexpr(a_perm),
16856                                    unop(Iop_NotV128, mkexpr(mask))),
16857                              binop(Iop_AndV128, mkexpr(b_perm),
16858                                    mkexpr(mask))) );
16859      return True;
16860   }
16861   case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
16862      if (b10 != 0) {
16863         vex_printf("dis_av_permute(ppc)(vsldoi)\n");
16864         return False;
16865      }
16866      DIP("vsldoi v%d,v%d,v%d,%d\n",
16867          vD_addr, vA_addr, vB_addr, SHB_uimm4);
16868      if (SHB_uimm4 == 0)
16869         putVReg( vD_addr, mkexpr(vA) );
16870      else
16871         putVReg( vD_addr,
16872            binop(Iop_OrV128,
16873                  binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
16874                  binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
16875      return True;
16876   case 0x2D: {  // vpermxor (Vector Permute and Exclusive-OR)
16877      IRTemp a_perm  = newTemp(Ity_V128);
16878      IRTemp b_perm  = newTemp(Ity_V128);
16879      IRTemp vrc_a   = newTemp(Ity_V128);
16880      IRTemp vrc_b   = newTemp(Ity_V128);
16881
16882      /* IBM index  is 0:7, Change index value to index 7:0 */
16883      assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
16884                            unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
16885      assign( vrc_a, binop( Iop_ShrV128,
16886                            binop( Iop_AndV128, mkexpr( vC ),
16887                                   unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
16888                            mkU8 ( 4 ) ) );
16889      assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
16890      assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
16891      putVReg( vD_addr, binop( Iop_XorV128,
16892                               mkexpr( a_perm ), mkexpr( b_perm) ) );
16893      return True;
16894   }
16895   default:
16896     break; // Fall through...
16897   }
16898
16899   opc2 = IFIELD( theInstr, 0, 11 );
16900   switch (opc2) {
16901
16902   /* Merge */
16903   case 0x00C: // vmrghb (Merge High B, AV p195)
16904      DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16905      putVReg( vD_addr,
16906               binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
16907      break;
16908
16909   case 0x04C: // vmrghh (Merge High HW, AV p196)
16910      DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16911      putVReg( vD_addr,
16912               binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
16913      break;
16914
16915   case 0x08C: // vmrghw (Merge High W, AV p197)
16916      DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16917      putVReg( vD_addr,
16918               binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
16919      break;
16920
16921   case 0x10C: // vmrglb (Merge Low B, AV p198)
16922      DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16923      putVReg( vD_addr,
16924               binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
16925      break;
16926
16927   case 0x14C: // vmrglh (Merge Low HW, AV p199)
16928      DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16929      putVReg( vD_addr,
16930               binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
16931      break;
16932
16933   case 0x18C: // vmrglw (Merge Low W, AV p200)
16934      DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16935      putVReg( vD_addr,
16936               binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
16937      break;
16938
16939
16940   /* Splat */
16941   case 0x20C: { // vspltb (Splat Byte, AV p245)
16942      /* vD = Dup8x16( vB[UIMM_5] ) */
16943      UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
16944      DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
16945      putVReg( vD_addr, unop(Iop_Dup8x16,
16946           unop(Iop_32to8, unop(Iop_V128to32,
16947                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
16948      break;
16949   }
16950   case 0x24C: { // vsplth (Splat Half Word, AV p246)
16951      UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
16952      DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
16953      putVReg( vD_addr, unop(Iop_Dup16x8,
16954           unop(Iop_32to16, unop(Iop_V128to32,
16955                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
16956      break;
16957   }
16958   case 0x28C: { // vspltw (Splat Word, AV p250)
16959      /* vD = Dup32x4( vB[UIMM_5] ) */
16960      UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
16961      DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
16962      putVReg( vD_addr, unop(Iop_Dup32x4,
16963         unop(Iop_V128to32,
16964              binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
16965      break;
16966   }
16967   case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
16968      DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
16969      putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
16970      break;
16971
16972   case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
16973      DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
16974      putVReg( vD_addr,
16975               unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
16976      break;
16977
16978   case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
16979      DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
16980      putVReg( vD_addr,
16981               unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
16982      break;
16983
16984   case 0x68C: // vmrgow (Merge Odd Word)
16985     DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16986      /*   VD[0] <- VA[1]
16987           VD[1] <- VB[1]
16988           VD[2] <- VA[3]
16989           VD[3] <- VB[3]
16990      */
16991      putVReg( vD_addr,
16992               binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
16993      break;
16994
16995   case 0x78C: // vmrgew (Merge Even Word)
16996      DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16997      /*   VD[0] <- VA[0]
16998           VD[1] <- VB[0]
16999           VD[2] <- VA[2]
17000           VD[3] <- VB[2]
17001      */
17002      putVReg( vD_addr,
17003               binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
17004      break;
17005
17006   default:
17007      vex_printf("dis_av_permute(ppc)(opc2)\n");
17008      return False;
17009   }
17010   return True;
17011}
17012
17013/*
17014  AltiVec Pack/Unpack Instructions
17015*/
17016static Bool dis_av_pack ( UInt theInstr )
17017{
17018   /* VX-Form */
17019   UChar opc1     = ifieldOPC(theInstr);
17020   UChar vD_addr  = ifieldRegDS(theInstr);
17021   UChar vA_addr  = ifieldRegA(theInstr);
17022   UChar vB_addr  = ifieldRegB(theInstr);
17023   UInt  opc2     = IFIELD( theInstr, 0, 11 );
17024
17025   IRTemp signs = IRTemp_INVALID;
17026   IRTemp zeros = IRTemp_INVALID;
17027   IRTemp vA    = newTemp(Ity_V128);
17028   IRTemp vB    = newTemp(Ity_V128);
17029   assign( vA, getVReg(vA_addr));
17030   assign( vB, getVReg(vB_addr));
17031
17032   if (opc1 != 0x4) {
17033      vex_printf("dis_av_pack(ppc)(instr)\n");
17034      return False;
17035   }
17036   switch (opc2) {
17037   /* Packing */
17038   case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
17039      DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17040      putVReg( vD_addr,
17041               binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
17042      return True;
17043
17044   case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
17045      DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17046      putVReg( vD_addr,
17047               binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
17048      return True;
17049
17050   case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
17051      DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17052      putVReg( vD_addr,
17053               binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
17054      // TODO: set VSCR[SAT]
17055      return True;
17056
17057   case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
17058      DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17059      putVReg( vD_addr,
17060               binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
17061      // TODO: set VSCR[SAT]
17062      return True;
17063
17064   case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
17065      // This insn does a signed->unsigned saturating conversion.
17066      // Conversion done here, then uses unsigned->unsigned vpk insn:
17067      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
17068      IRTemp vA_tmp = newTemp(Ity_V128);
17069      IRTemp vB_tmp = newTemp(Ity_V128);
17070      DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17071      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17072                            unop(Iop_NotV128,
17073                                 binop(Iop_SarN16x8,
17074                                       mkexpr(vA), mkU8(15)))) );
17075      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17076                            unop(Iop_NotV128,
17077                                 binop(Iop_SarN16x8,
17078                                       mkexpr(vB), mkU8(15)))) );
17079      putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
17080                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17081      // TODO: set VSCR[SAT]
17082      return True;
17083   }
17084   case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
17085      // This insn does a signed->unsigned saturating conversion.
17086      // Conversion done here, then uses unsigned->unsigned vpk insn:
17087      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
17088      IRTemp vA_tmp = newTemp(Ity_V128);
17089      IRTemp vB_tmp = newTemp(Ity_V128);
17090      DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17091      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17092                            unop(Iop_NotV128,
17093                                 binop(Iop_SarN32x4,
17094                                       mkexpr(vA), mkU8(31)))) );
17095      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17096                            unop(Iop_NotV128,
17097                                 binop(Iop_SarN32x4,
17098                                       mkexpr(vB), mkU8(31)))) );
17099      putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
17100                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17101      // TODO: set VSCR[SAT]
17102      return True;
17103   }
17104   case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
17105      DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17106      putVReg( vD_addr,
17107               binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
17108      // TODO: set VSCR[SAT]
17109      return True;
17110
17111   case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
17112      DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17113      putVReg( vD_addr,
17114               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
17115      // TODO: set VSCR[SAT]
17116      return True;
17117
17118   case 0x30E: { // vpkpx (Pack Pixel, AV p219)
17119      /* CAB: Worth a new primop? */
17120      /* Using shifts to compact pixel elements, then packing them */
17121      IRTemp a1 = newTemp(Ity_V128);
17122      IRTemp a2 = newTemp(Ity_V128);
17123      IRTemp a3 = newTemp(Ity_V128);
17124      IRTemp a_tmp = newTemp(Ity_V128);
17125      IRTemp b1 = newTemp(Ity_V128);
17126      IRTemp b2 = newTemp(Ity_V128);
17127      IRTemp b3 = newTemp(Ity_V128);
17128      IRTemp b_tmp = newTemp(Ity_V128);
17129      DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17130      assign( a1, binop(Iop_ShlN16x8,
17131                        binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
17132                        mkU8(10)) );
17133      assign( a2, binop(Iop_ShlN16x8,
17134                        binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
17135                        mkU8(5)) );
17136      assign( a3,  binop(Iop_ShrN16x8,
17137                         binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
17138                         mkU8(11)) );
17139      assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
17140                           binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
17141
17142      assign( b1, binop(Iop_ShlN16x8,
17143                        binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
17144                        mkU8(10)) );
17145      assign( b2, binop(Iop_ShlN16x8,
17146                        binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
17147                        mkU8(5)) );
17148      assign( b3,  binop(Iop_ShrN16x8,
17149                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
17150                         mkU8(11)) );
17151      assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
17152                           binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
17153
17154      putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
17155                              mkexpr(a_tmp), mkexpr(b_tmp)) );
17156      return True;
17157   }
17158
17159   case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
17160      DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17161      putVReg( vD_addr,
17162               binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
17163      return True;
17164
17165   case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
17166      DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17167      putVReg( vD_addr,
17168               binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
17169      // TODO: set VSCR[SAT]
17170      return True;
17171
17172   case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
17173      // This insn does a doubled signed->double unsigned saturating conversion
17174      // Conversion done here, then uses unsigned->unsigned vpk insn:
17175      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
17176      // This is similar to the technique used for vpkswus, except done
17177      // with double word integers versus word integers.
17178      IRTemp vA_tmp = newTemp(Ity_V128);
17179      IRTemp vB_tmp = newTemp(Ity_V128);
17180      DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17181      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17182                            unop(Iop_NotV128,
17183                                 binop(Iop_SarN64x2,
17184                                       mkexpr(vA), mkU8(63)))) );
17185      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17186                            unop(Iop_NotV128,
17187                                 binop(Iop_SarN64x2,
17188                                       mkexpr(vB), mkU8(63)))) );
17189      putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
17190                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17191      // TODO: set VSCR[SAT]
17192      return True;
17193   }
17194
17195   case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
17196      DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17197      putVReg( vD_addr,
17198               binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
17199      // TODO: set VSCR[SAT]
17200      return True;
17201   default:
17202      break; // Fall through...
17203   }
17204
17205
17206   if (vA_addr != 0) {
17207      vex_printf("dis_av_pack(ppc)(vA_addr)\n");
17208      return False;
17209   }
17210
17211   signs = newTemp(Ity_V128);
17212   zeros = newTemp(Ity_V128);
17213   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
17214
17215   switch (opc2) {
17216   /* Unpacking */
17217   case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
17218      DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
17219      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
17220      putVReg( vD_addr,
17221               binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
17222      break;
17223   }
17224   case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
17225      DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
17226      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
17227      putVReg( vD_addr,
17228               binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
17229      break;
17230   }
17231   case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
17232      DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
17233      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
17234      putVReg( vD_addr,
17235               binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
17236      break;
17237   }
17238   case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
17239      DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
17240      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
17241      putVReg( vD_addr,
17242               binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
17243      break;
17244   }
17245   case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
17246      /* CAB: Worth a new primop? */
17247      /* Using shifts to isolate pixel elements, then expanding them */
17248      IRTemp z0  = newTemp(Ity_V128);
17249      IRTemp z1  = newTemp(Ity_V128);
17250      IRTemp z01 = newTemp(Ity_V128);
17251      IRTemp z2  = newTemp(Ity_V128);
17252      IRTemp z3  = newTemp(Ity_V128);
17253      IRTemp z23 = newTemp(Ity_V128);
17254      DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
17255      assign( z0,  binop(Iop_ShlN16x8,
17256                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
17257                         mkU8(8)) );
17258      assign( z1,  binop(Iop_ShrN16x8,
17259                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
17260                         mkU8(11)) );
17261      assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
17262                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
17263      assign( z2,  binop(Iop_ShrN16x8,
17264                         binop(Iop_ShlN16x8,
17265                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
17266                               mkU8(11)),
17267                         mkU8(3)) );
17268      assign( z3,  binop(Iop_ShrN16x8,
17269                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
17270                         mkU8(11)) );
17271      assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
17272                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
17273      putVReg( vD_addr,
17274               binop(Iop_OrV128,
17275                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
17276                     mkexpr(z23)) );
17277      break;
17278   }
17279   case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
17280      /* identical to vupkhpx, except interleaving LO */
17281      IRTemp z0  = newTemp(Ity_V128);
17282      IRTemp z1  = newTemp(Ity_V128);
17283      IRTemp z01 = newTemp(Ity_V128);
17284      IRTemp z2  = newTemp(Ity_V128);
17285      IRTemp z3  = newTemp(Ity_V128);
17286      IRTemp z23 = newTemp(Ity_V128);
17287      DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
17288      assign( z0,  binop(Iop_ShlN16x8,
17289                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
17290                         mkU8(8)) );
17291      assign( z1,  binop(Iop_ShrN16x8,
17292                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
17293                         mkU8(11)) );
17294      assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
17295                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
17296      assign( z2,  binop(Iop_ShrN16x8,
17297                         binop(Iop_ShlN16x8,
17298                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
17299                               mkU8(11)),
17300                         mkU8(3)) );
17301      assign( z3,  binop(Iop_ShrN16x8,
17302                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
17303                         mkU8(11)) );
17304      assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
17305                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
17306      putVReg( vD_addr,
17307               binop(Iop_OrV128,
17308                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
17309                     mkexpr(z23)) );
17310      break;
17311   }
17312   case 0x64E: { // vupkhsw (Unpack High Signed Word)
17313      DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
17314      assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
17315      putVReg( vD_addr,
17316               binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
17317      break;
17318   }
17319   case 0x6CE: { // vupklsw (Unpack Low Signed Word)
17320      DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
17321      assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
17322      putVReg( vD_addr,
17323               binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
17324      break;
17325   }
17326   default:
17327      vex_printf("dis_av_pack(ppc)(opc2)\n");
17328      return False;
17329   }
17330   return True;
17331}
17332
17333/*
17334  AltiVec Cipher Instructions
17335*/
17336static Bool dis_av_cipher ( UInt theInstr )
17337{
17338   /* VX-Form */
17339   UChar opc1     = ifieldOPC(theInstr);
17340   UChar vD_addr  = ifieldRegDS(theInstr);
17341   UChar vA_addr  = ifieldRegA(theInstr);
17342   UChar vB_addr  = ifieldRegB(theInstr);
17343   UInt  opc2     = IFIELD( theInstr, 0, 11 );
17344
17345   IRTemp vA    = newTemp(Ity_V128);
17346   IRTemp vB    = newTemp(Ity_V128);
17347   assign( vA, getVReg(vA_addr));
17348   assign( vB, getVReg(vB_addr));
17349
17350   if (opc1 != 0x4) {
17351      vex_printf("dis_av_cipher(ppc)(instr)\n");
17352      return False;
17353   }
17354   switch (opc2) {
17355      case 0x508: // vcipher (Vector Inverser Cipher)
17356         DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17357         putVReg( vD_addr,
17358                  binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
17359         return True;
17360
17361      case 0x509: // vcipherlast (Vector Inverser Cipher Last)
17362         DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17363         putVReg( vD_addr,
17364                  binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
17365         return True;
17366
17367      case 0x548: // vncipher (Vector Inverser Cipher)
17368         DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17369         putVReg( vD_addr,
17370                  binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
17371         return True;
17372
17373      case 0x549: // vncipherlast (Vector Inverser Cipher Last)
17374         DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17375         putVReg( vD_addr,
17376                  binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
17377         return True;
17378
17379      case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
17380       * subBytes transform)
17381       */
17382         DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
17383         putVReg( vD_addr,
17384                  unop(Iop_CipherSV128, mkexpr(vA) ) );
17385         return True;
17386
17387      default:
17388         vex_printf("dis_av_cipher(ppc)(opc2)\n");
17389         return False;
17390   }
17391   return True;
17392}
17393
17394/*
17395  AltiVec Secure Hash Instructions
17396*/
17397static Bool dis_av_hash ( UInt theInstr )
17398{
17399   /* VX-Form */
17400   UChar opc1     = ifieldOPC(theInstr);
17401   UChar vRT_addr = ifieldRegDS(theInstr);
17402   UChar vRA_addr  = ifieldRegA(theInstr);
17403   UChar s_field  = IFIELD( theInstr, 11, 5 );  // st and six field
17404   UChar st       = IFIELD( theInstr, 15, 1 );  // st
17405   UChar six      = IFIELD( theInstr, 11, 4 );  // six field
17406   UInt  opc2     = IFIELD( theInstr, 0, 11 );
17407
17408   IRTemp vA    = newTemp(Ity_V128);
17409   IRTemp dst    = newTemp(Ity_V128);
17410   assign( vA, getVReg(vRA_addr));
17411
17412   if (opc1 != 0x4) {
17413      vex_printf("dis_av_hash(ppc)(instr)\n");
17414      return False;
17415   }
17416
17417   switch (opc2) {
17418      case 0x682:  // vshasigmaw
17419         DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
17420         assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
17421         putVReg( vRT_addr, mkexpr(dst));
17422         return True;
17423
17424      case 0x6C2:  // vshasigmad,
17425         DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
17426         putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
17427         return True;
17428
17429      default:
17430         vex_printf("dis_av_hash(ppc)(opc2)\n");
17431         return False;
17432   }
17433   return True;
17434}
17435
17436/*
17437 * This function is used by the Vector add/subtract [extended] modulo/carry
17438 * instructions.
17439 *   - For the non-extended add instructions, the cin arg is set to zero.
17440 *   - For the extended add instructions, cin is the integer value of
17441 *     src3.bit[127].
17442 *   - For the non-extended subtract instructions, src1 is added to the one's
17443 *     complement of src2 + 1.  We re-use the cin argument to hold the '1'
17444 *     value for this operation.
17445 *   - For the extended subtract instructions, cin is the integer value of src3.bit[127].
17446 */
17447static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
17448                                        IRExpr * cin, Bool modulo)
17449{
17450   IRTemp _vecA_32   = IRTemp_INVALID;
17451   IRTemp _vecB_32   = IRTemp_INVALID;
17452   IRTemp res_32     = IRTemp_INVALID;
17453   IRTemp result     = IRTemp_INVALID;
17454   IRTemp tmp_result = IRTemp_INVALID;
17455   IRTemp carry      = IRTemp_INVALID;
17456   Int i;
17457   IRExpr * _vecA_low64 =  unop( Iop_V128to64, vecA );
17458   IRExpr * _vecB_low64 =  unop( Iop_V128to64, vecB );
17459   IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
17460   IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
17461
17462   for (i = 0; i < 4; i++) {
17463      _vecA_32 = newTemp(Ity_I32);
17464      _vecB_32 = newTemp(Ity_I32);
17465      res_32   = newTemp(Ity_I32);
17466      switch (i) {
17467      case 0:
17468         assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
17469         assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
17470         break;
17471      case 1:
17472         assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
17473         assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
17474         break;
17475      case 2:
17476         assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
17477         assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
17478         break;
17479      case 3:
17480         assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
17481         assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
17482         break;
17483      }
17484
17485      assign(res_32, binop( Iop_Add32,
17486                            binop( Iop_Add32,
17487                                   binop ( Iop_Add32,
17488                                           mkexpr(_vecA_32),
17489                                           mkexpr(_vecB_32) ),
17490                                   (i == 0) ? mkU32(0) : mkexpr(carry) ),
17491                            (i == 0) ? cin : mkU32(0) ) );
17492      if (modulo) {
17493         result = newTemp(Ity_V128);
17494         assign(result, binop( Iop_OrV128,
17495                              (i == 0) ? binop( Iop_64HLtoV128,
17496                                                mkU64(0),
17497                                                mkU64(0) ) : mkexpr(tmp_result),
17498                              binop( Iop_ShlV128,
17499                                     binop( Iop_64HLtoV128,
17500                                            mkU64(0),
17501                                            binop( Iop_32HLto64,
17502                                                   mkU32(0),
17503                                                   mkexpr(res_32) ) ),
17504                                     mkU8(i * 32) ) ) );
17505         tmp_result = newTemp(Ity_V128);
17506         assign(tmp_result, mkexpr(result));
17507      }
17508      carry = newTemp(Ity_I32);
17509      assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U,
17510                                            mkexpr(res_32),
17511                                            mkexpr(_vecA_32 ) ) ) );
17512   }
17513   if (modulo)
17514      return result;
17515   else
17516      return carry;
17517}
17518
17519
17520static Bool dis_av_quad ( UInt theInstr )
17521{
17522   /* VX-Form */
17523   UChar opc1     = ifieldOPC(theInstr);
17524   UChar vRT_addr = ifieldRegDS(theInstr);
17525   UChar vRA_addr = ifieldRegA(theInstr);
17526   UChar vRB_addr = ifieldRegB(theInstr);
17527   UChar vRC_addr;
17528   UInt  opc2     = IFIELD( theInstr, 0, 11 );
17529
17530   IRTemp vA    = newTemp(Ity_V128);
17531   IRTemp vB    = newTemp(Ity_V128);
17532   IRTemp vC    = IRTemp_INVALID;
17533   IRTemp cin    = IRTemp_INVALID;
17534   assign( vA, getVReg(vRA_addr));
17535   assign( vB, getVReg(vRB_addr));
17536
17537   if (opc1 != 0x4) {
17538      vex_printf("dis_av_quad(ppc)(instr)\n");
17539      return False;
17540   }
17541
17542   switch (opc2) {
17543   case 0x140:  // vaddcuq
17544     DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
17545     putVReg( vRT_addr, unop( Iop_32UtoV128,
17546                              mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
17547                                                               mkexpr(vB),
17548                                                               mkU32(0), False) ) ) );
17549     return True;
17550   case 0x100: // vadduqm
17551      DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
17552      putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
17553                                                          mkexpr(vB), mkU32(0), True) ) );
17554      return True;
17555   case 0x540: // vsubcuq
17556      DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
17557      putVReg( vRT_addr,
17558               unop( Iop_32UtoV128,
17559                     mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
17560                                                      unop( Iop_NotV128,
17561                                                            mkexpr(vB) ),
17562                                                      mkU32(1), False) ) ) );
17563      return True;
17564   case 0x500: // vsubuqm
17565      DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
17566      putVReg( vRT_addr,
17567               mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
17568                                                unop( Iop_NotV128, mkexpr(vB) ),
17569                                                mkU32(1), True) ) );
17570      return True;
17571   case 0x054C: // vbpermq
17572   {
17573#define BPERMD_IDX_MASK 0x00000000000000FFULL
17574#define BPERMD_BIT_MASK 0x8000000000000000ULL
17575      int i;
17576      IRExpr * vB_expr = mkexpr(vB);
17577      IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
17578      DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
17579      for (i = 0; i < 16; i++) {
17580         IRTemp idx_tmp = newTemp( Ity_V128 );
17581         IRTemp perm_bit = newTemp( Ity_V128 );
17582         IRTemp idx = newTemp( Ity_I8 );
17583         IRTemp idx_LT127 = newTemp( Ity_I1 );
17584         IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
17585
17586         assign( idx_tmp,
17587                 binop( Iop_AndV128,
17588                        binop( Iop_64HLtoV128,
17589                               mkU64(0),
17590                               mkU64(BPERMD_IDX_MASK) ),
17591                        vB_expr ) );
17592         assign( idx_LT127,
17593                 binop( Iop_CmpEQ32,
17594                        unop ( Iop_64to32,
17595                               unop( Iop_V128to64, binop( Iop_ShrV128,
17596                                                          mkexpr(idx_tmp),
17597                                                          mkU8(7) ) ) ),
17598                        mkU32(0) ) );
17599
17600         /* Below, we set idx to determine which bit of vA to use for the
17601          * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
17602          */
17603         assign( idx,
17604                 binop( Iop_And8,
17605                        unop( Iop_1Sto8,
17606                              mkexpr(idx_LT127) ),
17607                        unop( Iop_32to8,
17608                              unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
17609
17610         assign( idx_LT127_ity128,
17611                 binop( Iop_64HLtoV128,
17612                        mkU64(0),
17613                        unop( Iop_32Uto64,
17614                              unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
17615         assign( perm_bit,
17616                 binop( Iop_AndV128,
17617                        mkexpr( idx_LT127_ity128 ),
17618                        binop( Iop_ShrV128,
17619                               binop( Iop_AndV128,
17620                                      binop (Iop_64HLtoV128,
17621                                             mkU64( BPERMD_BIT_MASK ),
17622                                             mkU64(0)),
17623                                      binop( Iop_ShlV128,
17624                                             mkexpr( vA ),
17625                                             mkexpr( idx ) ) ),
17626                               mkU8( 127 ) ) ) );
17627         res = binop( Iop_OrV128,
17628                      res,
17629                      binop( Iop_ShlV128,
17630                             mkexpr( perm_bit ),
17631                             mkU8( i ) ) );
17632         vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
17633      }
17634      putVReg( vRT_addr, res);
17635      return True;
17636#undef BPERMD_IDX_MASK
17637#undef BPERMD_BIT_MASK
17638   }
17639
17640   default:
17641      break;  // fall through
17642   }
17643
17644   opc2     = IFIELD( theInstr, 0, 6 );
17645   vRC_addr = ifieldRegC(theInstr);
17646   vC = newTemp(Ity_V128);
17647   cin = newTemp(Ity_I32);
17648   switch (opc2) {
17649      case 0x3D: // vaddecuq
17650         assign( vC, getVReg(vRC_addr));
17651         DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
17652             vRC_addr);
17653         assign(cin, binop( Iop_And32,
17654                            unop( Iop_64to32,
17655                                  unop( Iop_V128to64, mkexpr(vC) ) ),
17656                            mkU32(1) ) );
17657         putVReg( vRT_addr,
17658                  unop( Iop_32UtoV128,
17659                        mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
17660                                                         mkexpr(cin),
17661                                                         False) ) ) );
17662         return True;
17663      case 0x3C: // vaddeuqm
17664         assign( vC, getVReg(vRC_addr));
17665         DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
17666             vRC_addr);
17667         assign(cin, binop( Iop_And32,
17668                            unop( Iop_64to32,
17669                                  unop( Iop_V128to64, mkexpr(vC) ) ),
17670                            mkU32(1) ) );
17671         putVReg( vRT_addr,
17672                  mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
17673                                                   mkexpr(cin),
17674                                                   True) ) );
17675         return True;
17676      case 0x3F: // vsubecuq
17677         assign( vC, getVReg(vRC_addr));
17678         DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
17679             vRC_addr);
17680         assign(cin, binop( Iop_And32,
17681                            unop( Iop_64to32,
17682                                  unop( Iop_V128to64, mkexpr(vC) ) ),
17683                            mkU32(1) ) );
17684         putVReg( vRT_addr,
17685                  unop( Iop_32UtoV128,
17686                        mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
17687                                                         unop( Iop_NotV128,
17688                                                               mkexpr(vB) ),
17689                                                         mkexpr(cin),
17690                                                         False) ) ) );
17691         return True;
17692      case 0x3E: // vsubeuqm
17693         assign( vC, getVReg(vRC_addr));
17694         DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
17695             vRC_addr);
17696         assign(cin, binop( Iop_And32,
17697                            unop( Iop_64to32,
17698                                  unop( Iop_V128to64, mkexpr(vC) ) ),
17699                            mkU32(1) ) );
17700         putVReg( vRT_addr,
17701                  mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
17702                                                   unop( Iop_NotV128, mkexpr(vB) ),
17703                                                   mkexpr(cin),
17704                                                   True) ) );
17705         return True;
17706      default:
17707         vex_printf("dis_av_quad(ppc)(opc2.2)\n");
17708         return False;
17709   }
17710
17711   return True;
17712}
17713
17714
17715/*
17716  AltiVec BCD Arithmetic instructions.
17717  These instructions modify CR6 for various conditions in the result,
17718  including when an overflow occurs.  We could easily detect all conditions
17719  except when an overflow occurs.  But since we can't be 100% accurate
17720  in our emulation of CR6, it seems best to just not support it all.
17721*/
17722static Bool dis_av_bcd ( UInt theInstr )
17723{
17724   /* VX-Form */
17725   UChar opc1     = ifieldOPC(theInstr);
17726   UChar vRT_addr = ifieldRegDS(theInstr);
17727   UChar vRA_addr = ifieldRegA(theInstr);
17728   UChar vRB_addr = ifieldRegB(theInstr);
17729   UChar ps       = IFIELD( theInstr, 9, 1 );
17730   UInt  opc2     = IFIELD( theInstr, 0, 9 );
17731
17732   IRTemp vA    = newTemp(Ity_V128);
17733   IRTemp vB    = newTemp(Ity_V128);
17734   IRTemp dst    = newTemp(Ity_V128);
17735   assign( vA, getVReg(vRA_addr));
17736   assign( vB, getVReg(vRB_addr));
17737
17738   if (opc1 != 0x4) {
17739      vex_printf("dis_av_bcd(ppc)(instr)\n");
17740      return False;
17741   }
17742
17743   switch (opc2) {
17744   case 0x1:  // bcdadd
17745     DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
17746     assign( dst, triop( Iop_BCDAdd, mkexpr( vA ),
17747                         mkexpr( vB ), mkU8( ps ) ) );
17748     putVReg( vRT_addr, mkexpr(dst));
17749     return True;
17750
17751   case 0x41:  // bcdsub
17752     DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
17753     assign( dst, triop( Iop_BCDSub, mkexpr( vA ),
17754                         mkexpr( vB ), mkU8( ps ) ) );
17755     putVReg( vRT_addr, mkexpr(dst));
17756     return True;
17757
17758   default:
17759      vex_printf("dis_av_bcd(ppc)(opc2)\n");
17760      return False;
17761   }
17762   return True;
17763}
17764
17765/*
17766  AltiVec Floating Point Arithmetic Instructions
17767*/
17768static Bool dis_av_fp_arith ( UInt theInstr )
17769{
17770   /* VA-Form */
17771   UChar opc1     = ifieldOPC(theInstr);
17772   UChar vD_addr  = ifieldRegDS(theInstr);
17773   UChar vA_addr  = ifieldRegA(theInstr);
17774   UChar vB_addr  = ifieldRegB(theInstr);
17775   UChar vC_addr  = ifieldRegC(theInstr);
17776   UInt  opc2=0;
17777
17778   IRTemp vA = newTemp(Ity_V128);
17779   IRTemp vB = newTemp(Ity_V128);
17780   IRTemp vC = newTemp(Ity_V128);
17781   assign( vA, getVReg(vA_addr));
17782   assign( vB, getVReg(vB_addr));
17783   assign( vC, getVReg(vC_addr));
17784
17785   if (opc1 != 0x4) {
17786      vex_printf("dis_av_fp_arith(ppc)(instr)\n");
17787      return False;
17788   }
17789
17790   IRTemp rm = newTemp(Ity_I32);
17791   assign(rm, get_IR_roundingmode());
17792
17793   opc2 = IFIELD( theInstr, 0, 6 );
17794   switch (opc2) {
17795   case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
17796      DIP("vmaddfp v%d,v%d,v%d,v%d\n",
17797          vD_addr, vA_addr, vC_addr, vB_addr);
17798      putVReg( vD_addr,
17799               triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
17800                     mkexpr(vB),
17801                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
17802                           mkexpr(vA), mkexpr(vC))) );
17803      return True;
17804
17805   case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
17806      DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
17807          vD_addr, vA_addr, vC_addr, vB_addr);
17808      putVReg( vD_addr,
17809               triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
17810                     mkexpr(vB),
17811                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
17812                           mkexpr(vA), mkexpr(vC))) );
17813      return True;
17814   }
17815
17816   default:
17817     break; // Fall through...
17818   }
17819
17820   opc2 = IFIELD( theInstr, 0, 11 );
17821   switch (opc2) {
17822   case 0x00A: // vaddfp (Add FP, AV p137)
17823      DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17824      putVReg( vD_addr, triop(Iop_Add32Fx4,
17825                              mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
17826      return True;
17827
17828  case 0x04A: // vsubfp (Subtract FP, AV p261)
17829      DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17830      putVReg( vD_addr, triop(Iop_Sub32Fx4,
17831                              mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
17832      return True;
17833
17834   case 0x40A: // vmaxfp (Maximum FP, AV p178)
17835      DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17836      putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
17837      return True;
17838
17839   case 0x44A: // vminfp (Minimum FP, AV p187)
17840      DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17841      putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
17842      return True;
17843
17844   default:
17845      break; // Fall through...
17846   }
17847
17848
17849   if (vA_addr != 0) {
17850      vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
17851      return False;
17852   }
17853
17854   switch (opc2) {
17855   case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
17856      DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
17857      putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) );
17858      return True;
17859
17860   case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
17861      DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
17862      putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) );
17863      return True;
17864
17865   case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
17866      DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
17867      DIP(" => not implemented\n");
17868      return False;
17869
17870   case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
17871      DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
17872      DIP(" => not implemented\n");
17873      return False;
17874
17875   default:
17876      vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
17877      return False;
17878   }
17879   return True;
17880}
17881
17882/*
17883  AltiVec Floating Point Compare Instructions
17884*/
17885static Bool dis_av_fp_cmp ( UInt theInstr )
17886{
17887   /* VXR-Form */
17888   UChar opc1     = ifieldOPC(theInstr);
17889   UChar vD_addr  = ifieldRegDS(theInstr);
17890   UChar vA_addr  = ifieldRegA(theInstr);
17891   UChar vB_addr  = ifieldRegB(theInstr);
17892   UChar flag_rC  = ifieldBIT10(theInstr);
17893   UInt  opc2     = IFIELD( theInstr, 0, 10 );
17894
17895   Bool cmp_bounds = False;
17896
17897   IRTemp vA = newTemp(Ity_V128);
17898   IRTemp vB = newTemp(Ity_V128);
17899   IRTemp vD = newTemp(Ity_V128);
17900   assign( vA, getVReg(vA_addr));
17901   assign( vB, getVReg(vB_addr));
17902
17903   if (opc1 != 0x4) {
17904      vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
17905      return False;
17906   }
17907
17908   switch (opc2) {
17909   case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
17910      DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
17911                                      vD_addr, vA_addr, vB_addr);
17912      assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
17913      break;
17914
17915   case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
17916      DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
17917                                      vD_addr, vA_addr, vB_addr);
17918      assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
17919      break;
17920
17921   case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
17922      DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
17923                                      vD_addr, vA_addr, vB_addr);
17924      assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
17925      break;
17926
17927   case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
17928      IRTemp gt      = newTemp(Ity_V128);
17929      IRTemp lt      = newTemp(Ity_V128);
17930      IRTemp zeros   = newTemp(Ity_V128);
17931      DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
17932                                     vD_addr, vA_addr, vB_addr);
17933      cmp_bounds = True;
17934      assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
17935
17936      /* Note: making use of fact that the ppc backend for compare insns
17937         return zero'd lanes if either of the corresponding arg lanes is
17938         a nan.
17939
17940         Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
17941         need this for the other compares too (vcmpeqfp etc)...
17942         Better still, tighten down the spec for compare irops.
17943       */
17944      assign( gt, unop(Iop_NotV128,
17945                       binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
17946      assign( lt, unop(Iop_NotV128,
17947                       binop(Iop_CmpGE32Fx4, mkexpr(vA),
17948                             triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
17949                                   mkexpr(zeros),
17950                                   mkexpr(vB)))) );
17951
17952      // finally, just shift gt,lt to correct position
17953      assign( vD, binop(Iop_ShlN32x4,
17954                        binop(Iop_OrV128,
17955                              binop(Iop_AndV128, mkexpr(gt),
17956                                    unop(Iop_Dup32x4, mkU32(0x2))),
17957                              binop(Iop_AndV128, mkexpr(lt),
17958                                    unop(Iop_Dup32x4, mkU32(0x1)))),
17959                        mkU8(30)) );
17960      break;
17961   }
17962
17963   default:
17964      vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
17965      return False;
17966   }
17967
17968   putVReg( vD_addr, mkexpr(vD) );
17969
17970   if (flag_rC) {
17971      set_AV_CR6( mkexpr(vD), !cmp_bounds );
17972   }
17973   return True;
17974}
17975
17976/*
17977  AltiVec Floating Point Convert/Round Instructions
17978*/
17979static Bool dis_av_fp_convert ( UInt theInstr )
17980{
17981   /* VX-Form */
17982   UChar opc1     = ifieldOPC(theInstr);
17983   UChar vD_addr  = ifieldRegDS(theInstr);
17984   UChar UIMM_5   = ifieldRegA(theInstr);
17985   UChar vB_addr  = ifieldRegB(theInstr);
17986   UInt  opc2     = IFIELD( theInstr, 0, 11 );
17987
17988   IRTemp vB        = newTemp(Ity_V128);
17989   IRTemp vScale    = newTemp(Ity_V128);
17990   IRTemp vInvScale = newTemp(Ity_V128);
17991
17992   float scale, inv_scale;
17993
17994   assign( vB, getVReg(vB_addr));
17995
17996   /* scale = 2^UIMM, cast to float, reinterpreted as uint */
17997   scale = (float)( (unsigned int) 1<<UIMM_5 );
17998   assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
17999   inv_scale = 1/scale;
18000   assign( vInvScale,
18001           unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
18002
18003   if (opc1 != 0x4) {
18004      vex_printf("dis_av_fp_convert(ppc)(instr)\n");
18005      return False;
18006   }
18007
18008   switch (opc2) {
18009   case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
18010      DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18011      putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18012                              unop(Iop_I32UtoFx4, mkexpr(vB)),
18013                              mkexpr(vInvScale)) );
18014      return True;
18015
18016   case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
18017      DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18018
18019      putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18020                              unop(Iop_I32StoFx4, mkexpr(vB)),
18021                              mkexpr(vInvScale)) );
18022      return True;
18023
18024   case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
18025      DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18026      putVReg( vD_addr,
18027               unop(Iop_QFtoI32Ux4_RZ,
18028                    triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18029                          mkexpr(vB), mkexpr(vScale))) );
18030      return True;
18031
18032   case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
18033      DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18034      putVReg( vD_addr,
18035               unop(Iop_QFtoI32Sx4_RZ,
18036                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18037                           mkexpr(vB), mkexpr(vScale))) );
18038      return True;
18039
18040   default:
18041     break;    // Fall through...
18042   }
18043
18044   if (UIMM_5 != 0) {
18045      vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
18046      return False;
18047   }
18048
18049   switch (opc2) {
18050   case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
18051      DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
18052      putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
18053      break;
18054
18055   case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
18056      DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
18057      putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
18058      break;
18059
18060   case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
18061      DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
18062      putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
18063      break;
18064
18065   case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
18066      DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
18067      putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
18068      break;
18069
18070   default:
18071      vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
18072      return False;
18073   }
18074   return True;
18075}
18076
18077static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
18078                                       VexAbiInfo* vbi,
18079                                       /*OUT*/DisResult* dres,
18080                                       Bool (*resteerOkFn)(void*,Addr64),
18081                                       void* callback_opaque )
18082{
18083   UInt   opc2      = IFIELD( theInstr, 1, 10 );
18084
18085   switch (opc2) {
18086   case 0x28E: {        //tbegin.
18087      /* The current implementation is to just fail the tbegin and execute
18088       * the failure path.  The failure path is assumed to be functionaly
18089       * equivalent to the transactional path with the needed data locking
18090       * to ensure correctness.  The tend is just a noop and shouldn't
18091       * actually get executed.
18092       *   1) set cr0 to 0x2
18093       *   2) Initialize TFHAR to CIA+4
18094       *   3) Initialize TEXASR
18095       *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
18096       *   5) Continue executing at the next instruction.
18097       */
18098      UInt R = IFIELD( theInstr, 21, 1 );
18099
18100      ULong tm_reason;
18101      UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
18102                               * or treclaim.
18103                               */
18104      UInt persistant = 1;    /* set persistant since we are always failing
18105                               * the tbegin.
18106                               */
18107      UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
18108                                 as the reason for failing the trasaction */
18109      UInt tm_exact   = 1;    /* have exact address for failure */
18110
18111      DIP("tbegin. %d\n", R);
18112
18113      /* Set the CR0 field to indicate the tbegin failed.  Then let
18114       * the code do the branch to the failure path.
18115       *
18116       * 000 || 0  Transaction initiation successful,
18117       *           unnested (Transaction state of
18118       *           Non-transactional prior to tbegin.)
18119       * 010 || 0  Transaction initiation successful, nested
18120       *           (Transaction state of Transactional
18121       *           prior to tbegin.)
18122       * 001 || 0  Transaction initiation unsuccessful,
18123       *           (Transaction state of Suspended prior
18124       *           to tbegin.)
18125       */
18126      putCR321( 0, mkU8( 0x2 ) );
18127
18128      tm_reason = generate_TMreason( failure_code, persistant,
18129                                     nest_overflow, tm_exact );
18130
18131      storeTMfailure( guest_CIA_curr_instr, tm_reason,
18132                      guest_CIA_curr_instr+4 );
18133
18134      return True;
18135
18136      break;
18137   }
18138
18139   case 0x2AE: {        //tend.
18140      /* The tend. is just a noop.  Do nothing */
18141      UInt A = IFIELD( theInstr, 25, 1 );
18142
18143      DIP("tend. %d\n", A);
18144      break;
18145   }
18146
18147   case 0x2EE: {        //tsr.
18148      /* The tsr. is just a noop.  Do nothing */
18149      UInt L = IFIELD( theInstr, 21, 1 );
18150
18151      DIP("tsr. %d\n", L);
18152      break;
18153   }
18154
18155   case 0x2CE: {        //tcheck.
18156      /* The tcheck. is just a noop.  Do nothing */
18157      UInt BF = IFIELD( theInstr, 25, 1 );
18158
18159      DIP("tcheck. %d\n", BF);
18160      break;
18161   }
18162
18163   case 0x30E: {        //tbortwc.
18164      /* The tabortwc. is just a noop.  Do nothing */
18165      UInt TO = IFIELD( theInstr, 25, 1 );
18166      UInt RA = IFIELD( theInstr, 16, 5 );
18167      UInt RB = IFIELD( theInstr, 11, 5 );
18168
18169      DIP("tabortwc. %d,%d,%d\n", TO, RA, RB);
18170      break;
18171   }
18172
18173   case 0x32E: {        //tbortdc.
18174      /* The tabortdc. is just a noop.  Do nothing */
18175      UInt TO = IFIELD( theInstr, 25, 1 );
18176      UInt RA = IFIELD( theInstr, 16, 5 );
18177      UInt RB = IFIELD( theInstr, 11, 5 );
18178
18179      DIP("tabortdc. %d,%d,%d\n", TO, RA, RB);
18180      break;
18181   }
18182
18183   case 0x34E: {        //tbortwci.
18184      /* The tabortwci. is just a noop.  Do nothing */
18185      UInt TO = IFIELD( theInstr, 25, 1 );
18186      UInt RA = IFIELD( theInstr, 16, 5 );
18187      UInt SI = IFIELD( theInstr, 11, 5 );
18188
18189      DIP("tabortwci. %d,%d,%d\n", TO, RA, SI);
18190      break;
18191   }
18192
18193   case 0x36E: {        //tbortdci.
18194      /* The tabortdci. is just a noop.  Do nothing */
18195      UInt TO = IFIELD( theInstr, 25, 1 );
18196      UInt RA = IFIELD( theInstr, 16, 5 );
18197      UInt SI = IFIELD( theInstr, 11, 5 );
18198
18199      DIP("tabortdci. %d,%d,%d\n", TO, RA, SI);
18200      break;
18201   }
18202
18203   case 0x38E: {        //tbort.
18204      /* The tabort. is just a noop.  Do nothing */
18205      UInt RA = IFIELD( theInstr, 16, 5 );
18206
18207      DIP("tabort. %d\n", RA);
18208      break;
18209   }
18210
18211   case 0x3AE: {        //treclaim.
18212      /* The treclaim. is just a noop.  Do nothing */
18213      UInt RA = IFIELD( theInstr, 16, 5 );
18214
18215      DIP("treclaim. %d\n", RA);
18216      break;
18217   }
18218
18219   case 0x3EE: {        //trechkpt.
18220      /* The trechkpt. is just a noop.  Do nothing */
18221      DIP("trechkpt.\n");
18222      break;
18223   }
18224
18225   default:
18226      vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
18227      return False;
18228   }
18229
18230   return True;
18231}
18232
18233
18234/* The 0x3C primary opcode (VSX category) uses several different forms of
18235 * extended opcodes:
18236 *   o XX2-form:
18237 *      - [10:2] (IBM notation [21:29])
18238 *   o XX3-form variants:
18239 *       - variant 1: [10:3] (IBM notation [21:28])
18240 *       - variant 2: [9:3] (IBM notation [22:28])
18241 *       - variant 3: [7:3] (IBM notation [24:28])
18242 *   o XX-4 form:
18243 *      - [10:6] (IBM notation [21:25])
18244 *
18245 * The XX2-form needs bit 0 masked from the standard extended opcode
18246 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
18247 * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
18248 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
18249 * front end since their encoding does not begin at bit 21 like the standard
18250 * format.
18251 *
18252 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
18253 * secondary opcode for such VSX instructions.
18254 *
18255*/
18256
18257
18258struct vsx_insn {
18259   UInt opcode;
18260   const HChar * name;
18261};
18262
18263//  ATTENTION:  Keep this array sorted on the opcocde!!!
18264static struct vsx_insn vsx_all[] = {
18265      { 0x0, "xsaddsp" },
18266      { 0x4, "xsmaddasp" },
18267      { 0x8, "xxsldwi" },
18268      { 0x14, "xsrsqrtesp" },
18269      { 0x16, "xssqrtsp" },
18270      { 0x18, "xxsel" },
18271      { 0x20, "xssubsp" },
18272      { 0x24, "xsmaddmsp" },
18273      { 0x28, "xxpermdi" },
18274      { 0x34, "xsresp" },
18275      { 0x40, "xsmulsp" },
18276      { 0x44, "xsmsubasp" },
18277      { 0x48, "xxmrghw" },
18278      { 0x60, "xsdivsp" },
18279      { 0x64, "xsmsubmsp" },
18280      { 0x80, "xsadddp" },
18281      { 0x84, "xsmaddadp" },
18282      { 0x8c, "xscmpudp" },
18283      { 0x90, "xscvdpuxws" },
18284      { 0x92, "xsrdpi" },
18285      { 0x94, "xsrsqrtedp" },
18286      { 0x96, "xssqrtdp" },
18287      { 0xa0, "xssubdp" },
18288      { 0xa4, "xsmaddmdp" },
18289      { 0xac, "xscmpodp" },
18290      { 0xb0, "xscvdpsxws" },
18291      { 0xb2, "xsrdpiz" },
18292      { 0xb4, "xsredp" },
18293      { 0xc0, "xsmuldp" },
18294      { 0xc4, "xsmsubadp" },
18295      { 0xc8, "xxmrglw" },
18296      { 0xd2, "xsrdpip" },
18297      { 0xd4, "xstsqrtdp" },
18298      { 0xd6, "xsrdpic" },
18299      { 0xe0, "xsdivdp" },
18300      { 0xe4, "xsmsubmdp" },
18301      { 0xf2, "xsrdpim" },
18302      { 0xf4, "xstdivdp" },
18303      { 0x100, "xvaddsp" },
18304      { 0x104, "xvmaddasp" },
18305      { 0x10c, "xvcmpeqsp" },
18306      { 0x110, "xvcvspuxws" },
18307      { 0x112, "xvrspi" },
18308      { 0x114, "xvrsqrtesp" },
18309      { 0x116, "xvsqrtsp" },
18310      { 0x120, "xvsubsp" },
18311      { 0x124, "xvmaddmsp" },
18312      { 0x12c, "xvcmpgtsp" },
18313      { 0x130, "xvcvspsxws" },
18314      { 0x132, "xvrspiz" },
18315      { 0x134, "xvresp" },
18316      { 0x140, "xvmulsp" },
18317      { 0x144, "xvmsubasp" },
18318      { 0x148, "xxspltw" },
18319      { 0x14c, "xvcmpgesp" },
18320      { 0x150, "xvcvuxwsp" },
18321      { 0x152, "xvrspip" },
18322      { 0x154, "xvtsqrtsp" },
18323      { 0x156, "xvrspic" },
18324      { 0x160, "xvdivsp" },
18325      { 0x164, "xvmsubmsp" },
18326      { 0x170, "xvcvsxwsp" },
18327      { 0x172, "xvrspim" },
18328      { 0x174, "xvtdivsp" },
18329      { 0x180, "xvadddp" },
18330      { 0x184, "xvmaddadp" },
18331      { 0x18c, "xvcmpeqdp" },
18332      { 0x190, "xvcvdpuxws" },
18333      { 0x192, "xvrdpi" },
18334      { 0x194, "xvrsqrtedp" },
18335      { 0x196, "xvsqrtdp" },
18336      { 0x1a0, "xvsubdp" },
18337      { 0x1a4, "xvmaddmdp" },
18338      { 0x1ac, "xvcmpgtdp" },
18339      { 0x1b0, "xvcvdpsxws" },
18340      { 0x1b2, "xvrdpiz" },
18341      { 0x1b4, "xvredp" },
18342      { 0x1c0, "xvmuldp" },
18343      { 0x1c4, "xvmsubadp" },
18344      { 0x1cc, "xvcmpgedp" },
18345      { 0x1d0, "xvcvuxwdp" },
18346      { 0x1d2, "xvrdpip" },
18347      { 0x1d4, "xvtsqrtdp" },
18348      { 0x1d6, "xvrdpic" },
18349      { 0x1e0, "xvdivdp" },
18350      { 0x1e4, "xvmsubmdp" },
18351      { 0x1f0, "xvcvsxwdp" },
18352      { 0x1f2, "xvrdpim" },
18353      { 0x1f4, "xvtdivdp" },
18354      { 0x204, "xsnmaddasp" },
18355      { 0x208, "xxland" },
18356      { 0x212, "xscvdpsp" },
18357      { 0x216, "xscvdpspn" },
18358      { 0x224, "xsnmaddmsp" },
18359      { 0x228, "xxlandc" },
18360      { 0x232, "xxrsp" },
18361      { 0x244, "xsnmsubasp" },
18362      { 0x248, "xxlor" },
18363      { 0x250, "xscvuxdsp" },
18364      { 0x264, "xsnmsubmsp" },
18365      { 0x268, "xxlxor" },
18366      { 0x270, "xscvsxdsp" },
18367      { 0x280, "xsmaxdp" },
18368      { 0x284, "xsnmaddadp" },
18369      { 0x288, "xxlnor" },
18370      { 0x290, "xscvdpuxds" },
18371      { 0x292, "xscvspdp" },
18372      { 0x296, "xscvspdpn" },
18373      { 0x2a0, "xsmindp" },
18374      { 0x2a4, "xsnmaddmdp" },
18375      { 0x2a8, "xxlorc" },
18376      { 0x2b0, "xscvdpsxds" },
18377      { 0x2b2, "xsabsdp" },
18378      { 0x2c0, "xscpsgndp" },
18379      { 0x2c4, "xsnmsubadp" },
18380      { 0x2c8, "xxlnand" },
18381      { 0x2d0, "xscvuxddp" },
18382      { 0x2d2, "xsnabsdp" },
18383      { 0x2e4, "xsnmsubmdp" },
18384      { 0x2e8, "xxleqv" },
18385      { 0x2f0, "xscvsxddp" },
18386      { 0x2f2, "xsnegdp" },
18387      { 0x300, "xvmaxsp" },
18388      { 0x304, "xvnmaddasp" },
18389      { 0x30c, "xvcmpeqsp." },
18390      { 0x310, "xvcvspuxds" },
18391      { 0x312, "xvcvdpsp" },
18392      { 0x320, "xvminsp" },
18393      { 0x324, "xvnmaddmsp" },
18394      { 0x32c, "xvcmpgtsp." },
18395      { 0x330, "xvcvspsxds" },
18396      { 0x332, "xvabssp" },
18397      { 0x340, "xvcpsgnsp" },
18398      { 0x344, "xvnmsubasp" },
18399      { 0x34c, "xvcmpgesp." },
18400      { 0x350, "xvcvuxdsp" },
18401      { 0x352, "xvnabssp" },
18402      { 0x364, "xvnmsubmsp" },
18403      { 0x370, "xvcvsxdsp" },
18404      { 0x372, "xvnegsp" },
18405      { 0x380, "xvmaxdp" },
18406      { 0x384, "xvnmaddadp" },
18407      { 0x38c, "xvcmpeqdp." },
18408      { 0x390, "xvcvdpuxds" },
18409      { 0x392, "xvcvspdp" },
18410      { 0x3a0, "xvmindp" },
18411      { 0x3a4, "xvnmaddmdp" },
18412      { 0x3ac, "xvcmpgtdp." },
18413      { 0x3b0, "xvcvdpsxds" },
18414      { 0x3b2, "xvabsdp" },
18415      { 0x3c0, "xvcpsgndp" },
18416      { 0x3c4, "xvnmsubadp" },
18417      { 0x3cc, "xvcmpgedp." },
18418      { 0x3d0, "xvcvuxddp" },
18419      { 0x3d2, "xvnabsdp" },
18420      { 0x3e4, "xvnmsubmdp" },
18421      { 0x3f0, "xvcvsxddp" },
18422      { 0x3f2, "xvnegdp" }
18423};
18424#define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all)
18425
18426
18427// ATTENTION: This search function assumes vsx_all array is sorted.
18428static Int findVSXextOpCode(UInt opcode)
18429{
18430   Int low, mid, high;
18431   low = 0;
18432   high = VSX_ALL_LEN - 1;
18433   while (low <= high) {
18434      mid = (low + high)/2;
18435      if (opcode < vsx_all[mid].opcode)
18436         high = mid - 1;
18437      else if (opcode > vsx_all[mid].opcode)
18438         low = mid + 1;
18439      else
18440         return mid;
18441   }
18442   return -1;
18443}
18444
18445
18446/* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
18447 * passed, and we then try to match it up with one of the VSX forms
18448 * below.
18449 */
18450static UInt get_VSX60_opc2(UInt opc2_full)
18451{
18452#define XX2_MASK 0x000003FE
18453#define XX3_1_MASK 0x000003FC
18454#define XX3_2_MASK 0x000001FC
18455#define XX3_3_MASK 0x0000007C
18456#define XX4_MASK 0x00000018
18457   Int ret;
18458   UInt vsxExtOpcode = 0;
18459
18460   if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
18461      vsxExtOpcode = vsx_all[ret].opcode;
18462   else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
18463      vsxExtOpcode = vsx_all[ret].opcode;
18464   else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
18465      vsxExtOpcode = vsx_all[ret].opcode;
18466   else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
18467      vsxExtOpcode = vsx_all[ret].opcode;
18468   else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
18469      vsxExtOpcode = vsx_all[ret].opcode;
18470
18471   return vsxExtOpcode;
18472}
18473
18474/*------------------------------------------------------------*/
18475/*--- Disassemble a single instruction                     ---*/
18476/*------------------------------------------------------------*/
18477
18478/* Disassemble a single instruction into IR.  The instruction
18479   is located in host memory at &guest_code[delta]. */
18480
18481static
18482DisResult disInstr_PPC_WRK (
18483             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
18484             Bool         resteerCisOk,
18485             void*        callback_opaque,
18486             Long         delta64,
18487             VexArchInfo* archinfo,
18488             VexAbiInfo*  abiinfo,
18489             Bool         sigill_diag
18490          )
18491{
18492   UChar     opc1;
18493   UInt      opc2;
18494   DisResult dres;
18495   UInt      theInstr;
18496   IRType    ty = mode64 ? Ity_I64 : Ity_I32;
18497   Bool      allow_F  = False;
18498   Bool      allow_V  = False;
18499   Bool      allow_FX = False;
18500   Bool      allow_GX = False;
18501   Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
18502   Bool      allow_DFP = False;
18503   Bool      allow_isa_2_07 = False;
18504   UInt      hwcaps = archinfo->hwcaps;
18505   Long      delta;
18506
18507   /* What insn variants are we supporting today? */
18508   if (mode64) {
18509      allow_F  = True;
18510      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
18511      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
18512      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
18513      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
18514      allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
18515      allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
18516   } else {
18517      allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
18518      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
18519      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
18520      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
18521      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
18522      allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
18523      allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
18524   }
18525
18526   /* The running delta */
18527   delta = (Long)mkSzAddr(ty, (ULong)delta64);
18528
18529   /* Set result defaults. */
18530   dres.whatNext    = Dis_Continue;
18531   dres.len         = 0;
18532   dres.continueAt  = 0;
18533   dres.jk_StopHere = Ijk_INVALID;
18534
18535   /* At least this is simple on PPC32: insns are all 4 bytes long, and
18536      4-aligned.  So just fish the whole thing out of memory right now
18537      and have done. */
18538   theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) );
18539
18540   if (0) vex_printf("insn: 0x%x\n", theInstr);
18541
18542   DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
18543
18544   /* Spot "Special" instructions (see comment at top of file). */
18545   {
18546      UChar* code = (UChar*)(guest_code + delta);
18547      /* Spot the 16-byte preamble:
18548         32-bit mode:
18549            5400183E  rlwinm 0,0,3,0,31
18550            5400683E  rlwinm 0,0,13,0,31
18551            5400E83E  rlwinm 0,0,29,0,31
18552            5400983E  rlwinm 0,0,19,0,31
18553         64-bit mode:
18554            78001800  rotldi 0,0,3
18555            78006800  rotldi 0,0,13
18556            7800E802  rotldi 0,0,61
18557            78009802  rotldi 0,0,51
18558      */
18559      UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
18560      UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
18561      UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
18562      UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
18563      if (getUIntBigendianly(code+ 0) == word1 &&
18564          getUIntBigendianly(code+ 4) == word2 &&
18565          getUIntBigendianly(code+ 8) == word3 &&
18566          getUIntBigendianly(code+12) == word4) {
18567         /* Got a "Special" instruction preamble.  Which one is it? */
18568         if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
18569            /* %R3 = client_request ( %R4 ) */
18570            DIP("r3 = client_request ( %%r4 )\n");
18571            delta += 20;
18572            putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
18573            dres.jk_StopHere = Ijk_ClientReq;
18574            dres.whatNext    = Dis_StopHere;
18575            goto decode_success;
18576         }
18577         else
18578         if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
18579            /* %R3 = guest_NRADDR */
18580            DIP("r3 = guest_NRADDR\n");
18581            delta += 20;
18582            dres.len = 20;
18583            putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
18584            goto decode_success;
18585         }
18586         else
18587         if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
18588            /*  branch-and-link-to-noredir %R11 */
18589            DIP("branch-and-link-to-noredir r11\n");
18590            delta += 20;
18591            putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
18592            putGST( PPC_GST_CIA, getIReg(11));
18593            dres.jk_StopHere = Ijk_NoRedir;
18594            dres.whatNext    = Dis_StopHere;
18595            goto decode_success;
18596         }
18597         else
18598         if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
18599            /* %R3 = guest_NRADDR_GPR2 */
18600            DIP("r3 = guest_NRADDR_GPR2\n");
18601            delta += 20;
18602            dres.len = 20;
18603            putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
18604            goto decode_success;
18605         }
18606         else
18607         if (getUIntBigendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
18608            DIP("IR injection\n");
18609
18610            vex_inject_ir(irsb, Iend_BE);
18611
18612            delta += 20;
18613            dres.len = 20;
18614
18615            // Invalidate the current insn. The reason is that the IRop we're
18616            // injecting here can change. In which case the translation has to
18617            // be redone. For ease of handling, we simply invalidate all the
18618            // time.
18619
18620            stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
18621            stmt(IRStmt_Put(OFFB_CMLEN,   mkSzImm(ty, 20)));
18622
18623            putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
18624            dres.whatNext    = Dis_StopHere;
18625            dres.jk_StopHere = Ijk_InvalICache;
18626            goto decode_success;
18627         }
18628         /* We don't know what it is.  Set opc1/opc2 so decode_failure
18629            can print the insn following the Special-insn preamble. */
18630         theInstr = getUIntBigendianly(code+16);
18631         opc1     = ifieldOPC(theInstr);
18632         opc2     = ifieldOPClo10(theInstr);
18633         goto decode_failure;
18634         /*NOTREACHED*/
18635      }
18636   }
18637
18638   opc1 = ifieldOPC(theInstr);
18639   opc2 = ifieldOPClo10(theInstr);
18640
18641   // Note: all 'reserved' bits must be cleared, else invalid
18642   switch (opc1) {
18643
18644   /* Integer Arithmetic Instructions */
18645   case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
18646   case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
18647      if (dis_int_arith( theInstr )) goto decode_success;
18648      goto decode_failure;
18649
18650   /* Integer Compare Instructions */
18651   case 0x0B: case 0x0A: // cmpi, cmpli
18652      if (dis_int_cmp( theInstr )) goto decode_success;
18653      goto decode_failure;
18654
18655   /* Integer Logical Instructions */
18656   case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
18657   case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
18658      if (dis_int_logic( theInstr )) goto decode_success;
18659      goto decode_failure;
18660
18661   /* Integer Rotate Instructions */
18662   case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
18663      if (dis_int_rot( theInstr )) goto decode_success;
18664      goto decode_failure;
18665
18666   /* 64bit Integer Rotate Instructions */
18667   case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
18668      if (!mode64) goto decode_failure;
18669      if (dis_int_rot( theInstr )) goto decode_success;
18670      goto decode_failure;
18671
18672   /* Integer Load Instructions */
18673   case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
18674   case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
18675   case 0x20: case 0x21:            // lwz,  lwzu
18676      if (dis_int_load( theInstr )) goto decode_success;
18677      goto decode_failure;
18678
18679   /* Integer Store Instructions */
18680   case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
18681   case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
18682      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
18683      goto decode_failure;
18684
18685   /* Integer Load and Store Multiple Instructions */
18686   case 0x2E: case 0x2F: // lmw, stmw
18687      if (dis_int_ldst_mult( theInstr )) goto decode_success;
18688      goto decode_failure;
18689
18690   /* Branch Instructions */
18691   case 0x12: case 0x10: // b, bc
18692      if (dis_branch(theInstr, abiinfo, &dres,
18693                               resteerOkFn, callback_opaque))
18694         goto decode_success;
18695      goto decode_failure;
18696
18697   /* System Linkage Instructions */
18698   case 0x11: // sc
18699      if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
18700      goto decode_failure;
18701
18702   /* Trap Instructions */
18703   case 0x02:    // tdi
18704      if (!mode64) goto decode_failure;
18705      if (dis_trapi(theInstr, &dres)) goto decode_success;
18706      goto decode_failure;
18707
18708   case 0x03:   // twi
18709      if (dis_trapi(theInstr, &dres)) goto decode_success;
18710      goto decode_failure;
18711
18712   /* Floating Point Load Instructions */
18713   case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
18714   case 0x33:                       // lfdu
18715      if (!allow_F) goto decode_noF;
18716      if (dis_fp_load( theInstr )) goto decode_success;
18717      goto decode_failure;
18718
18719   /* Floating Point Store Instructions */
18720   case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
18721   case 0x37:                       // stfdux
18722      if (!allow_F) goto decode_noF;
18723      if (dis_fp_store( theInstr )) goto decode_success;
18724      goto decode_failure;
18725
18726      /* Floating Point Load Double Pair Instructions */
18727   case 0x39: case 0x3D:
18728      if (!allow_F) goto decode_noF;
18729      if (dis_fp_pair( theInstr )) goto decode_success;
18730      goto decode_failure;
18731
18732   /* 128-bit Integer Load */
18733   case 0x38:  // lq
18734      if (dis_int_load( theInstr )) goto decode_success;
18735      goto decode_failure;
18736
18737   /* 64bit Integer Loads */
18738   case 0x3A:  // ld, ldu, lwa
18739      if (!mode64) goto decode_failure;
18740      if (dis_int_load( theInstr )) goto decode_success;
18741      goto decode_failure;
18742
18743   case 0x3B:
18744      if (!allow_F) goto decode_noF;
18745      opc2 = ifieldOPClo10(theInstr);
18746
18747      switch (opc2) {
18748         case 0x2:    // dadd - DFP Add
18749         case 0x202:  // dsub - DFP Subtract
18750         case 0x22:   // dmul - DFP Mult
18751         case 0x222:  // ddiv - DFP Divide
18752            if (!allow_DFP) goto decode_noDFP;
18753            if (dis_dfp_arith( theInstr ))
18754               goto decode_success;
18755         case 0x82:   // dcmpo, DFP comparison ordered instruction
18756         case 0x282:  // dcmpu, DFP comparison unordered instruction
18757            if (!allow_DFP)
18758               goto decode_failure;
18759            if (dis_dfp_compare( theInstr ) )
18760               goto decode_success;
18761            goto decode_failure;
18762         case 0x102: // dctdp  - DFP convert to DFP long
18763         case 0x302: // drsp   - DFP round to dfp short
18764         case 0x122: // dctfix - DFP convert to fixed
18765            if (!allow_DFP)
18766               goto decode_failure;
18767            if (dis_dfp_fmt_conv( theInstr ))
18768               goto decode_success;
18769            goto decode_failure;
18770         case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
18771            if (!allow_VX)
18772               goto decode_failure;
18773            if (dis_dfp_fmt_conv( theInstr ))
18774               goto decode_success;
18775            goto decode_failure;
18776         case 0x2A2: // dtstsf - DFP number of significant digits
18777            if (!allow_DFP)
18778               goto decode_failure;
18779            if (dis_dfp_significant_digits(theInstr))
18780               goto decode_success;
18781            goto decode_failure;
18782         case 0x142: // ddedpd   DFP Decode DPD to BCD
18783         case 0x342: // denbcd   DFP Encode BCD to DPD
18784            if (!allow_DFP)
18785               goto decode_failure;
18786            if (dis_dfp_bcd(theInstr))
18787               goto decode_success;
18788            goto decode_failure;
18789         case 0x162:  // dxex - Extract exponent
18790         case 0x362:  // diex - Insert exponent
18791            if (!allow_DFP)
18792               goto decode_failure;
18793            if (dis_dfp_extract_insert( theInstr ) )
18794               goto decode_success;
18795            goto decode_failure;
18796         case 0x3CE: // fcfidus (implemented as native insn)
18797            if (!allow_VX)
18798               goto decode_noVX;
18799            if (dis_fp_round( theInstr ))
18800               goto decode_success;
18801            goto decode_failure;
18802         case 0x34E: // fcfids
18803            if (dis_fp_round( theInstr ))
18804               goto decode_success;
18805            goto decode_failure;
18806      }
18807
18808      opc2 = ifieldOPClo9( theInstr );
18809      switch (opc2) {
18810      case 0x42: // dscli, DFP shift left
18811      case 0x62: // dscri, DFP shift right
18812         if (!allow_DFP)
18813            goto decode_failure;
18814         if (dis_dfp_shift( theInstr ))
18815            goto decode_success;
18816         goto decode_failure;
18817      case 0xc2:  // dtstdc, DFP test data class
18818      case 0xe2:  // dtstdg, DFP test data group
18819         if (!allow_DFP)
18820            goto decode_failure;
18821         if (dis_dfp_class_test( theInstr ))
18822            goto decode_success;
18823         goto decode_failure;
18824      }
18825
18826      opc2 = ifieldOPClo8( theInstr );
18827      switch (opc2) {
18828      case 0x3:   // dqua  - DFP Quantize
18829      case 0x23:  // drrnd - DFP Reround
18830      case 0x43:  // dquai - DFP Quantize immediate
18831         if (!allow_DFP)
18832            goto decode_failure;
18833         if (dis_dfp_quantize_sig_rrnd( theInstr ) )
18834            goto decode_success;
18835         goto decode_failure;
18836      case 0xA2: // dtstex - DFP Test exponent
18837         if (!allow_DFP)
18838            goto decode_failure;
18839         if (dis_dfp_exponent_test( theInstr ) )
18840            goto decode_success;
18841         goto decode_failure;
18842      case 0x63: // drintx - Round to an integer value
18843      case 0xE3: // drintn - Round to an integer value
18844         if (!allow_DFP)
18845            goto decode_failure;
18846         if (dis_dfp_round( theInstr ) ) {
18847            goto decode_success;
18848         }
18849         goto decode_failure;
18850      default:
18851         break;  /* fall through to next opc2 check */
18852      }
18853
18854      opc2 = IFIELD(theInstr, 1, 5);
18855      switch (opc2) {
18856      /* Floating Point Arith Instructions */
18857      case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
18858      case 0x19:                       // fmuls
18859         if (dis_fp_arith(theInstr)) goto decode_success;
18860         goto decode_failure;
18861      case 0x16:                       // fsqrts
18862         if (!allow_FX) goto decode_noFX;
18863         if (dis_fp_arith(theInstr)) goto decode_success;
18864         goto decode_failure;
18865      case 0x18:                       // fres
18866         if (!allow_GX) goto decode_noGX;
18867         if (dis_fp_arith(theInstr)) goto decode_success;
18868         goto decode_failure;
18869
18870      /* Floating Point Mult-Add Instructions */
18871      case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
18872      case 0x1F:                       // fnmadds
18873         if (dis_fp_multadd(theInstr)) goto decode_success;
18874         goto decode_failure;
18875
18876      case 0x1A:                       // frsqrtes
18877         if (!allow_GX) goto decode_noGX;
18878         if (dis_fp_arith(theInstr)) goto decode_success;
18879         goto decode_failure;
18880
18881      default:
18882         goto decode_failure;
18883      }
18884      break;
18885
18886   case 0x3C: // VSX instructions (except load/store)
18887   {
18888      // All of these VSX instructions use some VMX facilities, so
18889      // if allow_V is not set, we'll skip trying to decode.
18890      if (!allow_V) goto decode_noVX;
18891
18892      UInt vsxOpc2 = get_VSX60_opc2(opc2);
18893      /* The vsxOpc2 returned is the "normalized" value, representing the
18894       * instructions secondary opcode as taken from the standard secondary
18895       * opcode field [21:30] (IBM notatition), even if the actual field
18896       * is non-standard.  These normalized values are given in the opcode
18897       * appendices of the ISA 2.06 document.
18898       */
18899
18900      switch (vsxOpc2) {
18901         case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
18902         case 0x018: case 0x148: // xxsel, xxspltw
18903            if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
18904            goto decode_failure;
18905         case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
18906         case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc
18907         case 0x2C8: case 0x2E8: // xxlnand, xxleqv
18908            if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
18909            goto decode_failure;
18910         case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
18911         case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
18912         case 0x280: case 0x2A0: // xsmaxdp, xsmindp
18913         case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
18914         case 0x034: case 0x014: // xsresp, xsrsqrtesp
18915         case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
18916         case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
18917         case 0x092: case 0x232: // xsrdpi, xsrsp
18918            if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
18919            goto decode_failure;
18920         case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
18921            if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
18922            goto decode_failure;
18923         case 0x0:   case 0x020: // xsaddsp, xssubsp
18924         case 0x080:             // xsadddp
18925         case 0x060: case 0x0E0: // xsdivsp, xsdivdp
18926         case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
18927         case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
18928         case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
18929         case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
18930         case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
18931         case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
18932         case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
18933         case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
18934         case 0x040: case 0x0C0: // xsmulsp, xsmuldp
18935         case 0x0A0:             // xssubdp
18936         case 0x016: case 0x096: // xssqrtsp,xssqrtdp
18937         case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
18938            if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
18939            goto decode_failure;
18940         case 0x180: // xvadddp
18941         case 0x1E0: // xvdivdp
18942         case 0x1C0: // xvmuldp
18943         case 0x1A0: // xvsubdp
18944         case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
18945         case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
18946         case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
18947         case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
18948         case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
18949         case 0x196: // xvsqrtdp
18950            if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
18951            goto decode_failure;
18952         case 0x100: // xvaddsp
18953         case 0x160: // xvdivsp
18954         case 0x140: // xvmulsp
18955         case 0x120: // xvsubsp
18956         case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
18957         case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
18958         case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
18959         case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
18960         case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
18961         case 0x116: // xvsqrtsp
18962            if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
18963            goto decode_failure;
18964
18965         case 0x250:             // xscvuxdsp
18966         case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
18967         case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
18968         case 0x090: // xscvdpuxws
18969            // The above VSX conversion instructions employ some ISA 2.06
18970            // floating point conversion instructions under the covers,
18971            // so if allow_VX (which means "supports ISA 2.06") is not set,
18972            // we'll skip the decode.
18973            if (!allow_VX) goto decode_noVX;
18974            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
18975            goto decode_failure;
18976
18977         case 0x2B0: // xscvdpsxds
18978         case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
18979         case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
18980         case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
18981         case 0x212: case 0x216: // xscvdpsp, xscvdpspn
18982         case 0x292: case 0x296: // xscvspdp, xscvspdpn
18983         case 0x312: // xvcvdpsp
18984         case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
18985         case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
18986         case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
18987         case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
18988         case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
18989         case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
18990            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
18991            goto decode_failure;
18992
18993         case 0x18C: case 0x38C: // xvcmpeqdp[.]
18994         case 0x10C: case 0x30C: // xvcmpeqsp[.]
18995         case 0x14C: case 0x34C: // xvcmpgesp[.]
18996         case 0x12C: case 0x32C: // xvcmpgtsp[.]
18997         case 0x1CC: case 0x3CC: // xvcmpgedp[.]
18998         case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
18999             if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
19000             goto decode_failure;
19001
19002         case 0x134:  // xvresp
19003         case 0x1B4:  // xvredp
19004         case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
19005         case 0x380: case 0x3A0: // xvmaxdp, xvmindp
19006         case 0x300: case 0x320: // xvmaxsp, xvminsp
19007         case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
19008         case 0x3B2: case 0x332: // xvabsdp, xvabssp
19009         case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
19010         case 0x192: case 0x1D6: // xvrdpi, xvrdpic
19011         case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
19012         case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
19013         case 0x112: case 0x156: // xvrspi, xvrspic
19014         case 0x172: case 0x152: // xvrspim, xvrspip
19015         case 0x132: // xvrspiz
19016            if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
19017            goto decode_failure;
19018
19019         default:
19020            goto decode_failure;
19021      }
19022      break;
19023   }
19024
19025   /* 64bit Integer Stores */
19026   case 0x3E:  // std, stdu, stq
19027      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19028      goto decode_failure;
19029
19030   case 0x3F:
19031      if (!allow_F) goto decode_noF;
19032      /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
19033         so we can simply fall through the first switch statement */
19034
19035      opc2 = IFIELD(theInstr, 1, 5);
19036      switch (opc2) {
19037      /* Floating Point Arith Instructions */
19038      case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
19039      case 0x19:                       // fmul
19040         if (dis_fp_arith(theInstr)) goto decode_success;
19041         goto decode_failure;
19042      case 0x16:                       // fsqrt
19043         if (!allow_FX) goto decode_noFX;
19044         if (dis_fp_arith(theInstr)) goto decode_success;
19045         goto decode_failure;
19046      case 0x17: case 0x1A:            // fsel, frsqrte
19047         if (!allow_GX) goto decode_noGX;
19048         if (dis_fp_arith(theInstr)) goto decode_success;
19049         goto decode_failure;
19050
19051      /* Floating Point Mult-Add Instructions */
19052      case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
19053      case 0x1F:                       // fnmadd
19054         if (dis_fp_multadd(theInstr)) goto decode_success;
19055         goto decode_failure;
19056
19057      case 0x18:                       // fre
19058         if (!allow_GX) goto decode_noGX;
19059         if (dis_fp_arith(theInstr)) goto decode_success;
19060         goto decode_failure;
19061
19062      default:
19063         break; // Fall through
19064      }
19065
19066      opc2 = IFIELD(theInstr, 1, 10);
19067      switch (opc2) {
19068      /* 128-bit DFP instructions */
19069      case 0x2:    // daddq - DFP Add
19070      case 0x202:  // dsubq - DFP Subtract
19071      case 0x22:   // dmulq - DFP Mult
19072      case 0x222:  // ddivq - DFP Divide
19073         if (!allow_DFP) goto decode_noDFP;
19074         if (dis_dfp_arithq( theInstr ))
19075            goto decode_success;
19076         goto decode_failure;
19077      case 0x162:  // dxexq - DFP Extract exponent
19078      case 0x362:  // diexq - DFP Insert exponent
19079         if (!allow_DFP)
19080            goto decode_failure;
19081         if (dis_dfp_extract_insertq( theInstr ))
19082            goto decode_success;
19083         goto decode_failure;
19084
19085      case 0x82:   // dcmpoq, DFP comparison ordered instruction
19086      case 0x282:  // dcmpuq, DFP comparison unordered instruction
19087         if (!allow_DFP)
19088            goto decode_failure;
19089         if (dis_dfp_compare( theInstr ) )
19090            goto decode_success;
19091         goto decode_failure;
19092
19093      case 0x102: // dctqpq  - DFP convert to DFP extended
19094      case 0x302: // drdpq   - DFP round to dfp Long
19095      case 0x122: // dctfixq - DFP convert to fixed quad
19096      case 0x322: // dcffixq - DFP convert from fixed quad
19097         if (!allow_DFP)
19098            goto decode_failure;
19099         if (dis_dfp_fmt_convq( theInstr ))
19100            goto decode_success;
19101         goto decode_failure;
19102
19103      case 0x2A2: // dtstsfq - DFP number of significant digits
19104         if (!allow_DFP)
19105            goto decode_failure;
19106         if (dis_dfp_significant_digits(theInstr))
19107            goto decode_success;
19108         goto decode_failure;
19109
19110      case 0x142: // ddedpdq   DFP Decode DPD to BCD
19111      case 0x342: // denbcdq   DFP Encode BCD to DPD
19112         if (!allow_DFP)
19113            goto decode_failure;
19114         if (dis_dfp_bcdq(theInstr))
19115            goto decode_success;
19116         goto decode_failure;
19117
19118      /* Floating Point Compare Instructions */
19119      case 0x000: // fcmpu
19120      case 0x020: // fcmpo
19121         if (dis_fp_cmp(theInstr)) goto decode_success;
19122         goto decode_failure;
19123
19124      case 0x080: // ftdiv
19125      case 0x0A0: // ftsqrt
19126         if (dis_fp_tests(theInstr)) goto decode_success;
19127         goto decode_failure;
19128
19129      /* Floating Point Rounding/Conversion Instructions */
19130      case 0x00C: // frsp
19131      case 0x00E: // fctiw
19132      case 0x00F: // fctiwz
19133      case 0x32E: // fctid
19134      case 0x32F: // fctidz
19135      case 0x34E: // fcfid
19136         if (dis_fp_round(theInstr)) goto decode_success;
19137         goto decode_failure;
19138      case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
19139      case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
19140         if (!allow_VX) goto decode_noVX;
19141         if (dis_fp_round(theInstr)) goto decode_success;
19142         goto decode_failure;
19143
19144      /* Power6 rounding stuff */
19145      case 0x1E8: // frim
19146      case 0x1C8: // frip
19147      case 0x188: // frin
19148      case 0x1A8: // friz
19149         /* A hack to check for P6 capability . . . */
19150         if ((allow_F && allow_V && allow_FX && allow_GX) &&
19151             (dis_fp_round(theInstr)))
19152            goto decode_success;
19153         goto decode_failure;
19154
19155      /* Floating Point Move Instructions */
19156      case 0x008: // fcpsgn
19157      case 0x028: // fneg
19158      case 0x048: // fmr
19159      case 0x088: // fnabs
19160      case 0x108: // fabs
19161         if (dis_fp_move( theInstr )) goto decode_success;
19162         goto decode_failure;
19163
19164      case 0x3c6: case 0x346:          // fmrgew, fmrgow
19165         if (dis_fp_merge( theInstr )) goto decode_success;
19166         goto decode_failure;
19167
19168      /* Floating Point Status/Control Register Instructions */
19169      case 0x026: // mtfsb1
19170      case 0x040: // mcrfs
19171      case 0x046: // mtfsb0
19172      case 0x086: // mtfsfi
19173      case 0x247: // mffs
19174      case 0x2C7: // mtfsf
19175         // Some of the above instructions need to know more about the
19176         // ISA level supported by the host.
19177         if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
19178         goto decode_failure;
19179
19180      default:
19181         break; // Fall through...
19182      }
19183
19184      opc2 = ifieldOPClo9( theInstr );
19185      switch (opc2) {
19186      case 0x42: // dscli, DFP shift left
19187      case 0x62: // dscri, DFP shift right
19188         if (!allow_DFP)
19189            goto decode_failure;
19190         if (dis_dfp_shiftq( theInstr ))
19191            goto decode_success;
19192         goto decode_failure;
19193      case 0xc2:  // dtstdc, DFP test data class
19194      case 0xe2:  // dtstdg, DFP test data group
19195         if (!allow_DFP)
19196            goto decode_failure;
19197         if (dis_dfp_class_test( theInstr ))
19198            goto decode_success;
19199         goto decode_failure;
19200      default:
19201         break;
19202      }
19203
19204      opc2 = ifieldOPClo8( theInstr );
19205      switch (opc2) {
19206      case 0x3:   // dquaq  - DFP Quantize Quad
19207      case 0x23:  // drrndq - DFP Reround Quad
19208      case 0x43:  // dquaiq - DFP Quantize immediate Quad
19209         if (!allow_DFP)
19210            goto decode_failure;
19211         if (dis_dfp_quantize_sig_rrndq( theInstr ))
19212            goto decode_success;
19213         goto decode_failure;
19214      case 0xA2: // dtstexq - DFP Test exponent Quad
19215         if (dis_dfp_exponent_test( theInstr ) )
19216            goto decode_success;
19217         goto decode_failure;
19218      case 0x63:  // drintxq - DFP Round to an integer value
19219      case 0xE3:  // drintnq - DFP Round to an integer value
19220         if (!allow_DFP)
19221            goto decode_failure;
19222         if (dis_dfp_roundq( theInstr ))
19223            goto decode_success;
19224         goto decode_failure;
19225
19226      default:
19227         goto decode_failure;
19228      }
19229      break;
19230
19231   case 0x13:
19232      switch (opc2) {
19233
19234      /* Condition Register Logical Instructions */
19235      case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
19236      case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
19237      case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
19238         if (dis_cond_logic( theInstr )) goto decode_success;
19239         goto decode_failure;
19240
19241      /* Branch Instructions */
19242      case 0x210: case 0x010: // bcctr, bclr
19243         if (dis_branch(theInstr, abiinfo, &dres,
19244                                  resteerOkFn, callback_opaque))
19245            goto decode_success;
19246         goto decode_failure;
19247
19248      /* Memory Synchronization Instructions */
19249      case 0x096: // isync
19250         if (dis_memsync( theInstr )) goto decode_success;
19251         goto decode_failure;
19252
19253      default:
19254         goto decode_failure;
19255      }
19256      break;
19257
19258
19259   case 0x1F:
19260
19261      /* For arith instns, bit10 is the OE flag (overflow enable) */
19262
19263      opc2 = IFIELD(theInstr, 1, 9);
19264      switch (opc2) {
19265      /* Integer Arithmetic Instructions */
19266      case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
19267      case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
19268      case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
19269      case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
19270      case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
19271      case 0x0C8: // subfze
19272         if (dis_int_arith( theInstr )) goto decode_success;
19273         goto decode_failure;
19274
19275      case 0x18B: // divweu (implemented as native insn)
19276      case 0x1AB: // divwe (implemented as native insn)
19277         if (!allow_VX) goto decode_noVX;
19278         if (dis_int_arith( theInstr )) goto decode_success;
19279         goto decode_failure;
19280
19281      /* 64bit Integer Arithmetic */
19282      case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
19283      case 0x1C9: case 0x1E9: // divdu, divd
19284         if (!mode64) goto decode_failure;
19285         if (dis_int_arith( theInstr )) goto decode_success;
19286         goto decode_failure;
19287
19288      case 0x1A9: //  divde (implemented as native insn)
19289      case 0x189: //  divdeuo (implemented as native insn)
19290         if (!allow_VX) goto decode_noVX;
19291         if (!mode64) goto decode_failure;
19292         if (dis_int_arith( theInstr )) goto decode_success;
19293         goto decode_failure;
19294
19295      case 0x1FC:                         // cmpb
19296         if (dis_int_logic( theInstr )) goto decode_success;
19297         goto decode_failure;
19298
19299      default:
19300         break;  // Fall through...
19301      }
19302
19303      /* All remaining opcodes use full 10 bits. */
19304
19305      opc2 = IFIELD(theInstr, 1, 10);
19306      switch (opc2) {
19307      /* Integer Compare Instructions  */
19308      case 0x000: case 0x020: // cmp, cmpl
19309         if (dis_int_cmp( theInstr )) goto decode_success;
19310         goto decode_failure;
19311
19312      /* Integer Logical Instructions */
19313      case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
19314      case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
19315      case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
19316      case 0x19C: case 0x13C:             // orc,  xor
19317      case 0x2DF: case 0x25F:            // mftgpr, mffgpr
19318         if (dis_int_logic( theInstr )) goto decode_success;
19319         goto decode_failure;
19320
19321      case 0x28E: case 0x2AE:             // tbegin., tend.
19322      case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
19323      case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
19324      case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
19325      if (dis_transactional_memory( theInstr,
19326                                    getUIntBigendianly( (UChar*)(&guest_code[delta + 4])),
19327                                    abiinfo, &dres,
19328                                    resteerOkFn, callback_opaque))
19329            goto decode_success;
19330         goto decode_failure;
19331
19332      /* 64bit Integer Logical Instructions */
19333      case 0x3DA: case 0x03A: // extsw, cntlzd
19334         if (!mode64) goto decode_failure;
19335         if (dis_int_logic( theInstr )) goto decode_success;
19336         goto decode_failure;
19337
19338         /* 64bit Integer Parity Instructions */
19339      case 0xba: // prtyd
19340         if (!mode64) goto decode_failure;
19341         if (dis_int_parity( theInstr )) goto decode_success;
19342         goto decode_failure;
19343
19344      case 0x9a: // prtyw
19345         if (dis_int_parity( theInstr )) goto decode_success;
19346         goto decode_failure;
19347
19348      /* Integer Shift Instructions */
19349      case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
19350      case 0x218:                         // srw
19351         if (dis_int_shift( theInstr )) goto decode_success;
19352         goto decode_failure;
19353
19354      /* 64bit Integer Shift Instructions */
19355      case 0x01B: case 0x31A: // sld, srad
19356      case 0x33A: case 0x33B: // sradi
19357      case 0x21B:             // srd
19358         if (!mode64) goto decode_failure;
19359         if (dis_int_shift( theInstr )) goto decode_success;
19360         goto decode_failure;
19361
19362      /* Integer Load Instructions */
19363      case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
19364      case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
19365      case 0x017: case 0x037:             // lwzx,  lwzux
19366         if (dis_int_load( theInstr )) goto decode_success;
19367         goto decode_failure;
19368
19369      /* 64bit Integer Load Instructions */
19370      case 0x035: case 0x015:             // ldux,  ldx
19371      case 0x175: case 0x155:             // lwaux, lwax
19372         if (!mode64) goto decode_failure;
19373         if (dis_int_load( theInstr )) goto decode_success;
19374         goto decode_failure;
19375
19376      /* Integer Store Instructions */
19377      case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
19378      case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
19379         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19380         goto decode_failure;
19381
19382      /* 64bit Integer Store Instructions */
19383      case 0x0B5: case 0x095: // stdux, stdx
19384         if (!mode64) goto decode_failure;
19385         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19386         goto decode_failure;
19387
19388      /* Integer Load and Store with Byte Reverse Instructions */
19389      case 0x214: case 0x294: // ldbrx, stdbrx
19390         if (!mode64) goto decode_failure;
19391         if (dis_int_ldst_rev( theInstr )) goto decode_success;
19392         goto decode_failure;
19393
19394      case 0x216: case 0x316: case 0x296:    // lwbrx, lhbrx, stwbrx
19395      case 0x396:                            // sthbrx
19396         if (dis_int_ldst_rev( theInstr )) goto decode_success;
19397         goto decode_failure;
19398
19399      /* Integer Load and Store String Instructions */
19400      case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
19401      case 0x295: {                       // stswx
19402         Bool stopHere = False;
19403         Bool ok = dis_int_ldst_str( theInstr, &stopHere );
19404         if (!ok) goto decode_failure;
19405         if (stopHere) {
19406            putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
19407            dres.jk_StopHere = Ijk_Boring;
19408            dres.whatNext    = Dis_StopHere;
19409         }
19410         goto decode_success;
19411      }
19412
19413      /* Memory Synchronization Instructions */
19414      case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
19415      case 0x256:                         // sync
19416         if (dis_memsync( theInstr )) goto decode_success;
19417         goto decode_failure;
19418
19419      /* 64bit Memory Synchronization Instructions */
19420      case 0x054: case 0x0D6: // ldarx, stdcx.
19421         if (!mode64) goto decode_failure;
19422         if (dis_memsync( theInstr )) goto decode_success;
19423         goto decode_failure;
19424
19425      case 0x114: case 0x0B6: // lqarx, stqcx.
19426         if (dis_memsync( theInstr )) goto decode_success;
19427         goto decode_failure;
19428
19429      /* Processor Control Instructions */
19430      case 0x33:  case 0x73: // mfvsrd, mfvsrwz
19431      case 0xB3:  case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
19432      case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
19433      case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
19434      case 0x220:                         // mcrxrt
19435         if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
19436         goto decode_failure;
19437
19438      /* Cache Management Instructions */
19439      case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
19440      case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
19441      case 0x3D6:                         // icbi
19442         if (dis_cache_manage( theInstr, &dres, archinfo ))
19443            goto decode_success;
19444         goto decode_failure;
19445
19446//zz       /* External Control Instructions */
19447//zz       case 0x136: case 0x1B6: // eciwx, ecowx
19448//zz          DIP("external control op => not implemented\n");
19449//zz          goto decode_failure;
19450
19451      /* Trap Instructions */
19452      case 0x004:             // tw
19453         if (dis_trap(theInstr, &dres)) goto decode_success;
19454         goto decode_failure;
19455
19456      case 0x044:             // td
19457         if (!mode64) goto decode_failure;
19458         if (dis_trap(theInstr, &dres)) goto decode_success;
19459         goto decode_failure;
19460
19461      /* Floating Point Load Instructions */
19462      case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
19463      case 0x277:                         // lfdux
19464         if (!allow_F) goto decode_noF;
19465         if (dis_fp_load( theInstr )) goto decode_success;
19466         goto decode_failure;
19467
19468      /* Floating Point Store Instructions */
19469      case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
19470      case 0x2F7:                         // stfdu, stfiwx
19471         if (!allow_F) goto decode_noF;
19472         if (dis_fp_store( theInstr )) goto decode_success;
19473         goto decode_failure;
19474      case 0x3D7:                         // stfiwx
19475         if (!allow_F) goto decode_noF;
19476         if (!allow_GX) goto decode_noGX;
19477         if (dis_fp_store( theInstr )) goto decode_success;
19478         goto decode_failure;
19479
19480         /* Floating Point Double Pair Indexed Instructions */
19481      case 0x317: // lfdpx (Power6)
19482      case 0x397: // stfdpx (Power6)
19483         if (!allow_F) goto decode_noF;
19484         if (dis_fp_pair(theInstr)) goto decode_success;
19485         goto decode_failure;
19486
19487      case 0x357:                         // lfiwax
19488         if (!allow_F) goto decode_noF;
19489         if (dis_fp_load( theInstr )) goto decode_success;
19490         goto decode_failure;
19491
19492      case 0x377:                         // lfiwzx
19493         if (!allow_F) goto decode_noF;
19494         if (dis_fp_load( theInstr )) goto decode_success;
19495         goto decode_failure;
19496
19497      /* AltiVec instructions */
19498
19499      /* AV Cache Control - Data streams */
19500      case 0x156: case 0x176: case 0x336: // dst, dstst, dss
19501         if (!allow_V) goto decode_noV;
19502         if (dis_av_datastream( theInstr )) goto decode_success;
19503         goto decode_failure;
19504
19505      /* AV Load */
19506      case 0x006: case 0x026:             // lvsl, lvsr
19507      case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
19508      case 0x067: case 0x167:             // lvx, lvxl
19509         if (!allow_V) goto decode_noV;
19510         if (dis_av_load( abiinfo, theInstr )) goto decode_success;
19511         goto decode_failure;
19512
19513      /* AV Store */
19514      case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
19515      case 0x0E7: case 0x1E7:             // stvx, stvxl
19516         if (!allow_V) goto decode_noV;
19517         if (dis_av_store( theInstr )) goto decode_success;
19518         goto decode_failure;
19519
19520      /* VSX Load */
19521      case 0x00C: // lxsiwzx
19522      case 0x04C: // lxsiwax
19523      case 0x20C: // lxsspx
19524      case 0x24C: // lxsdx
19525      case 0x34C: // lxvd2x
19526      case 0x14C: // lxvdsx
19527      case 0x30C: // lxvw4x
19528        // All of these VSX load instructions use some VMX facilities, so
19529        // if allow_V is not set, we'll skip trying to decode.
19530        if (!allow_V) goto decode_noV;
19531
19532    	  if (dis_vx_load( theInstr )) goto decode_success;
19533          goto decode_failure;
19534
19535      /* VSX Store */
19536      case 0x08C: // stxsiwx
19537      case 0x28C: // stxsspx
19538      case 0x2CC: // stxsdx
19539      case 0x3CC: // stxvd2x
19540      case 0x38C: // stxvw4x
19541        // All of these VSX store instructions use some VMX facilities, so
19542        // if allow_V is not set, we'll skip trying to decode.
19543        if (!allow_V) goto decode_noV;
19544
19545    	  if (dis_vx_store( theInstr )) goto decode_success;
19546    	  goto decode_failure;
19547
19548      /* Miscellaneous ISA 2.06 instructions */
19549      case 0x1FA: // popcntd
19550      case 0x17A: // popcntw
19551      case 0x7A:  // popcntb
19552    	  if (dis_int_logic( theInstr )) goto decode_success;
19553    	  goto decode_failure;
19554
19555      case 0x0FC: // bpermd
19556         if (!mode64) goto decode_failure;
19557         if (dis_int_logic( theInstr )) goto decode_success;
19558         goto decode_failure;
19559
19560      default:
19561         /* Deal with some other cases that we would otherwise have
19562            punted on. */
19563         /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
19564         /* only decode this insn when reserved bit 0 (31 in IBM's
19565            notation) is zero */
19566         if (IFIELD(theInstr, 0, 6) == (15<<1)) {
19567            UInt rT = ifieldRegDS( theInstr );
19568            UInt rA = ifieldRegA( theInstr );
19569            UInt rB = ifieldRegB( theInstr );
19570            UInt bi = ifieldRegC( theInstr );
19571            putIReg(
19572               rT,
19573               IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
19574                           rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
19575                                   : getIReg(rA),
19576                           getIReg(rB))
19577
19578            );
19579            DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
19580            goto decode_success;
19581         }
19582         goto decode_failure;
19583      }
19584      break;
19585
19586
19587   case 0x04:
19588      /* AltiVec instructions */
19589
19590      opc2 = IFIELD(theInstr, 0, 6);
19591      switch (opc2) {
19592      /* AV Mult-Add, Mult-Sum */
19593      case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
19594      case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
19595      case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
19596         if (!allow_V) goto decode_noV;
19597         if (dis_av_multarith( theInstr )) goto decode_success;
19598         goto decode_failure;
19599
19600      /* AV Permutations */
19601      case 0x2A:                       // vsel
19602      case 0x2B:                       // vperm
19603      case 0x2C:                       // vsldoi
19604         if (!allow_V) goto decode_noV;
19605         if (dis_av_permute( theInstr )) goto decode_success;
19606         goto decode_failure;
19607
19608      case 0x2D:                       // vpermxor
19609         if (!allow_isa_2_07) goto decode_noP8;
19610         if (dis_av_permute( theInstr )) goto decode_success;
19611         goto decode_failure;
19612
19613      /* AV Floating Point Mult-Add/Sub */
19614      case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
19615         if (!allow_V) goto decode_noV;
19616         if (dis_av_fp_arith( theInstr )) goto decode_success;
19617         goto decode_failure;
19618
19619      case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
19620      case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
19621         if (!allow_V) goto decode_noV;
19622         if (dis_av_quad( theInstr)) goto decode_success;
19623         goto decode_failure;
19624
19625      default:
19626         break;  // Fall through...
19627      }
19628
19629      opc2 = IFIELD(theInstr, 0, 9);
19630      switch (opc2) {
19631      /* BCD arithmetic */
19632      case 0x1: case 0x41:             // bcdadd, bcdsub
19633         if (!allow_isa_2_07) goto decode_noP8;
19634         if (dis_av_bcd( theInstr )) goto decode_success;
19635         goto decode_failure;
19636
19637      default:
19638         break;  // Fall through...
19639      }
19640
19641      opc2 = IFIELD(theInstr, 0, 11);
19642      switch (opc2) {
19643      /* AV Arithmetic */
19644      case 0x180:                         // vaddcuw
19645      case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
19646      case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
19647      case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
19648      case 0x580:                         // vsubcuw
19649      case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
19650      case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
19651      case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
19652      case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
19653      case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
19654      case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
19655      case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
19656      case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
19657      case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
19658      case 0x008: case 0x048:             // vmuloub, vmulouh
19659      case 0x108: case 0x148:             // vmulosb, vmulosh
19660      case 0x208: case 0x248:             // vmuleub, vmuleuh
19661      case 0x308: case 0x348:             // vmulesb, vmulesh
19662      case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
19663      case 0x688: case 0x788:             // vsum2sws, vsumsws
19664         if (!allow_V) goto decode_noV;
19665         if (dis_av_arith( theInstr )) goto decode_success;
19666         goto decode_failure;
19667
19668      case 0x088: case 0x089:             // vmulouw, vmuluwm
19669      case 0x0C0: case 0x0C2:             // vaddudm, vmaxud
19670      case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
19671      case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
19672      case 0x4C0:                         // vsubudm
19673         if (!allow_isa_2_07) goto decode_noP8;
19674         if (dis_av_arith( theInstr )) goto decode_success;
19675         goto decode_failure;
19676
19677      /* AV Polynomial Vector Multiply Add */
19678      case 0x408: case 0x448:            // vpmsumb, vpmsumd
19679      case 0x488: case 0x4C8:            // vpmsumw, vpmsumh
19680         if (!allow_isa_2_07) goto decode_noP8;
19681         if (dis_av_polymultarith( theInstr )) goto decode_success;
19682         goto decode_failure;
19683
19684      /* AV Rotate, Shift */
19685      case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
19686      case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
19687      case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
19688      case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
19689      case 0x1C4: case 0x2C4:             // vsl, vsr
19690      case 0x40C: case 0x44C:             // vslo, vsro
19691         if (!allow_V) goto decode_noV;
19692         if (dis_av_shift( theInstr )) goto decode_success;
19693         goto decode_failure;
19694
19695      case 0x0C4:                         // vrld
19696      case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
19697          if (!allow_isa_2_07) goto decode_noP8;
19698          if (dis_av_shift( theInstr )) goto decode_success;
19699          goto decode_failure;
19700
19701      /* AV Logic */
19702      case 0x404: case 0x444: case 0x484: // vand, vandc, vor
19703      case 0x4C4: case 0x504:             // vxor, vnor
19704         if (!allow_V) goto decode_noV;
19705         if (dis_av_logic( theInstr )) goto decode_success;
19706         goto decode_failure;
19707
19708      case 0x544:                         // vorc
19709      case 0x584: case 0x684:             // vnand, veqv
19710         if (!allow_isa_2_07) goto decode_noP8;
19711         if (dis_av_logic( theInstr )) goto decode_success;
19712         goto decode_failure;
19713
19714      /* AV Processor Control */
19715      case 0x604: case 0x644:             // mfvscr, mtvscr
19716         if (!allow_V) goto decode_noV;
19717         if (dis_av_procctl( theInstr )) goto decode_success;
19718         goto decode_failure;
19719
19720      /* AV Floating Point Arithmetic */
19721      case 0x00A: case 0x04A:             // vaddfp, vsubfp
19722      case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
19723      case 0x1CA:                         // vlogefp
19724      case 0x40A: case 0x44A:             // vmaxfp, vminfp
19725         if (!allow_V) goto decode_noV;
19726         if (dis_av_fp_arith( theInstr )) goto decode_success;
19727         goto decode_failure;
19728
19729      /* AV Floating Point Round/Convert */
19730      case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
19731      case 0x2CA:                         // vrfim
19732      case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
19733      case 0x3CA:                         // vctsxs
19734         if (!allow_V) goto decode_noV;
19735         if (dis_av_fp_convert( theInstr )) goto decode_success;
19736         goto decode_failure;
19737
19738      /* AV Merge, Splat */
19739      case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
19740      case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
19741      case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
19742      case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
19743         if (!allow_V) goto decode_noV;
19744         if (dis_av_permute( theInstr )) goto decode_success;
19745         goto decode_failure;
19746
19747      case 0x68C: case 0x78C:             // vmrgow, vmrgew
19748          if (!allow_isa_2_07) goto decode_noP8;
19749          if (dis_av_permute( theInstr )) goto decode_success;
19750          goto decode_failure;
19751
19752      /* AV Pack, Unpack */
19753      case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
19754      case 0x0CE:                         // vpkuwus
19755      case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
19756      case 0x1CE:                         // vpkswss
19757      case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
19758      case 0x2CE:                         // vupklsh
19759      case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
19760          if (!allow_V) goto decode_noV;
19761          if (dis_av_pack( theInstr )) goto decode_success;
19762          goto decode_failure;
19763
19764      case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
19765      case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
19766         if (!allow_isa_2_07) goto decode_noP8;
19767         if (dis_av_pack( theInstr )) goto decode_success;
19768         goto decode_failure;
19769
19770      case 0x508: case 0x509:             // vcipher, vcipherlast
19771      case 0x548: case 0x549:             // vncipher, vncipherlast
19772      case 0x5C8:                         // vsbox
19773         if (!allow_isa_2_07) goto decode_noP8;
19774         if (dis_av_cipher( theInstr )) goto decode_success;
19775         goto decode_failure;
19776
19777      case 0x6C2: case 0x682:             // vshasigmaw, vshasigmad
19778         if (!allow_isa_2_07) goto decode_noP8;
19779         if (dis_av_hash( theInstr )) goto decode_success;
19780         goto decode_failure;
19781
19782      case 0x702: case 0x742:             // vclzb, vclzh
19783      case 0x782: case 0x7c2:             // vclzw, vclzd
19784         if (!allow_isa_2_07) goto decode_noP8;
19785         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
19786         goto decode_failure;
19787
19788      case 0x703: case 0x743:             // vpopcntb, vpopcnth
19789      case 0x783: case 0x7c3:             // vpopcntw, vpopcntd
19790         if (!allow_isa_2_07) goto decode_noP8;
19791         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
19792         goto decode_failure;
19793
19794      case 0x50c:                         // vgbbd
19795         if (!allow_isa_2_07) goto decode_noP8;
19796         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
19797         goto decode_failure;
19798
19799      case 0x140: case 0x100:             // vaddcuq, vadduqm
19800      case 0x540: case 0x500:             // vsubcuq, vsubuqm
19801      case 0x54C:                         // vbpermq
19802         if (!allow_V) goto decode_noV;
19803         if (dis_av_quad( theInstr)) goto decode_success;
19804         goto decode_failure;
19805
19806      default:
19807         break;  // Fall through...
19808      }
19809
19810      opc2 = IFIELD(theInstr, 0, 10);
19811      switch (opc2) {
19812
19813      /* AV Compare */
19814      case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
19815      case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
19816      case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
19817         if (!allow_V) goto decode_noV;
19818         if (dis_av_cmp( theInstr )) goto decode_success;
19819         goto decode_failure;
19820
19821      case 0x0C7:                         // vcmpequd
19822      case 0x2C7:                         // vcmpgtud
19823      case 0x3C7:                         // vcmpgtsd
19824          if (!allow_isa_2_07) goto decode_noP8;
19825          if (dis_av_cmp( theInstr )) goto decode_success;
19826          goto decode_failure;
19827
19828      /* AV Floating Point Compare */
19829      case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
19830      case 0x3C6:                         // vcmpbfp
19831         if (!allow_V) goto decode_noV;
19832         if (dis_av_fp_cmp( theInstr )) goto decode_success;
19833         goto decode_failure;
19834
19835      default:
19836         goto decode_failure;
19837      }
19838      break;
19839
19840   default:
19841      goto decode_failure;
19842
19843   decode_noF:
19844      vassert(!allow_F);
19845      vex_printf("disInstr(ppc): declined to decode an FP insn.\n");
19846      goto decode_failure;
19847   decode_noV:
19848      vassert(!allow_V);
19849      vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n");
19850      goto decode_failure;
19851   decode_noVX:
19852      vassert(!allow_VX);
19853      vex_printf("disInstr(ppc): declined to decode a Power ISA 2.06 insn.\n");
19854      goto decode_failure;
19855   decode_noFX:
19856      vassert(!allow_FX);
19857      vex_printf("disInstr(ppc): "
19858                 "declined to decode a GeneralPurpose-Optional insn.\n");
19859      goto decode_failure;
19860   decode_noGX:
19861      vassert(!allow_GX);
19862      vex_printf("disInstr(ppc): "
19863                 "declined to decode a Graphics-Optional insn.\n");
19864      goto decode_failure;
19865   decode_noDFP:
19866      vassert(!allow_DFP);
19867      vex_printf("disInstr(ppc): "
19868               "declined to decode a Decimal Floating Point insn.\n");
19869      goto decode_failure;
19870   decode_noP8:
19871      vassert(!allow_isa_2_07);
19872      vex_printf("disInstr(ppc): "
19873               "declined to decode a Power 8 insn.\n");
19874      goto decode_failure;
19875
19876
19877   decode_failure:
19878   /* All decode failures end up here. */
19879   opc2 = (theInstr) & 0x7FF;
19880   if (sigill_diag) {
19881      vex_printf("disInstr(ppc): unhandled instruction: "
19882                 "0x%x\n", theInstr);
19883      vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
19884                 opc1, opc1, opc2, opc2);
19885   }
19886
19887   /* Tell the dispatcher that this insn cannot be decoded, and so has
19888      not been executed, and (is currently) the next to be executed.
19889      CIA should be up-to-date since it made so at the start of each
19890      insn, but nevertheless be paranoid and update it again right
19891      now. */
19892   putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
19893   dres.whatNext    = Dis_StopHere;
19894   dres.jk_StopHere = Ijk_NoDecode;
19895   dres.len         = 0;
19896   return dres;
19897
19898   } /* switch (opc) for the main (primary) opcode switch. */
19899
19900  decode_success:
19901   /* All decode successes end up here. */
19902   switch (dres.whatNext) {
19903      case Dis_Continue:
19904         putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
19905         break;
19906      case Dis_ResteerU:
19907      case Dis_ResteerC:
19908         putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
19909         break;
19910      case Dis_StopHere:
19911         break;
19912      default:
19913         vassert(0);
19914   }
19915   DIP("\n");
19916
19917   if (dres.len == 0) {
19918      dres.len = 4;
19919   } else {
19920      vassert(dres.len == 20);
19921   }
19922   return dres;
19923}
19924
19925#undef DIP
19926#undef DIS
19927
19928
19929/*------------------------------------------------------------*/
19930/*--- Top-level fn                                         ---*/
19931/*------------------------------------------------------------*/
19932
19933/* Disassemble a single instruction into IR.  The instruction
19934   is located in host memory at &guest_code[delta]. */
19935
19936DisResult disInstr_PPC ( IRSB*        irsb_IN,
19937                         Bool         (*resteerOkFn) ( void*, Addr64 ),
19938                         Bool         resteerCisOk,
19939                         void*        callback_opaque,
19940                         UChar*       guest_code_IN,
19941                         Long         delta,
19942                         Addr64       guest_IP,
19943                         VexArch      guest_arch,
19944                         VexArchInfo* archinfo,
19945                         VexAbiInfo*  abiinfo,
19946                         Bool         host_bigendian_IN,
19947                         Bool         sigill_diag_IN )
19948{
19949   IRType     ty;
19950   DisResult  dres;
19951   UInt       mask32, mask64;
19952   UInt hwcaps_guest = archinfo->hwcaps;
19953
19954   vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
19955
19956   /* global -- ick */
19957   mode64 = guest_arch == VexArchPPC64;
19958   ty = mode64 ? Ity_I64 : Ity_I32;
19959
19960   /* do some sanity checks */
19961   mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
19962            | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
19963            | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
19964
19965   mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
19966            | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
19967            | VEX_HWCAPS_PPC64_ISA2_07;
19968
19969   if (mode64) {
19970      vassert((hwcaps_guest & mask32) == 0);
19971   } else {
19972      vassert((hwcaps_guest & mask64) == 0);
19973   }
19974
19975   /* Set globals (see top of this file) */
19976   guest_code           = guest_code_IN;
19977   irsb                 = irsb_IN;
19978   host_is_bigendian    = host_bigendian_IN;
19979
19980   guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
19981   guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
19982
19983   dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
19984                             delta, archinfo, abiinfo, sigill_diag_IN );
19985
19986   return dres;
19987}
19988
19989
19990/*------------------------------------------------------------*/
19991/*--- Unused stuff                                         ---*/
19992/*------------------------------------------------------------*/
19993
19994///* A potentially more memcheck-friendly implementation of Clz32, with
19995//   the boundary case Clz32(0) = 32, which is what ppc requires. */
19996//
19997//static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
19998//{
19999//   /* Welcome ... to SSA R Us. */
20000//   IRTemp n1  = newTemp(Ity_I32);
20001//   IRTemp n2  = newTemp(Ity_I32);
20002//   IRTemp n3  = newTemp(Ity_I32);
20003//   IRTemp n4  = newTemp(Ity_I32);
20004//   IRTemp n5  = newTemp(Ity_I32);
20005//   IRTemp n6  = newTemp(Ity_I32);
20006//   IRTemp n7  = newTemp(Ity_I32);
20007//   IRTemp n8  = newTemp(Ity_I32);
20008//   IRTemp n9  = newTemp(Ity_I32);
20009//   IRTemp n10 = newTemp(Ity_I32);
20010//   IRTemp n11 = newTemp(Ity_I32);
20011//   IRTemp n12 = newTemp(Ity_I32);
20012//
20013//   /* First, propagate the most significant 1-bit into all lower
20014//      positions in the word. */
20015//   /* unsigned int clz ( unsigned int n )
20016//      {
20017//         n |= (n >> 1);
20018//         n |= (n >> 2);
20019//         n |= (n >> 4);
20020//         n |= (n >> 8);
20021//         n |= (n >> 16);
20022//         return bitcount(~n);
20023//      }
20024//   */
20025//   assign(n1, mkexpr(arg));
20026//   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
20027//   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
20028//   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
20029//   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
20030//   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
20031//   /* This gives a word of the form 0---01---1.  Now invert it, giving
20032//      a word of the form 1---10---0, then do a population-count idiom
20033//      (to count the 1s, which is the number of leading zeroes, or 32
20034//      if the original word was 0. */
20035//   assign(n7, unop(Iop_Not32, mkexpr(n6)));
20036//
20037//   /* unsigned int bitcount ( unsigned int n )
20038//      {
20039//         n = n - ((n >> 1) & 0x55555555);
20040//         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
20041//         n = (n + (n >> 4)) & 0x0F0F0F0F;
20042//         n = n + (n >> 8);
20043//         n = (n + (n >> 16)) & 0x3F;
20044//         return n;
20045//      }
20046//   */
20047//   assign(n8,
20048//          binop(Iop_Sub32,
20049//                mkexpr(n7),
20050//                binop(Iop_And32,
20051//                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
20052//                      mkU32(0x55555555))));
20053//   assign(n9,
20054//          binop(Iop_Add32,
20055//                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
20056//                binop(Iop_And32,
20057//                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
20058//                      mkU32(0x33333333))));
20059//   assign(n10,
20060//          binop(Iop_And32,
20061//                binop(Iop_Add32,
20062//                      mkexpr(n9),
20063//                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
20064//                mkU32(0x0F0F0F0F)));
20065//   assign(n11,
20066//          binop(Iop_Add32,
20067//                mkexpr(n10),
20068//                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
20069//   assign(n12,
20070//          binop(Iop_Add32,
20071//                mkexpr(n11),
20072//                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
20073//   return
20074//      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
20075//}
20076
20077/*--------------------------------------------------------------------*/
20078/*--- end                                         guest_ppc_toIR.c ---*/
20079/*--------------------------------------------------------------------*/
20080