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