]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/guest_ppc_toIR.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / VEX / priv / guest_ppc_toIR.c
1
2
3 /*--------------------------------------------------------------------*/
4 /*--- begin                                       guest_ppc_toIR.c ---*/
5 /*--------------------------------------------------------------------*/
6
7 /*
8    This file is part of Valgrind, a dynamic binary instrumentation
9    framework.
10
11    Copyright (C) 2004-2010 OpenWorks LLP
12       info@open-works.net
13
14    This program is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License as
16    published by the Free Software Foundation; either version 2 of the
17    License, or (at your option) any later version.
18
19    This program is distributed in the hope that it will be useful, but
20    WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22    General Public License for more details.
23
24    You should have received a copy of the GNU General Public License
25    along with this program; if not, write to the Free Software
26    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27    02110-1301, USA.
28
29    The GNU General Public License is contained in the file COPYING.
30
31    Neither the names of the U.S. Department of Energy nor the
32    University of California nor the names of its contributors may be
33    used to endorse or promote products derived from this software
34    without prior written permission.
35 */
36
37 /* TODO 18/Nov/05:
38
39    Spot rld... cases which are simply left/right shifts and emit
40    Shl64/Shr64 accordingly.
41
42    Altivec
43    - datastream insns
44    - lvxl,stvxl: load/store with 'least recently used' hint
45    - vexptefp, vlogefp
46
47    LIMITATIONS:
48
49    Various, including:
50
51    - Some invalid forms of lswi and lswx are accepted when they should
52      not be.
53
54    - Floating Point:
55      - All exceptions disabled in FPSCR
56      - condition codes not set in FPSCR
57
58    - Altivec floating point:
59      - vmaddfp, vnmsubfp
60        Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
61        system default of Non-Java mode, we get some small errors
62        (lowest bit only).
63        This is because Non-Java mode brutally hacks denormalised results
64        to zero, whereas we keep maximum accuracy.  However, using
65        Non-Java mode would give us more inaccuracy, as our intermediate
66        results would then be zeroed, too.
67
68    - AbiHints for the stack red zone are only emitted for
69        unconditional calls and returns (bl, blr).  They should also be
70        emitted for conditional calls and returns, but we don't have a 
71        way to express that right now.  Ah well.
72 */
73
74 /* "Special" instructions.
75
76    This instruction decoder can decode four special instructions
77    which mean nothing natively (are no-ops as far as regs/mem are
78    concerned) but have meaning for supporting Valgrind.  A special
79    instruction is flagged by a 16-byte preamble:
80
81       32-bit mode: 54001800 54006800 5400E800 54009800
82                    (rlwinm 0,0,3,0,0; rlwinm 0,0,13,0,0; 
83                     rlwinm 0,0,29,0,0; rlwinm 0,0,19,0,0)
84
85       64-bit mode: 78001800 78006800 7800E802 78009802
86                    (rotldi 0,0,3; rotldi 0,0,13;
87                     rotldi 0,0,61; rotldi 0,0,51)
88
89    Following that, one of the following 3 are allowed
90    (standard interpretation in parentheses):
91
92       7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
93       7C421378 (or 2,2,2)   %R3 = guest_NRADDR
94       7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11
95       7C842378 (or 4,4,4)   %R3 = guest_NRADDR_GPR2
96
97    Any other bytes following the 16-byte preamble are illegal and
98    constitute a failure in instruction decoding.  This all assumes
99    that the preamble will never occur except in specific code
100    fragments designed for Valgrind to catch.
101 */
102
103
104 /* Translates PPC32/64 code to IR. */
105
106 /* References
107
108 #define PPC32
109    "PowerPC Microprocessor Family:
110     The Programming Environments Manual for 32-Bit Microprocessors"
111     02/21/2000
112     http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
113
114 #define PPC64
115    "PowerPC Microprocessor Family:
116     Programming Environments Manual for 64-Bit Microprocessors"
117     06/10/2003
118    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
119
120 #define AV
121    "PowerPC Microprocessor Family:
122     AltiVec(TM) Technology Programming Environments Manual"
123     07/10/2003
124    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
125 */
126
127 #include "libvex_basictypes.h"
128 #include "libvex_ir.h"
129 #include "libvex.h"
130 #include "libvex_guest_ppc32.h"
131 #include "libvex_guest_ppc64.h"
132
133 #include "main_util.h"
134 #include "main_globals.h"
135 #include "guest_generic_bb_to_IR.h"
136 #include "guest_ppc_defs.h"
137
138
139 /*------------------------------------------------------------*/
140 /*--- Globals                                              ---*/
141 /*------------------------------------------------------------*/
142
143 /* These are set at the start of the translation of an insn, right
144    down in disInstr_PPC, so that we don't have to pass them around
145    endlessly.  They are all constant during the translation of any
146    given insn. */
147
148 /* We need to know this to do sub-register accesses correctly. */
149 static Bool host_is_bigendian;
150
151 /* Pointer to the guest code area. */
152 static UChar* guest_code;
153
154 /* The guest address corresponding to guest_code[0]. */
155 static Addr64 guest_CIA_bbstart;
156
157 /* The guest address for the instruction currently being
158    translated. */
159 static Addr64 guest_CIA_curr_instr;
160
161 /* The IRSB* into which we're generating code. */
162 static IRSB* irsb;
163
164 /* Is our guest binary 32 or 64bit?  Set at each call to
165    disInstr_PPC below. */
166 static Bool mode64 = False;
167
168 // Given a pointer to a function as obtained by "& functionname" in C,
169 // produce a pointer to the actual entry point for the function.  For
170 // most platforms it's the identity function.  Unfortunately, on
171 // ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and
172 // ppc64-aix5.
173 static void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f )
174 {
175    if (vbi->host_ppc_calls_use_fndescrs) {
176       /* f is a pointer to a 3-word function descriptor, of which the
177          first word is the entry address. */
178       /* note, this is correct even with cross-jitting, since this is
179          purely a host issue, not a guest one. */
180       HWord* fdescr = (HWord*)f;
181       return (void*)(fdescr[0]);
182    } else {
183       /* Simple; "& f" points directly at the code for f. */
184       return f;
185    }
186 }
187
188
189 /*------------------------------------------------------------*/
190 /*--- Debugging output                                     ---*/
191 /*------------------------------------------------------------*/
192
193 #define DIP(format, args...)           \
194    if (vex_traceflags & VEX_TRACE_FE)  \
195       vex_printf(format, ## args)
196
197 #define DIS(buf, format, args...)      \
198    if (vex_traceflags & VEX_TRACE_FE)  \
199       vex_sprintf(buf, format, ## args)
200
201
202 /*------------------------------------------------------------*/
203 /*--- Offsets of various parts of the ppc32/64 guest state ---*/
204 /*------------------------------------------------------------*/
205
206 #define offsetofPPCGuestState(_x) \
207    (mode64 ? offsetof(VexGuestPPC64State, _x) : \
208              offsetof(VexGuestPPC32State, _x))
209
210 #define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
211 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
212 #define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
213 #define OFFB_LR          offsetofPPCGuestState(guest_LR)
214 #define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
215 #define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
216 #define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
217 #define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
218 #define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
219 #define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
220 #define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
221 #define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
222 #define OFFB_EMWARN      offsetofPPCGuestState(guest_EMWARN)
223 #define OFFB_TISTART     offsetofPPCGuestState(guest_TISTART)
224 #define OFFB_TILEN       offsetofPPCGuestState(guest_TILEN)
225 #define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
226 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
227
228
229 /*------------------------------------------------------------*/
230 /*--- Extract instruction fields                          --- */
231 /*------------------------------------------------------------*/
232
233 /* Extract field from insn, given idx (zero = lsb) and field length */
234 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
235
236 /* Extract primary opcode, instr[31:26] */
237 static UChar ifieldOPC( UInt instr ) {
238    return toUChar( IFIELD( instr, 26, 6 ) );
239 }
240
241 /* Extract 10-bit secondary opcode, instr[10:1] */
242 static UInt ifieldOPClo10 ( UInt instr) {
243    return IFIELD( instr, 1, 10 );
244 }
245
246 /* Extract 9-bit secondary opcode, instr[9:1] */
247 static UInt ifieldOPClo9 ( UInt instr) {
248    return IFIELD( instr, 1, 9 );
249 }
250
251 /* Extract 5-bit secondary opcode, instr[5:1] */
252 static UInt ifieldOPClo5 ( UInt instr) {
253    return IFIELD( instr, 1, 5 );
254 }
255
256 /* Extract RD (destination register) field, instr[25:21] */
257 static UChar ifieldRegDS( UInt instr ) {
258    return toUChar( IFIELD( instr, 21, 5 ) );
259 }
260
261 /* Extract XT (destination register) field, instr[0,25:21] */
262 static UChar ifieldRegXT ( UInt instr )
263 {
264   UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
265   UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
266   return (upper_bit << 5) | lower_bits;
267 }
268
269 /* Extract XS (store source register) field, instr[0,25:21] */
270 static inline UChar ifieldRegXS ( UInt instr )
271 {
272   return ifieldRegXT ( instr );
273 }
274
275 /* Extract RA (1st source register) field, instr[20:16] */
276 static UChar ifieldRegA ( UInt instr ) {
277    return toUChar( IFIELD( instr, 16, 5 ) );
278 }
279
280 /* Extract XA (1st source register) field, instr[2,20:16] */
281 static UChar ifieldRegXA ( UInt instr )
282 {
283   UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
284   UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
285   return (upper_bit << 5) | lower_bits;
286 }
287
288 /* Extract RB (2nd source register) field, instr[15:11] */
289 static UChar ifieldRegB ( UInt instr ) {
290    return toUChar( IFIELD( instr, 11, 5 ) );
291 }
292
293 /* Extract XB (2nd source register) field, instr[1,15:11] */
294 static UChar ifieldRegXB ( UInt instr )
295 {
296   UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
297   UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
298   return (upper_bit << 5) | lower_bits;
299 }
300
301 /* Extract RC (3rd source register) field, instr[10:6] */
302 static UChar ifieldRegC ( UInt instr ) {
303    return toUChar( IFIELD( instr, 6, 5 ) );
304 }
305
306 /* Extract bit 10, instr[10] */
307 static UChar ifieldBIT10 ( UInt instr ) {
308    return toUChar( IFIELD( instr, 10, 1 ) );
309 }
310
311 /* Extract 2nd lowest bit, instr[1] */
312 static UChar ifieldBIT1 ( UInt instr ) {
313    return toUChar( IFIELD( instr, 1, 1 ) );
314 }
315
316 /* Extract lowest bit, instr[0] */
317 static UChar ifieldBIT0 ( UInt instr ) {
318    return toUChar( instr & 0x1 );
319 }
320
321 /* Extract unsigned bottom half, instr[15:0] */
322 static UInt ifieldUIMM16 ( UInt instr ) {
323    return instr & 0xFFFF;
324 }
325
326 /* Extract unsigned bottom 26 bits, instr[25:0] */
327 static UInt ifieldUIMM26 ( UInt instr ) {
328    return instr & 0x3FFFFFF;
329 }
330
331 /* Extract DM field, instr[9:8] */
332 static UChar ifieldDM ( UInt instr ) {
333    return toUChar( IFIELD( instr, 8, 2 ) );
334 }
335
336 /* Extract SHW field, instr[9:8] */
337 static inline UChar ifieldSHW ( UInt instr )
338 {
339   return ifieldDM ( instr );
340 }
341
342 /*------------------------------------------------------------*/
343 /*--- Guest-state identifiers                              ---*/
344 /*------------------------------------------------------------*/
345
346 typedef enum {
347     PPC_GST_CIA,    // Current Instruction Address
348     PPC_GST_LR,     // Link Register
349     PPC_GST_CTR,    // Count Register
350     PPC_GST_XER,    // Overflow, carry flags, byte count
351     PPC_GST_CR,     // Condition Register
352     PPC_GST_FPSCR,  // Floating Point Status/Control Register
353     PPC_GST_VRSAVE, // Vector Save/Restore Register
354     PPC_GST_VSCR,   // Vector Status and Control Register
355     PPC_GST_EMWARN, // Emulation warnings
356     PPC_GST_TISTART,// For icbi: start of area to invalidate
357     PPC_GST_TILEN,  // For icbi: length of area to invalidate
358     PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
359     PPC_GST_SPRG3_RO, // SPRG3
360     PPC_GST_MAX
361 } PPC_GST;
362
363 #define MASK_FPSCR_RN   0x3
364 #define MASK_FPSCR_FPRF 0x1F000
365 #define MASK_VSCR_VALID 0x00010001
366
367
368 /*------------------------------------------------------------*/
369 /*---  FP Helpers                                          ---*/
370 /*------------------------------------------------------------*/
371
372 /* Produce the 32-bit pattern corresponding to the supplied
373    float. */
374 static UInt float_to_bits ( Float f )
375 {
376    union { UInt i; Float f; } u;
377    vassert(4 == sizeof(UInt));
378    vassert(4 == sizeof(Float));
379    vassert(4 == sizeof(u));
380    u.f = f;
381    return u.i;
382 }
383
384
385 /*------------------------------------------------------------*/
386 /*--- Misc Helpers                                         ---*/
387 /*------------------------------------------------------------*/
388
389 /* Generate mask with 1's from 'begin' through 'end',
390    wrapping if begin > end.
391    begin->end works from right to left, 0=lsb
392 */
393 static UInt MASK32( UInt begin, UInt end )
394 {
395    UInt m1, m2, mask;
396    vassert(begin < 32);
397    vassert(end < 32);
398    m1   = ((UInt)(-1)) << begin;
399    m2   = ((UInt)(-1)) << end << 1;
400    mask = m1 ^ m2;
401    if (begin > end) mask = ~mask;  // wrap mask
402    return mask;
403 }
404
405 /* ditto for 64bit mask */
406 static ULong MASK64( UInt begin, UInt end )
407 {
408    ULong m1, m2, mask;
409    vassert(begin < 64);
410    vassert(end < 64);
411    m1   = ((ULong)(-1)) << begin;
412    m2   = ((ULong)(-1)) << end << 1;
413    mask = m1 ^ m2;
414    if (begin > end) mask = ~mask;  // wrap mask
415    return mask;
416 }
417
418 static Addr64 nextInsnAddr( void )
419 {
420    return guest_CIA_curr_instr + 4;
421 }
422
423
424 /*------------------------------------------------------------*/
425 /*--- Helper bits and pieces for deconstructing the        ---*/
426 /*--- ppc32/64 insn stream.                                ---*/
427 /*------------------------------------------------------------*/
428
429 /* Add a statement to the list held by "irsb". */
430 static void stmt ( IRStmt* st )
431 {
432    addStmtToIRSB( irsb, st );
433 }
434
435 /* Generate a new temporary of the given type. */
436 static IRTemp newTemp ( IRType ty )
437 {
438    vassert(isPlausibleIRType(ty));
439    return newIRTemp( irsb->tyenv, ty );
440 }
441
442 /* Various simple conversions */
443
444 static UChar extend_s_5to8 ( UChar x )
445 {
446    return toUChar((((Int)x) << 27) >> 27);
447 }
448
449 static UInt extend_s_8to32( UChar x )
450 {
451    return (UInt)((((Int)x) << 24) >> 24);
452 }
453
454 static UInt extend_s_16to32 ( UInt x )
455 {
456    return (UInt)((((Int)x) << 16) >> 16);
457 }
458
459 static ULong extend_s_16to64 ( UInt x )
460 {
461    return (ULong)((((Long)x) << 48) >> 48);
462 }
463
464 static ULong extend_s_26to64 ( UInt x )
465 {
466    return (ULong)((((Long)x) << 38) >> 38);
467 }
468
469 static ULong extend_s_32to64 ( UInt x )
470 {
471    return (ULong)((((Long)x) << 32) >> 32);
472 }
473
474 /* Do a big-endian load of a 32-bit word, regardless of the endianness
475    of the underlying host. */
476 static UInt getUIntBigendianly ( UChar* p )
477 {
478    UInt w = 0;
479    w = (w << 8) | p[0];
480    w = (w << 8) | p[1];
481    w = (w << 8) | p[2];
482    w = (w << 8) | p[3];
483    return w;
484 }
485
486
487 /*------------------------------------------------------------*/
488 /*--- Helpers for constructing IR.                         ---*/
489 /*------------------------------------------------------------*/
490
491 static void assign ( IRTemp dst, IRExpr* e )
492 {
493    stmt( IRStmt_WrTmp(dst, e) );
494 }
495
496 /* This generates a normal (non store-conditional) store. */
497 static void storeBE ( IRExpr* addr, IRExpr* data )
498 {
499    IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
500    vassert(tyA == Ity_I32 || tyA == Ity_I64);
501    stmt( IRStmt_Store(Iend_BE, addr, data) );
502 }
503
504 static IRExpr* unop ( IROp op, IRExpr* a )
505 {
506    return IRExpr_Unop(op, a);
507 }
508
509 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
510 {
511    return IRExpr_Binop(op, a1, a2);
512 }
513
514 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
515 {
516    return IRExpr_Triop(op, a1, a2, a3);
517 }
518
519 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2, 
520                               IRExpr* a3, IRExpr* a4 )
521 {
522    return IRExpr_Qop(op, a1, a2, a3, a4);
523 }
524
525 static IRExpr* mkexpr ( IRTemp tmp )
526 {
527    return IRExpr_RdTmp(tmp);
528 }
529
530 static IRExpr* mkU8 ( UChar i )
531 {
532    return IRExpr_Const(IRConst_U8(i));
533 }
534
535 static IRExpr* mkU16 ( UInt i )
536 {
537    return IRExpr_Const(IRConst_U16(i));
538 }
539
540 static IRExpr* mkU32 ( UInt i )
541 {
542    return IRExpr_Const(IRConst_U32(i));
543 }
544
545 static IRExpr* mkU64 ( ULong i )
546 {
547    return IRExpr_Const(IRConst_U64(i));
548 }
549
550 static IRExpr* mkV128 ( UShort i )
551 {
552    vassert(i == 0 || i == 0xffff);
553    return IRExpr_Const(IRConst_V128(i));
554 }
555
556 /* This generates a normal (non load-linked) load. */
557 static IRExpr* loadBE ( IRType ty, IRExpr* addr )
558 {
559    return IRExpr_Load(Iend_BE, ty, addr);
560 }
561
562 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
563 {
564    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
565    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
566    return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1), 
567                                           unop(Iop_1Uto32, arg2)));
568 }
569
570 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
571 {
572    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
573    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
574    return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1), 
575                                            unop(Iop_1Uto32, arg2)));
576 }
577
578 /* expand V128_8Ux16 to 2x V128_16Ux8's */
579 static void expand8Ux16( IRExpr* vIn,
580                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
581 {
582    IRTemp ones8x16 = newTemp(Ity_V128);
583
584    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
585    vassert(vEvn && *vEvn == IRTemp_INVALID);
586    vassert(vOdd && *vOdd == IRTemp_INVALID);
587    *vEvn = newTemp(Ity_V128);
588    *vOdd = newTemp(Ity_V128);
589
590    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
591    assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
592    assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 
593                         binop(Iop_ShrV128, vIn, mkU8(8))) );
594 }
595
596 /* expand V128_8Sx16 to 2x V128_16Sx8's */
597 static void expand8Sx16( IRExpr* vIn,
598                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
599 {
600    IRTemp ones8x16 = newTemp(Ity_V128);
601
602    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
603    vassert(vEvn && *vEvn == IRTemp_INVALID);
604    vassert(vOdd && *vOdd == IRTemp_INVALID);
605    *vEvn = newTemp(Ity_V128);
606    *vOdd = newTemp(Ity_V128);
607
608    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
609    assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
610    assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 
611                         binop(Iop_ShrV128, vIn, mkU8(8))) );
612 }
613
614 /* expand V128_16Uto8 to 2x V128_32Ux4's */
615 static void expand16Ux8( IRExpr* vIn,
616                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
617 {
618    IRTemp ones16x8 = newTemp(Ity_V128);
619
620    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
621    vassert(vEvn && *vEvn == IRTemp_INVALID);
622    vassert(vOdd && *vOdd == IRTemp_INVALID);
623    *vEvn = newTemp(Ity_V128);
624    *vOdd = newTemp(Ity_V128);
625
626    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
627    assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
628    assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 
629                         binop(Iop_ShrV128, vIn, mkU8(16))) );
630 }
631
632 /* expand V128_16Sto8 to 2x V128_32Sx4's */
633 static void expand16Sx8( IRExpr* vIn,
634                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
635 {
636    IRTemp ones16x8 = newTemp(Ity_V128);
637
638    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
639    vassert(vEvn && *vEvn == IRTemp_INVALID);
640    vassert(vOdd && *vOdd == IRTemp_INVALID);
641    *vEvn = newTemp(Ity_V128);
642    *vOdd = newTemp(Ity_V128);
643
644    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
645    assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
646    assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 
647                        binop(Iop_ShrV128, vIn, mkU8(16))) );
648 }
649
650 /* break V128 to 4xI32's, then sign-extend to I64's */
651 static void breakV128to4x64S( IRExpr* t128,
652                               /*OUTs*/
653                               IRTemp* t3, IRTemp* t2,
654                               IRTemp* t1, IRTemp* t0 )
655 {
656    IRTemp hi64 = newTemp(Ity_I64);
657    IRTemp lo64 = newTemp(Ity_I64);
658
659    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
660    vassert(t0 && *t0 == IRTemp_INVALID);
661    vassert(t1 && *t1 == IRTemp_INVALID);
662    vassert(t2 && *t2 == IRTemp_INVALID);
663    vassert(t3 && *t3 == IRTemp_INVALID);
664    *t0 = newTemp(Ity_I64);
665    *t1 = newTemp(Ity_I64);
666    *t2 = newTemp(Ity_I64);
667    *t3 = newTemp(Ity_I64);
668
669    assign( hi64, unop(Iop_V128HIto64, t128) );
670    assign( lo64, unop(Iop_V128to64,   t128) );
671    assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
672    assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
673    assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
674    assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
675 }
676
677 /* break V128 to 4xI32's, then zero-extend to I64's */
678 static void breakV128to4x64U ( IRExpr* t128,
679                                /*OUTs*/
680                                IRTemp* t3, IRTemp* t2,
681                                IRTemp* t1, IRTemp* t0 )
682 {
683    IRTemp hi64 = newTemp(Ity_I64);
684    IRTemp lo64 = newTemp(Ity_I64);
685
686    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
687    vassert(t0 && *t0 == IRTemp_INVALID);
688    vassert(t1 && *t1 == IRTemp_INVALID);
689    vassert(t2 && *t2 == IRTemp_INVALID);
690    vassert(t3 && *t3 == IRTemp_INVALID);
691    *t0 = newTemp(Ity_I64);
692    *t1 = newTemp(Ity_I64);
693    *t2 = newTemp(Ity_I64);
694    *t3 = newTemp(Ity_I64);
695
696    assign( hi64, unop(Iop_V128HIto64, t128) );
697    assign( lo64, unop(Iop_V128to64,   t128) );
698    assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
699    assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
700    assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
701    assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
702 }
703
704 /* Signed saturating narrow 64S to 32 */
705 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
706 {
707    IRTemp hi32 = newTemp(Ity_I32);
708    IRTemp lo32 = newTemp(Ity_I32);
709
710    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
711
712    assign( hi32, unop(Iop_64HIto32, t64));
713    assign( lo32, unop(Iop_64to32,   t64));
714
715    return IRExpr_Mux0X(
716              /* if (hi32 == (lo32 >>s 31)) */
717              unop(Iop_1Uto8,
718                   binop(Iop_CmpEQ32, mkexpr(hi32),
719                         binop( Iop_Sar32, mkexpr(lo32), mkU8(31)))),
720              /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
721              binop(Iop_Add32, mkU32(0x7FFFFFFF),
722                    binop(Iop_Shr32, mkexpr(hi32), mkU8(31))),
723              /* then: within signed-32 range: lo half good enough */
724              mkexpr(lo32) );
725 }
726
727 /* Unsigned saturating narrow 64S to 32 */
728 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
729 {
730    IRTemp hi32 = newTemp(Ity_I32);
731    IRTemp lo32 = newTemp(Ity_I32);
732
733    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
734
735    assign( hi32, unop(Iop_64HIto32, t64));
736    assign( lo32, unop(Iop_64to32,   t64));
737
738    return IRExpr_Mux0X(
739             /* if (top 32 bits of t64 are 0) */
740             unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0))),
741             /* else: positive saturate -> 0xFFFFFFFF */
742             mkU32(0xFFFFFFFF),
743             /* then: within unsigned-32 range: lo half good enough */
744             mkexpr(lo32) );
745 }
746
747 /* Signed saturate narrow 64->32, combining to V128 */
748 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
749                                  IRExpr* t1, IRExpr* t0 )
750 {
751    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
752    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
753    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
754    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
755    return binop(Iop_64HLtoV128,
756                 binop(Iop_32HLto64,
757                       mkQNarrow64Sto32( t3 ),
758                       mkQNarrow64Sto32( t2 )),
759                 binop(Iop_32HLto64,
760                       mkQNarrow64Sto32( t1 ),
761                       mkQNarrow64Sto32( t0 )));
762 }
763
764 /* Unsigned saturate narrow 64->32, combining to V128 */
765 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
766                                  IRExpr* t1, IRExpr* t0 )
767 {
768    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
769    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
770    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
771    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
772    return binop(Iop_64HLtoV128,
773                 binop(Iop_32HLto64,
774                       mkQNarrow64Uto32( t3 ),
775                       mkQNarrow64Uto32( t2 )),
776                 binop(Iop_32HLto64,
777                       mkQNarrow64Uto32( t1 ),
778                       mkQNarrow64Uto32( t0 )));
779 }
780
781 /* Simulate irops Iop_MullOdd*, since we don't have them  */
782 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
783       binop(Iop_MullEven8Ux16, \
784             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
785             binop(Iop_ShrV128, expr_vB, mkU8(8)))
786
787 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
788       binop(Iop_MullEven8Sx16, \
789             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
790             binop(Iop_ShrV128, expr_vB, mkU8(8)))
791
792 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
793       binop(Iop_MullEven16Ux8, \
794             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
795             binop(Iop_ShrV128, expr_vB, mkU8(16)))
796
797 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
798       binop(Iop_MullEven16Sx8, \
799             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
800             binop(Iop_ShrV128, expr_vB, mkU8(16)))
801
802 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
803 {
804    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
805    return unop(Iop_32Sto64, unop(Iop_64to32, src));
806 }
807
808 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
809 {
810    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
811    return unop(Iop_32Uto64, unop(Iop_64to32, src));
812 }
813
814 static IROp mkSzOp ( IRType ty, IROp op8 )
815 {
816    Int adj;
817    vassert(ty == Ity_I8  || ty == Ity_I16 ||
818            ty == Ity_I32 || ty == Ity_I64);
819    vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
820            op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
821            op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
822            op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
823            op8 == Iop_Not8 );
824    adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
825    return adj + op8;
826 }
827
828 /* Make sure we get valid 32 and 64bit addresses */
829 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
830 {
831    vassert(ty == Ity_I32 || ty == Ity_I64);
832    return ( ty == Ity_I64 ?
833             (Addr64)addr :
834             (Addr64)extend_s_32to64( toUInt(addr) ) );
835 }
836
837 /* sz, ULong -> IRExpr */
838 static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
839 {
840    vassert(ty == Ity_I32 || ty == Ity_I64);
841    return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
842 }
843
844 /* sz, ULong -> IRConst */
845 static IRConst* mkSzConst ( IRType ty, ULong imm64 )
846 {
847    vassert(ty == Ity_I32 || ty == Ity_I64);
848    return ( ty == Ity_I64 ?
849             IRConst_U64(imm64) :
850             IRConst_U32((UInt)imm64) );
851 }
852
853 /* Sign extend imm16 -> IRExpr* */
854 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
855 {
856    vassert(ty == Ity_I32 || ty == Ity_I64);
857    return ( ty == Ity_I64 ?
858             mkU64(extend_s_16to64(imm16)) :
859             mkU32(extend_s_16to32(imm16)) );
860 }
861
862 /* Sign extend imm32 -> IRExpr* */
863 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
864 {
865    vassert(ty == Ity_I32 || ty == Ity_I64);
866    return ( ty == Ity_I64 ?
867             mkU64(extend_s_32to64(imm32)) :
868             mkU32(imm32) );
869 }
870
871 /* IR narrows I32/I64 -> I8/I16/I32 */
872 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
873 {
874    vassert(ty == Ity_I32 || ty == Ity_I64);
875    return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
876 }
877
878 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
879 {
880    vassert(ty == Ity_I32 || ty == Ity_I64);
881    return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
882 }
883
884 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
885 {
886    vassert(ty == Ity_I32 || ty == Ity_I64);
887    return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
888 }
889
890 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
891 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
892 {
893    IROp op;
894    vassert(ty == Ity_I32 || ty == Ity_I64);
895    if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
896    else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
897    return unop(op, src);
898 }
899
900 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
901 {
902    IROp op;
903    vassert(ty == Ity_I32 || ty == Ity_I64);
904    if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
905    else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
906    return unop(op, src);
907 }
908
909 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
910 {
911    vassert(ty == Ity_I32 || ty == Ity_I64);
912    if (ty == Ity_I32)
913       return src;
914    return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
915 }
916
917
918 static Int integerGuestRegOffset ( UInt archreg )
919 {
920    vassert(archreg < 32);
921    
922    // jrs: probably not necessary; only matters if we reference sub-parts
923    // of the ppc registers, but that isn't the case
924    // later: this might affect Altivec though?
925    vassert(host_is_bigendian);
926
927    switch (archreg) {
928    case  0: return offsetofPPCGuestState(guest_GPR0);
929    case  1: return offsetofPPCGuestState(guest_GPR1);
930    case  2: return offsetofPPCGuestState(guest_GPR2);
931    case  3: return offsetofPPCGuestState(guest_GPR3);
932    case  4: return offsetofPPCGuestState(guest_GPR4);
933    case  5: return offsetofPPCGuestState(guest_GPR5);
934    case  6: return offsetofPPCGuestState(guest_GPR6);
935    case  7: return offsetofPPCGuestState(guest_GPR7);
936    case  8: return offsetofPPCGuestState(guest_GPR8);
937    case  9: return offsetofPPCGuestState(guest_GPR9);
938    case 10: return offsetofPPCGuestState(guest_GPR10);
939    case 11: return offsetofPPCGuestState(guest_GPR11);
940    case 12: return offsetofPPCGuestState(guest_GPR12);
941    case 13: return offsetofPPCGuestState(guest_GPR13);
942    case 14: return offsetofPPCGuestState(guest_GPR14);
943    case 15: return offsetofPPCGuestState(guest_GPR15);
944    case 16: return offsetofPPCGuestState(guest_GPR16);
945    case 17: return offsetofPPCGuestState(guest_GPR17);
946    case 18: return offsetofPPCGuestState(guest_GPR18);
947    case 19: return offsetofPPCGuestState(guest_GPR19);
948    case 20: return offsetofPPCGuestState(guest_GPR20);
949    case 21: return offsetofPPCGuestState(guest_GPR21);
950    case 22: return offsetofPPCGuestState(guest_GPR22);
951    case 23: return offsetofPPCGuestState(guest_GPR23);
952    case 24: return offsetofPPCGuestState(guest_GPR24);
953    case 25: return offsetofPPCGuestState(guest_GPR25);
954    case 26: return offsetofPPCGuestState(guest_GPR26);
955    case 27: return offsetofPPCGuestState(guest_GPR27);
956    case 28: return offsetofPPCGuestState(guest_GPR28);
957    case 29: return offsetofPPCGuestState(guest_GPR29);
958    case 30: return offsetofPPCGuestState(guest_GPR30);
959    case 31: return offsetofPPCGuestState(guest_GPR31);
960    default: break;
961    }
962    vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
963 }
964
965 static IRExpr* getIReg ( UInt archreg )
966 {
967    IRType ty = mode64 ? Ity_I64 : Ity_I32;
968    vassert(archreg < 32);
969    return IRExpr_Get( integerGuestRegOffset(archreg), ty );
970 }
971
972 /* Ditto, but write to a reg instead. */
973 static void putIReg ( UInt archreg, IRExpr* e )
974 {
975    IRType ty = mode64 ? Ity_I64 : Ity_I32;
976    vassert(archreg < 32);
977    vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
978    stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
979 }
980
981
982 /* Floating point egisters are mapped to VSX registers[0..31]. */
983 static Int floatGuestRegOffset ( UInt archreg )
984 {
985    vassert(archreg < 32);
986    
987    switch (archreg) {
988    case  0: return offsetofPPCGuestState(guest_VSR0);
989    case  1: return offsetofPPCGuestState(guest_VSR1);
990    case  2: return offsetofPPCGuestState(guest_VSR2);
991    case  3: return offsetofPPCGuestState(guest_VSR3);
992    case  4: return offsetofPPCGuestState(guest_VSR4);
993    case  5: return offsetofPPCGuestState(guest_VSR5);
994    case  6: return offsetofPPCGuestState(guest_VSR6);
995    case  7: return offsetofPPCGuestState(guest_VSR7);
996    case  8: return offsetofPPCGuestState(guest_VSR8);
997    case  9: return offsetofPPCGuestState(guest_VSR9);
998    case 10: return offsetofPPCGuestState(guest_VSR10);
999    case 11: return offsetofPPCGuestState(guest_VSR11);
1000    case 12: return offsetofPPCGuestState(guest_VSR12);
1001    case 13: return offsetofPPCGuestState(guest_VSR13);
1002    case 14: return offsetofPPCGuestState(guest_VSR14);
1003    case 15: return offsetofPPCGuestState(guest_VSR15);
1004    case 16: return offsetofPPCGuestState(guest_VSR16);
1005    case 17: return offsetofPPCGuestState(guest_VSR17);
1006    case 18: return offsetofPPCGuestState(guest_VSR18);
1007    case 19: return offsetofPPCGuestState(guest_VSR19);
1008    case 20: return offsetofPPCGuestState(guest_VSR20);
1009    case 21: return offsetofPPCGuestState(guest_VSR21);
1010    case 22: return offsetofPPCGuestState(guest_VSR22);
1011    case 23: return offsetofPPCGuestState(guest_VSR23);
1012    case 24: return offsetofPPCGuestState(guest_VSR24);
1013    case 25: return offsetofPPCGuestState(guest_VSR25);
1014    case 26: return offsetofPPCGuestState(guest_VSR26);
1015    case 27: return offsetofPPCGuestState(guest_VSR27);
1016    case 28: return offsetofPPCGuestState(guest_VSR28);
1017    case 29: return offsetofPPCGuestState(guest_VSR29);
1018    case 30: return offsetofPPCGuestState(guest_VSR30);
1019    case 31: return offsetofPPCGuestState(guest_VSR31);
1020    default: break;
1021    }
1022    vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1023 }
1024
1025 static IRExpr* getFReg ( UInt archreg )
1026 {
1027    vassert(archreg < 32);
1028    return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1029 }
1030
1031 /* Ditto, but write to a reg instead. */
1032 static void putFReg ( UInt archreg, IRExpr* e )
1033 {
1034    vassert(archreg < 32);
1035    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1036    stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1037 }
1038
1039 static Int vsxGuestRegOffset ( UInt archreg )
1040 {
1041    vassert(archreg < 64);
1042    switch (archreg) {
1043    case  0: return offsetofPPCGuestState(guest_VSR0);
1044    case  1: return offsetofPPCGuestState(guest_VSR1);
1045    case  2: return offsetofPPCGuestState(guest_VSR2);
1046    case  3: return offsetofPPCGuestState(guest_VSR3);
1047    case  4: return offsetofPPCGuestState(guest_VSR4);
1048    case  5: return offsetofPPCGuestState(guest_VSR5);
1049    case  6: return offsetofPPCGuestState(guest_VSR6);
1050    case  7: return offsetofPPCGuestState(guest_VSR7);
1051    case  8: return offsetofPPCGuestState(guest_VSR8);
1052    case  9: return offsetofPPCGuestState(guest_VSR9);
1053    case 10: return offsetofPPCGuestState(guest_VSR10);
1054    case 11: return offsetofPPCGuestState(guest_VSR11);
1055    case 12: return offsetofPPCGuestState(guest_VSR12);
1056    case 13: return offsetofPPCGuestState(guest_VSR13);
1057    case 14: return offsetofPPCGuestState(guest_VSR14);
1058    case 15: return offsetofPPCGuestState(guest_VSR15);
1059    case 16: return offsetofPPCGuestState(guest_VSR16);
1060    case 17: return offsetofPPCGuestState(guest_VSR17);
1061    case 18: return offsetofPPCGuestState(guest_VSR18);
1062    case 19: return offsetofPPCGuestState(guest_VSR19);
1063    case 20: return offsetofPPCGuestState(guest_VSR20);
1064    case 21: return offsetofPPCGuestState(guest_VSR21);
1065    case 22: return offsetofPPCGuestState(guest_VSR22);
1066    case 23: return offsetofPPCGuestState(guest_VSR23);
1067    case 24: return offsetofPPCGuestState(guest_VSR24);
1068    case 25: return offsetofPPCGuestState(guest_VSR25);
1069    case 26: return offsetofPPCGuestState(guest_VSR26);
1070    case 27: return offsetofPPCGuestState(guest_VSR27);
1071    case 28: return offsetofPPCGuestState(guest_VSR28);
1072    case 29: return offsetofPPCGuestState(guest_VSR29);
1073    case 30: return offsetofPPCGuestState(guest_VSR30);
1074    case 31: return offsetofPPCGuestState(guest_VSR31);
1075    case 32: return offsetofPPCGuestState(guest_VSR32);
1076    case 33: return offsetofPPCGuestState(guest_VSR33);
1077    case 34: return offsetofPPCGuestState(guest_VSR34);
1078    case 35: return offsetofPPCGuestState(guest_VSR35);
1079    case 36: return offsetofPPCGuestState(guest_VSR36);
1080    case 37: return offsetofPPCGuestState(guest_VSR37);
1081    case 38: return offsetofPPCGuestState(guest_VSR38);
1082    case 39: return offsetofPPCGuestState(guest_VSR39);
1083    case 40: return offsetofPPCGuestState(guest_VSR40);
1084    case 41: return offsetofPPCGuestState(guest_VSR41);
1085    case 42: return offsetofPPCGuestState(guest_VSR42);
1086    case 43: return offsetofPPCGuestState(guest_VSR43);
1087    case 44: return offsetofPPCGuestState(guest_VSR44);
1088    case 45: return offsetofPPCGuestState(guest_VSR45);
1089    case 46: return offsetofPPCGuestState(guest_VSR46);
1090    case 47: return offsetofPPCGuestState(guest_VSR47);
1091    case 48: return offsetofPPCGuestState(guest_VSR48);
1092    case 49: return offsetofPPCGuestState(guest_VSR49);
1093    case 50: return offsetofPPCGuestState(guest_VSR50);
1094    case 51: return offsetofPPCGuestState(guest_VSR51);
1095    case 52: return offsetofPPCGuestState(guest_VSR52);
1096    case 53: return offsetofPPCGuestState(guest_VSR53);
1097    case 54: return offsetofPPCGuestState(guest_VSR54);
1098    case 55: return offsetofPPCGuestState(guest_VSR55);
1099    case 56: return offsetofPPCGuestState(guest_VSR56);
1100    case 57: return offsetofPPCGuestState(guest_VSR57);
1101    case 58: return offsetofPPCGuestState(guest_VSR58);
1102    case 59: return offsetofPPCGuestState(guest_VSR59);
1103    case 60: return offsetofPPCGuestState(guest_VSR60);
1104    case 61: return offsetofPPCGuestState(guest_VSR61);
1105    case 62: return offsetofPPCGuestState(guest_VSR62);
1106    case 63: return offsetofPPCGuestState(guest_VSR63);
1107    default: break;
1108    }
1109    vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1110 }
1111
1112 /* Vector registers are mapped to VSX registers[32..63]. */
1113 static Int vectorGuestRegOffset ( UInt archreg )
1114 {
1115    vassert(archreg < 32);
1116    
1117    switch (archreg) {
1118    case  0: return offsetofPPCGuestState(guest_VSR32);
1119    case  1: return offsetofPPCGuestState(guest_VSR33);
1120    case  2: return offsetofPPCGuestState(guest_VSR34);
1121    case  3: return offsetofPPCGuestState(guest_VSR35);
1122    case  4: return offsetofPPCGuestState(guest_VSR36);
1123    case  5: return offsetofPPCGuestState(guest_VSR37);
1124    case  6: return offsetofPPCGuestState(guest_VSR38);
1125    case  7: return offsetofPPCGuestState(guest_VSR39);
1126    case  8: return offsetofPPCGuestState(guest_VSR40);
1127    case  9: return offsetofPPCGuestState(guest_VSR41);
1128    case 10: return offsetofPPCGuestState(guest_VSR42);
1129    case 11: return offsetofPPCGuestState(guest_VSR43);
1130    case 12: return offsetofPPCGuestState(guest_VSR44);
1131    case 13: return offsetofPPCGuestState(guest_VSR45);
1132    case 14: return offsetofPPCGuestState(guest_VSR46);
1133    case 15: return offsetofPPCGuestState(guest_VSR47);
1134    case 16: return offsetofPPCGuestState(guest_VSR48);
1135    case 17: return offsetofPPCGuestState(guest_VSR49);
1136    case 18: return offsetofPPCGuestState(guest_VSR50);
1137    case 19: return offsetofPPCGuestState(guest_VSR51);
1138    case 20: return offsetofPPCGuestState(guest_VSR52);
1139    case 21: return offsetofPPCGuestState(guest_VSR53);
1140    case 22: return offsetofPPCGuestState(guest_VSR54);
1141    case 23: return offsetofPPCGuestState(guest_VSR55);
1142    case 24: return offsetofPPCGuestState(guest_VSR56);
1143    case 25: return offsetofPPCGuestState(guest_VSR57);
1144    case 26: return offsetofPPCGuestState(guest_VSR58);
1145    case 27: return offsetofPPCGuestState(guest_VSR59);
1146    case 28: return offsetofPPCGuestState(guest_VSR60);
1147    case 29: return offsetofPPCGuestState(guest_VSR61);
1148    case 30: return offsetofPPCGuestState(guest_VSR62);
1149    case 31: return offsetofPPCGuestState(guest_VSR63);
1150    default: break;
1151    }
1152    vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1153 }
1154
1155 static IRExpr* getVReg ( UInt archreg )
1156 {
1157    vassert(archreg < 32);
1158    return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1159 }
1160
1161 /* Ditto, but write to a reg instead. */
1162 static void putVReg ( UInt archreg, IRExpr* e )
1163 {
1164    vassert(archreg < 32);
1165    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1166    stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1167 }
1168
1169 /* Get contents of VSX guest register */
1170 static IRExpr* getVSReg ( UInt archreg )
1171 {
1172    vassert(archreg < 64);
1173    return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
1174 }
1175
1176 /* Ditto, but write to a VSX reg instead. */
1177 static void putVSReg ( UInt archreg, IRExpr* e )
1178 {
1179    vassert(archreg < 64);
1180    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1181    stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
1182 }
1183
1184
1185 static Int guestCR321offset ( UInt cr )
1186 {
1187    switch (cr) {
1188    case 0: return offsetofPPCGuestState(guest_CR0_321 );
1189    case 1: return offsetofPPCGuestState(guest_CR1_321 );
1190    case 2: return offsetofPPCGuestState(guest_CR2_321 );
1191    case 3: return offsetofPPCGuestState(guest_CR3_321 );
1192    case 4: return offsetofPPCGuestState(guest_CR4_321 );
1193    case 5: return offsetofPPCGuestState(guest_CR5_321 );
1194    case 6: return offsetofPPCGuestState(guest_CR6_321 );
1195    case 7: return offsetofPPCGuestState(guest_CR7_321 );
1196    default: vpanic("guestCR321offset(ppc)");
1197    }
1198
1199
1200 static Int guestCR0offset ( UInt cr )
1201 {
1202    switch (cr) {
1203    case 0: return offsetofPPCGuestState(guest_CR0_0 );
1204    case 1: return offsetofPPCGuestState(guest_CR1_0 );
1205    case 2: return offsetofPPCGuestState(guest_CR2_0 );
1206    case 3: return offsetofPPCGuestState(guest_CR3_0 );
1207    case 4: return offsetofPPCGuestState(guest_CR4_0 );
1208    case 5: return offsetofPPCGuestState(guest_CR5_0 );
1209    case 6: return offsetofPPCGuestState(guest_CR6_0 );
1210    case 7: return offsetofPPCGuestState(guest_CR7_0 );
1211    default: vpanic("guestCR3offset(ppc)");
1212    }
1213 }
1214
1215 /* Generate an IR sequence to do a popcount operation on the supplied
1216  * IRTemp, and return an IRTemp holding the result.
1217  */
1218 static IRTemp gen_POPCOUNT ( IRTemp src )
1219 {
1220    Int i, shift[6];
1221    IRTemp old = IRTemp_INVALID;
1222    IRTemp nyu = IRTemp_INVALID;
1223    IRTemp mask[6];
1224
1225    vassert(typeOfIRExpr(irsb->tyenv,mkexpr(src)) == Ity_I64);
1226    for (i = 0; i < 6; i++) {
1227       mask[i] = newTemp( Ity_I64 );
1228       shift[i] = 1 << i;
1229    }
1230    assign( mask[0], mkU64( 0x5555555555555555ULL ) );
1231    assign( mask[1], mkU64( 0x3333333333333333ULL ) );
1232    assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
1233    assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
1234    assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
1235    assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
1236    old = src;
1237    for (i = 0; i < 6; i++) {
1238       nyu = newTemp( Ity_I64 );
1239       assign( nyu,
1240               binop( Iop_Add64,
1241                      binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
1242                      binop( Iop_And64,
1243                             binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
1244                             mkexpr( mask[i] ) ) ) );
1245       old = nyu;
1246    }
1247    return nyu;
1248 }
1249
1250
1251 // ROTL(src32/64, rot_amt5/6)
1252 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1253                                           IRExpr* rot_amt )
1254 {
1255    IRExpr *mask, *rot;
1256    vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1257
1258    if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1259       // rot = (src << rot_amt) | (src >> (64-rot_amt))
1260       mask = binop(Iop_And8, rot_amt, mkU8(63));
1261       rot  = binop(Iop_Or64,
1262                 binop(Iop_Shl64, src, mask),
1263                 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1264    } else {
1265       // rot = (src << rot_amt) | (src >> (32-rot_amt))
1266       mask = binop(Iop_And8, rot_amt, mkU8(31));
1267       rot  = binop(Iop_Or32,
1268                 binop(Iop_Shl32, src, mask),
1269                 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
1270    }
1271    /* Note: the MuxOX is not merely an optimisation; it's needed
1272       because otherwise the Shr is a shift by the word size when
1273       mask denotes zero.  For rotates by immediates, a lot of
1274       this junk gets folded out. */
1275    return IRExpr_Mux0X( mask, /*     zero rotate */ src,
1276                               /* non-zero rotate */ rot );
1277 }
1278
1279 /* Standard effective address calc: (rA + rB) */
1280 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1281 {
1282    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1283    vassert(rA < 32);
1284    vassert(rB < 32);
1285    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1286 }
1287
1288 /* Standard effective address calc: (rA + simm) */
1289 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1290 {
1291    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1292    vassert(rA < 32);
1293    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
1294                 mkSzExtendS16(ty, simm16));
1295 }
1296
1297 /* Standard effective address calc: (rA|0) */
1298 static IRExpr* ea_rAor0 ( UInt rA )
1299 {
1300    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1301    vassert(rA < 32);
1302    if (rA == 0) {
1303       return mkSzImm(ty, 0);
1304    } else {
1305       return getIReg(rA);
1306    }
1307 }
1308
1309 /* Standard effective address calc: (rA|0) + rB */
1310 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1311 {
1312    vassert(rA < 32);
1313    vassert(rB < 32);
1314    return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1315 }
1316
1317 /* Standard effective address calc: (rA|0) + simm16 */
1318 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
1319 {
1320    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1321    vassert(rA < 32);
1322    if (rA == 0) {
1323       return mkSzExtendS16(ty, simm16);
1324    } else {
1325       return ea_rA_simm( rA, simm16 );
1326    }
1327 }
1328
1329
1330 /* Align effective address */
1331 static IRExpr* addr_align( IRExpr* addr, UChar align )
1332 {
1333    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1334    Long mask;
1335    switch (align) {
1336    case 1:  return addr;                    // byte aligned
1337    case 2:  mask = ((Long)-1) << 1; break;  // half-word aligned
1338    case 4:  mask = ((Long)-1) << 2; break;  // word aligned
1339    case 16: mask = ((Long)-1) << 4; break;  // quad-word aligned
1340    default:
1341       vex_printf("addr_align: align = %u\n", align);
1342       vpanic("addr_align(ppc)");
1343    }
1344
1345    vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1346    return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
1347 }
1348
1349
1350 /* Exit the trace if ADDR (intended to be a guest memory address) is
1351    not ALIGN-aligned, generating a request for a SIGBUS followed by a
1352    restart of the current insn. */
1353 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1354 {
1355    vassert(align == 4 || align == 8);
1356    if (mode64) {
1357       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1358       stmt(
1359          IRStmt_Exit(
1360             binop(Iop_CmpNE64,
1361                   binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1362                   mkU64(0)),
1363             Ijk_SigBUS,
1364             IRConst_U64( guest_CIA_curr_instr )
1365          )
1366       );
1367    } else {
1368       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1369       stmt(
1370          IRStmt_Exit(
1371             binop(Iop_CmpNE32,
1372                   binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1373                   mkU32(0)),
1374             Ijk_SigBUS,
1375             IRConst_U32( guest_CIA_curr_instr )
1376          )
1377       );
1378    }
1379 }
1380
1381
1382 /* Generate AbiHints which mark points at which the ELF or PowerOpen
1383    ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1384    N) becomes undefined.  That is at function calls and returns.  ELF
1385    ppc32 doesn't have this "feature" (how fortunate for it).  nia is
1386    the address of the next instruction to be executed.
1387 */
1388 static void make_redzone_AbiHint ( VexAbiInfo* vbi, 
1389                                    IRTemp nia, HChar* who )
1390 {
1391    Int szB = vbi->guest_stack_redzone_size;
1392    if (0) vex_printf("AbiHint: %s\n", who);
1393    vassert(szB >= 0);
1394    if (szB > 0) {
1395       if (mode64) {
1396          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1397          stmt( IRStmt_AbiHint( 
1398                   binop(Iop_Sub64, getIReg(1), mkU64(szB)), 
1399                   szB,
1400                   mkexpr(nia)
1401          ));
1402       } else {
1403          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1404          stmt( IRStmt_AbiHint( 
1405                   binop(Iop_Sub32, getIReg(1), mkU32(szB)), 
1406                   szB,
1407                   mkexpr(nia)
1408          ));
1409       }
1410    }
1411 }
1412
1413
1414 /*------------------------------------------------------------*/
1415 /*--- Helpers for condition codes.                         ---*/
1416 /*------------------------------------------------------------*/
1417
1418 /* Condition register layout. 
1419
1420    In the hardware, CR is laid out like this.  The leftmost end is the
1421    most significant bit in the register; however the IBM documentation
1422    numbers the bits backwards for some reason.
1423
1424    CR0      CR1    ..........   CR6       CR7
1425    0 .. 3   .......................  28 .. 31    (IBM bit numbering)
1426    31  28                             3    0     (normal bit numbering)
1427
1428    Each CR field is 4 bits:  [<,>,==,SO]
1429
1430    Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1431
1432    Indexing from BI to guest state:
1433
1434      let    n = BI / 4
1435           off = BI % 4
1436      this references CR n:
1437
1438         off==0   ->  guest_CRn_321 >> 3
1439         off==1   ->  guest_CRn_321 >> 2
1440         off==2   ->  guest_CRn_321 >> 1
1441         off==3   ->  guest_CRn_SO
1442
1443    Bear in mind the only significant bit in guest_CRn_SO is bit 0
1444    (normal notation) and in guest_CRn_321 the significant bits are
1445    3, 2 and 1 (normal notation).
1446 */
1447
1448 static void putCR321 ( UInt cr, IRExpr* e )
1449 {
1450    vassert(cr < 8);
1451    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1452    stmt( IRStmt_Put(guestCR321offset(cr), e) );
1453 }
1454
1455 static void putCR0 ( UInt cr, IRExpr* e )
1456 {
1457    vassert(cr < 8);
1458    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1459    stmt( IRStmt_Put(guestCR0offset(cr), e) );
1460 }
1461
1462 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1463 {
1464    vassert(cr < 8);
1465    return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1466 }
1467
1468 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1469 {
1470    vassert(cr < 8);
1471    return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1472 }
1473
1474 /* Fetch the specified CR bit (as per IBM/hardware notation) and
1475    return it at the bottom of an I32; the top 31 bits are guaranteed
1476    to be zero. */
1477 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1478 {
1479    UInt n   = bi / 4;
1480    UInt off = bi % 4;
1481    vassert(bi < 32);
1482    if (off == 3) {
1483       /* Fetch the SO bit for this CR field */
1484       /* Note: And32 is redundant paranoia iff guest state only has 0
1485          or 1 in that slot. */
1486       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1487    } else {
1488       /* Fetch the <, > or == bit for this CR field */
1489       return binop( Iop_And32, 
1490                     binop( Iop_Shr32, 
1491                            unop(Iop_8Uto32, getCR321(n)),
1492                            mkU8(toUChar(3-off)) ),
1493                     mkU32(1) );
1494    }
1495 }
1496
1497 /* Dually, write the least significant bit of BIT to the specified CR
1498    bit.  Indexing as per getCRbit. */
1499 static void putCRbit ( UInt bi, IRExpr* bit )
1500 {
1501    UInt    n, off;
1502    IRExpr* safe;
1503    vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
1504    safe = binop(Iop_And32, bit, mkU32(1));
1505    n   = bi / 4;
1506    off = bi % 4;
1507    vassert(bi < 32);
1508    if (off == 3) {
1509       /* This is the SO bit for this CR field */
1510       putCR0(n, unop(Iop_32to8, safe));
1511    } else {
1512       off = 3 - off;
1513       vassert(off == 1 || off == 2 || off == 3);
1514       putCR321(
1515          n,
1516          unop( Iop_32to8,
1517                binop( Iop_Or32,
1518                       /* old value with field masked out */
1519                       binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
1520                                        mkU32(~(1 << off))),
1521                       /* new value in the right place */
1522                       binop(Iop_Shl32, safe, mkU8(toUChar(off)))
1523                )
1524          )
1525       );
1526    }
1527 }
1528
1529 /* Fetch the specified CR bit (as per IBM/hardware notation) and
1530    return it somewhere in an I32; it does not matter where, but
1531    whichever bit it is, all other bits are guaranteed to be zero.  In
1532    other words, the I32-typed expression will be zero if the bit is
1533    zero and nonzero if the bit is 1.  Write into *where the index
1534    of where the bit will be. */
1535
1536 static
1537 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
1538 {
1539    UInt n   = bi / 4;
1540    UInt off = bi % 4;
1541    vassert(bi < 32);
1542    if (off == 3) {
1543       /* Fetch the SO bit for this CR field */
1544       /* Note: And32 is redundant paranoia iff guest state only has 0
1545          or 1 in that slot. */
1546       *where = 0;
1547       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1548    } else {
1549       /* Fetch the <, > or == bit for this CR field */
1550       *where = 3-off;
1551       return binop( Iop_And32, 
1552                     unop(Iop_8Uto32, getCR321(n)),
1553                     mkU32(1 << (3-off)) );
1554    }
1555 }
1556
1557 /* Set the CR0 flags following an arithmetic operation.
1558    (Condition Register CR0 Field Definition, PPC32 p60)
1559 */
1560 static IRExpr* getXER_SO ( void );
1561 static void set_CR0 ( IRExpr* result )
1562 {
1563    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
1564            typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
1565    if (mode64) {
1566       putCR321( 0, unop(Iop_64to8,
1567                         binop(Iop_CmpORD64S, result, mkU64(0))) );
1568    } else {
1569       putCR321( 0, unop(Iop_32to8,
1570                         binop(Iop_CmpORD32S, result, mkU32(0))) );
1571    }
1572    putCR0( 0, getXER_SO() );
1573 }
1574
1575
1576 /* Set the CR6 flags following an AltiVec compare operation. */
1577 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
1578 {
1579    /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
1580       all_ones  = (v[0] && v[1] && v[2] && v[3])
1581       all_zeros = ~(v[0] || v[1] || v[2] || v[3])
1582    */
1583    IRTemp v0 = newTemp(Ity_V128);
1584    IRTemp v1 = newTemp(Ity_V128);
1585    IRTemp v2 = newTemp(Ity_V128);
1586    IRTemp v3 = newTemp(Ity_V128);
1587    IRTemp rOnes  = newTemp(Ity_I8);
1588    IRTemp rZeros = newTemp(Ity_I8);
1589
1590    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
1591
1592    assign( v0, result );
1593    assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
1594    assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
1595    assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
1596
1597    assign( rZeros, unop(Iop_1Uto8,
1598        binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1599              unop(Iop_Not32,
1600                   unop(Iop_V128to32,
1601                        binop(Iop_OrV128,
1602                              binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
1603                              binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
1604                   ))) );
1605
1606    if (test_all_ones) {
1607       assign( rOnes, unop(Iop_1Uto8,
1608          binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1609                unop(Iop_V128to32,
1610                     binop(Iop_AndV128,
1611                           binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
1612                           binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
1613                     ))) );
1614       putCR321( 6, binop(Iop_Or8,
1615                          binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
1616                          binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
1617    } else {
1618       putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
1619    }
1620    putCR0( 6, mkU8(0) );
1621
1622
1623
1624
1625 /*------------------------------------------------------------*/
1626 /*--- Helpers for XER flags.                               ---*/
1627 /*------------------------------------------------------------*/
1628
1629 static void putXER_SO ( IRExpr* e )
1630 {
1631    IRExpr* so;
1632    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1633    so = binop(Iop_And8, e, mkU8(1));
1634    stmt( IRStmt_Put( OFFB_XER_SO, so ) );
1635 }
1636
1637 static void putXER_OV ( IRExpr* e )
1638 {
1639    IRExpr* ov;
1640    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1641    ov = binop(Iop_And8, e, mkU8(1));
1642    stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
1643 }
1644
1645 static void putXER_CA ( IRExpr* e )
1646 {
1647    IRExpr* ca;
1648    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1649    ca = binop(Iop_And8, e, mkU8(1));
1650    stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
1651 }
1652
1653 static void putXER_BC ( IRExpr* e )
1654 {
1655    IRExpr* bc;
1656    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1657    bc = binop(Iop_And8, e, mkU8(0x7F));
1658    stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
1659 }
1660
1661 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
1662 {
1663    return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
1664 }
1665
1666 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
1667 {
1668    return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
1669 }
1670
1671 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
1672 {
1673    return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
1674 }
1675
1676 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
1677 {
1678    return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
1679 }
1680
1681 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
1682 {
1683    IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
1684    return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
1685 }
1686
1687 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
1688 {
1689    return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
1690 }
1691
1692 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
1693 {
1694    IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
1695    return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
1696 }
1697
1698
1699 /* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
1700    %XER.SO accordingly. */
1701
1702 static void set_XER_OV_32( UInt op, IRExpr* res,
1703                            IRExpr* argL, IRExpr* argR )
1704 {
1705    IRTemp  t64;
1706    IRExpr* xer_ov;
1707    vassert(op < PPCG_FLAG_OP_NUMBER);
1708    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
1709    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
1710    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
1711
1712 #  define INT32_MIN 0x80000000
1713
1714 #  define XOR2(_aa,_bb) \
1715       binop(Iop_Xor32,(_aa),(_bb))
1716
1717 #  define XOR3(_cc,_dd,_ee) \
1718       binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
1719
1720 #  define AND3(_ff,_gg,_hh) \
1721       binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
1722
1723 #define NOT(_jj) \
1724       unop(Iop_Not32, (_jj))
1725
1726    switch (op) {
1727    case /* 0  */ PPCG_FLAG_OP_ADD:
1728    case /* 1  */ PPCG_FLAG_OP_ADDE:
1729       /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
1730       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
1731       xer_ov 
1732          = AND3( XOR3(argL,argR,mkU32(-1)),
1733                  XOR2(argL,res),
1734                  mkU32(INT32_MIN) );
1735       /* xer_ov can only be 0 or 1<<31 */
1736       xer_ov 
1737          = binop(Iop_Shr32, xer_ov, mkU8(31) );
1738       break;
1739       
1740    case /* 2  */ PPCG_FLAG_OP_DIVW:
1741       /* (argL == INT32_MIN && argR == -1) || argR == 0 */
1742       xer_ov
1743          = mkOR1(
1744               mkAND1( 
1745                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
1746                  binop(Iop_CmpEQ32, argR, mkU32(-1)) 
1747               ),
1748               binop(Iop_CmpEQ32, argR, mkU32(0) ) 
1749            );
1750       xer_ov 
1751          = unop(Iop_1Uto32, xer_ov);
1752       break;
1753       
1754    case /* 3  */ PPCG_FLAG_OP_DIVWU:
1755       /* argR == 0 */
1756       xer_ov 
1757          = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
1758       break;
1759       
1760    case /* 4  */ PPCG_FLAG_OP_MULLW:
1761       /* OV true if result can't be represented in 32 bits
1762          i.e sHi != sign extension of sLo */
1763       t64 = newTemp(Ity_I64);
1764       assign( t64, binop(Iop_MullS32, argL, argR) );
1765       xer_ov 
1766          = binop( Iop_CmpNE32,
1767                   unop(Iop_64HIto32, mkexpr(t64)),
1768                   binop( Iop_Sar32, 
1769                          unop(Iop_64to32, mkexpr(t64)), 
1770                          mkU8(31))
1771                   );
1772       xer_ov
1773          = unop(Iop_1Uto32, xer_ov);
1774       break;
1775       
1776    case /* 5  */ PPCG_FLAG_OP_NEG:
1777       /* argL == INT32_MIN */
1778       xer_ov
1779          = unop( Iop_1Uto32, 
1780                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
1781       break;
1782       
1783    case /* 6  */ PPCG_FLAG_OP_SUBF:
1784    case /* 7  */ PPCG_FLAG_OP_SUBFC:
1785    case /* 8  */ PPCG_FLAG_OP_SUBFE:
1786       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
1787       xer_ov 
1788          = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
1789                  XOR2(NOT(argL),res),
1790                  mkU32(INT32_MIN) );
1791       /* xer_ov can only be 0 or 1<<31 */
1792       xer_ov 
1793          = binop(Iop_Shr32, xer_ov, mkU8(31) );
1794       break;
1795       
1796    default: 
1797       vex_printf("set_XER_OV: op = %u\n", op);
1798       vpanic("set_XER_OV(ppc)");
1799    }
1800    
1801    /* xer_ov MUST denote either 0 or 1, no other value allowed */
1802    putXER_OV( unop(Iop_32to8, xer_ov) );
1803
1804    /* Update the summary overflow */
1805    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
1806
1807 #  undef INT32_MIN
1808 #  undef AND3
1809 #  undef XOR3
1810 #  undef XOR2
1811 #  undef NOT
1812 }
1813
1814 static void set_XER_OV_64( UInt op, IRExpr* res,
1815                            IRExpr* argL, IRExpr* argR )
1816 {
1817    IRExpr* xer_ov;
1818    vassert(op < PPCG_FLAG_OP_NUMBER);
1819    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
1820    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
1821    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
1822
1823 #  define INT64_MIN 0x8000000000000000ULL
1824
1825 #  define XOR2(_aa,_bb) \
1826       binop(Iop_Xor64,(_aa),(_bb))
1827
1828 #  define XOR3(_cc,_dd,_ee) \
1829       binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
1830
1831 #  define AND3(_ff,_gg,_hh) \
1832       binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
1833
1834 #define NOT(_jj) \
1835       unop(Iop_Not64, (_jj))
1836
1837    switch (op) {
1838    case /* 0  */ PPCG_FLAG_OP_ADD:
1839    case /* 1  */ PPCG_FLAG_OP_ADDE:
1840       /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
1841       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
1842       xer_ov 
1843          = AND3( XOR3(argL,argR,mkU64(-1)),
1844                  XOR2(argL,res),
1845                  mkU64(INT64_MIN) );
1846       /* xer_ov can only be 0 or 1<<63 */
1847       xer_ov 
1848          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
1849       break;
1850       
1851    case /* 2  */ PPCG_FLAG_OP_DIVW:
1852       /* (argL == INT64_MIN && argR == -1) || argR == 0 */
1853       xer_ov
1854          = mkOR1(
1855               mkAND1( 
1856                  binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
1857                  binop(Iop_CmpEQ64, argR, mkU64(-1)) 
1858               ),
1859               binop(Iop_CmpEQ64, argR, mkU64(0) ) 
1860            );
1861       break;
1862
1863    case /* 3  */ PPCG_FLAG_OP_DIVWU:
1864       /* argR == 0 */
1865       xer_ov 
1866          = binop(Iop_CmpEQ64, argR, mkU64(0));
1867       break;
1868       
1869    case /* 4  */ PPCG_FLAG_OP_MULLW: {
1870       /* OV true if result can't be represented in 64 bits
1871          i.e sHi != sign extension of sLo */
1872       xer_ov 
1873          = binop( Iop_CmpNE32,
1874                   unop(Iop_64HIto32, res),
1875                   binop( Iop_Sar32, 
1876                          unop(Iop_64to32, res), 
1877                          mkU8(31))
1878                   );
1879       break;
1880    }
1881       
1882    case /* 5  */ PPCG_FLAG_OP_NEG:
1883       /* argL == INT64_MIN */
1884       xer_ov
1885          = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
1886       break;
1887       
1888    case /* 6  */ PPCG_FLAG_OP_SUBF:
1889    case /* 7  */ PPCG_FLAG_OP_SUBFC:
1890    case /* 8  */ PPCG_FLAG_OP_SUBFE:
1891       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
1892       xer_ov 
1893          = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
1894                  XOR2(NOT(argL),res),
1895                  mkU64(INT64_MIN) );
1896       /* xer_ov can only be 0 or 1<<63 */
1897       xer_ov 
1898          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
1899       break;
1900       
1901    default: 
1902       vex_printf("set_XER_OV: op = %u\n", op);
1903       vpanic("set_XER_OV(ppc64)");
1904    }
1905    
1906    /* xer_ov MUST denote either 0 or 1, no other value allowed */
1907    putXER_OV( unop(Iop_1Uto8, xer_ov) );
1908
1909    /* Update the summary overflow */
1910    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
1911
1912 #  undef INT64_MIN
1913 #  undef AND3
1914 #  undef XOR3
1915 #  undef XOR2
1916 #  undef NOT
1917 }
1918
1919 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
1920                          IRExpr* argL, IRExpr* argR )
1921 {
1922    if (ty == Ity_I32)
1923       set_XER_OV_32( op, res, argL, argR );
1924    else
1925       set_XER_OV_64( op, res, argL, argR );
1926 }
1927
1928
1929
1930 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
1931    value being OLDCA.  Set %XER.CA accordingly. */
1932
1933 static void set_XER_CA_32 ( UInt op, IRExpr* res,
1934                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
1935 {
1936    IRExpr* xer_ca;
1937    vassert(op < PPCG_FLAG_OP_NUMBER);
1938    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
1939    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
1940    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
1941    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
1942
1943    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
1944       seems reasonable given that it's always generated by
1945       getXER_CA32(), which masks it accordingly.  In any case it being
1946       0 or 1 is an invariant of the ppc guest state representation;
1947       if it has any other value, that invariant has been violated. */
1948
1949    switch (op) {
1950    case /* 0 */ PPCG_FLAG_OP_ADD:
1951       /* res <u argL */
1952       xer_ca
1953          = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
1954       break;
1955       
1956    case /* 1 */ PPCG_FLAG_OP_ADDE:
1957       /* res <u argL || (old_ca==1 && res==argL) */
1958       xer_ca 
1959          = mkOR1( 
1960               binop(Iop_CmpLT32U, res, argL),
1961               mkAND1( 
1962                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
1963                  binop(Iop_CmpEQ32, res, argL) 
1964               ) 
1965            );
1966       xer_ca 
1967          = unop(Iop_1Uto32, xer_ca);
1968       break;
1969       
1970    case /* 8 */ PPCG_FLAG_OP_SUBFE:
1971       /* res <u argR || (old_ca==1 && res==argR) */
1972       xer_ca 
1973          = mkOR1( 
1974               binop(Iop_CmpLT32U, res, argR),
1975               mkAND1( 
1976                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
1977                  binop(Iop_CmpEQ32, res, argR) 
1978               ) 
1979            );
1980       xer_ca 
1981          = unop(Iop_1Uto32, xer_ca);
1982       break;
1983       
1984    case /* 7 */ PPCG_FLAG_OP_SUBFC:
1985    case /* 9 */ PPCG_FLAG_OP_SUBFI:
1986       /* res <=u argR */
1987       xer_ca
1988          = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
1989       break;
1990       
1991    case /* 10 */ PPCG_FLAG_OP_SRAW:
1992       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
1993          If it is <= 31, behave like SRAWI; else XER.CA is the sign
1994          bit of argL. */
1995       /* This term valid for shift amount < 32 only */
1996       xer_ca
1997          = binop(
1998               Iop_And32,
1999               binop(Iop_Sar32, argL, mkU8(31)),
2000               binop( Iop_And32,
2001                      argL,
2002                      binop( Iop_Sub32,
2003                             binop(Iop_Shl32, mkU32(1),
2004                                              unop(Iop_32to8,argR)),
2005                             mkU32(1) )
2006                      )
2007               );
2008       xer_ca 
2009          = IRExpr_Mux0X(
2010               /* shift amt > 31 ? */
2011               unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)),
2012               /* no -- be like srawi */
2013               unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))),
2014               /* yes -- get sign bit of argL */
2015               binop(Iop_Shr32, argL, mkU8(31))
2016            );
2017       break;
2018
2019    case /* 11 */ PPCG_FLAG_OP_SRAWI:
2020       /* xer_ca is 1 iff src was negative and bits_shifted_out != 
2021          0.  Since the shift amount is known to be in the range
2022          0 .. 31 inclusive the following seems viable:
2023          xer.ca == 1 iff the following is nonzero:
2024          (argL >>s 31)           -- either all 0s or all 1s
2025          & (argL & (1<<argR)-1)  -- the stuff shifted out */
2026       xer_ca
2027          = binop(
2028               Iop_And32,
2029               binop(Iop_Sar32, argL, mkU8(31)),
2030               binop( Iop_And32,
2031                      argL,
2032                      binop( Iop_Sub32,
2033                             binop(Iop_Shl32, mkU32(1),
2034                                              unop(Iop_32to8,argR)),
2035                             mkU32(1) )
2036                      )
2037               );
2038       xer_ca 
2039          = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2040       break;
2041       
2042    default: 
2043       vex_printf("set_XER_CA: op = %u\n", op);
2044       vpanic("set_XER_CA(ppc)");
2045    }
2046
2047    /* xer_ca MUST denote either 0 or 1, no other value allowed */
2048    putXER_CA( unop(Iop_32to8, xer_ca) );
2049 }
2050
2051 static void set_XER_CA_64 ( UInt op, IRExpr* res,
2052                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2053 {
2054    IRExpr* xer_ca;
2055    vassert(op < PPCG_FLAG_OP_NUMBER);
2056    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
2057    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
2058    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
2059    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
2060
2061    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2062       seems reasonable given that it's always generated by
2063       getXER_CA32(), which masks it accordingly.  In any case it being
2064       0 or 1 is an invariant of the ppc guest state representation;
2065       if it has any other value, that invariant has been violated. */
2066
2067    switch (op) {
2068    case /* 0 */ PPCG_FLAG_OP_ADD:
2069       /* res <u argL */
2070       xer_ca
2071          = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2072       break;
2073       
2074    case /* 1 */ PPCG_FLAG_OP_ADDE:
2075       /* res <u argL || (old_ca==1 && res==argL) */
2076       xer_ca 
2077          = mkOR1( 
2078               binop(Iop_CmpLT64U, res, argL),
2079               mkAND1( 
2080                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
2081                  binop(Iop_CmpEQ64, res, argL) 
2082                  ) 
2083               );
2084       xer_ca 
2085          = unop(Iop_1Uto32, xer_ca);
2086       break;
2087       
2088    case /* 8 */ PPCG_FLAG_OP_SUBFE:
2089       /* res <u argR || (old_ca==1 && res==argR) */
2090       xer_ca 
2091          = mkOR1( 
2092               binop(Iop_CmpLT64U, res, argR),
2093               mkAND1( 
2094                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
2095                  binop(Iop_CmpEQ64, res, argR) 
2096               ) 
2097            );
2098       xer_ca 
2099          = unop(Iop_1Uto32, xer_ca);
2100       break;
2101       
2102    case /* 7 */ PPCG_FLAG_OP_SUBFC:
2103    case /* 9 */ PPCG_FLAG_OP_SUBFI:
2104       /* res <=u argR */
2105       xer_ca
2106          = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2107       break;
2108       
2109       
2110    case /* 10 */ PPCG_FLAG_OP_SRAW:
2111       /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2112          If it is <= 31, behave like SRAWI; else XER.CA is the sign
2113          bit of argL. */
2114          /* This term valid for shift amount < 31 only */
2115
2116       xer_ca
2117          = binop(
2118               Iop_And64,
2119               binop(Iop_Sar64, argL, mkU8(31)),
2120               binop( Iop_And64,
2121                      argL,
2122                      binop( Iop_Sub64,
2123                             binop(Iop_Shl64, mkU64(1),
2124                                              unop(Iop_64to8,argR)),
2125                             mkU64(1) )
2126               )
2127            );
2128       xer_ca 
2129          = IRExpr_Mux0X(
2130               /* shift amt > 31 ? */
2131               unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(31), argR)),
2132               /* no -- be like srawi */
2133               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
2134               /* yes -- get sign bit of argL */
2135               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
2136            );
2137       break;
2138       
2139    case /* 11 */ PPCG_FLAG_OP_SRAWI:
2140       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2141          Since the shift amount is known to be in the range 0 .. 31
2142          inclusive the following seems viable:
2143          xer.ca == 1 iff the following is nonzero:
2144          (argL >>s 31)           -- either all 0s or all 1s
2145          & (argL & (1<<argR)-1)  -- the stuff shifted out */
2146
2147       xer_ca
2148          = binop(
2149               Iop_And64,
2150               binop(Iop_Sar64, argL, mkU8(31)),
2151               binop( Iop_And64,
2152                      argL,
2153                      binop( Iop_Sub64,
2154                             binop(Iop_Shl64, mkU64(1),
2155                                              unop(Iop_64to8,argR)),
2156                             mkU64(1) )
2157               )
2158            );
2159       xer_ca 
2160          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2161       break;
2162       
2163
2164    case /* 12 */ PPCG_FLAG_OP_SRAD:
2165       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2166          If it is <= 63, behave like SRADI; else XER.CA is the sign
2167          bit of argL. */
2168          /* This term valid for shift amount < 63 only */
2169
2170       xer_ca
2171          = binop(
2172               Iop_And64,
2173               binop(Iop_Sar64, argL, mkU8(63)),
2174               binop( Iop_And64,
2175                      argL,
2176                      binop( Iop_Sub64,
2177                             binop(Iop_Shl64, mkU64(1),
2178                                              unop(Iop_64to8,argR)),
2179                             mkU64(1) )
2180               )
2181            );
2182       xer_ca 
2183          = IRExpr_Mux0X(
2184               /* shift amt > 63 ? */
2185               unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)),
2186               /* no -- be like sradi */
2187               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
2188               /* yes -- get sign bit of argL */
2189               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
2190            );
2191       break;
2192
2193
2194    case /* 13 */ PPCG_FLAG_OP_SRADI:
2195       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2196          Since the shift amount is known to be in the range 0 .. 63
2197          inclusive, the following seems viable:
2198          xer.ca == 1 iff the following is nonzero:
2199          (argL >>s 63)           -- either all 0s or all 1s
2200          & (argL & (1<<argR)-1)  -- the stuff shifted out */
2201
2202       xer_ca
2203          = binop(
2204               Iop_And64,
2205               binop(Iop_Sar64, argL, mkU8(63)),
2206               binop( Iop_And64,
2207                      argL,
2208                      binop( Iop_Sub64,
2209                             binop(Iop_Shl64, mkU64(1),
2210                                              unop(Iop_64to8,argR)),
2211                             mkU64(1) )
2212               )
2213            );
2214       xer_ca 
2215          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2216       break;
2217
2218    default: 
2219       vex_printf("set_XER_CA: op = %u\n", op);
2220       vpanic("set_XER_CA(ppc64)");
2221    }
2222
2223    /* xer_ca MUST denote either 0 or 1, no other value allowed */
2224    putXER_CA( unop(Iop_32to8, xer_ca) );
2225 }
2226
2227 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
2228                          IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2229 {
2230    if (ty == Ity_I32)
2231       set_XER_CA_32( op, res, argL, argR, oldca );
2232    else
2233       set_XER_CA_64( op, res, argL, argR, oldca );
2234 }
2235
2236
2237
2238 /*------------------------------------------------------------*/
2239 /*--- Read/write to guest-state                           --- */
2240 /*------------------------------------------------------------*/
2241
2242 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
2243 {
2244    IRType ty = mode64 ? Ity_I64 : Ity_I32;
2245    switch (reg) {
2246    case PPC_GST_SPRG3_RO:
2247       return IRExpr_Get( OFFB_SPRG3_RO, ty );
2248
2249    case PPC_GST_CIA: 
2250       return IRExpr_Get( OFFB_CIA, ty );
2251
2252    case PPC_GST_LR: 
2253       return IRExpr_Get( OFFB_LR, ty );
2254
2255    case PPC_GST_CTR: 
2256       return IRExpr_Get( OFFB_CTR, ty );
2257
2258    case PPC_GST_VRSAVE: 
2259       return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
2260
2261    case PPC_GST_VSCR:
2262       return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
2263                               mkU32(MASK_VSCR_VALID));
2264
2265    case PPC_GST_CR: {
2266       /* Synthesise the entire CR into a single word.  Expensive. */
2267 #     define FIELD(_n)                                               \
2268          binop(Iop_Shl32,                                            \
2269                unop(Iop_8Uto32,                                      \
2270                     binop(Iop_Or8,                                   \
2271                           binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
2272                           binop(Iop_And8, getCR0(_n), mkU8(1))       \
2273                     )                                                \
2274                ),                                                    \
2275                mkU8(4 * (7-(_n)))                                    \
2276          )
2277       return binop(Iop_Or32,
2278                    binop(Iop_Or32,
2279                          binop(Iop_Or32, FIELD(0), FIELD(1)),
2280                          binop(Iop_Or32, FIELD(2), FIELD(3))
2281                          ),
2282                    binop(Iop_Or32,
2283                          binop(Iop_Or32, FIELD(4), FIELD(5)),
2284                          binop(Iop_Or32, FIELD(6), FIELD(7))
2285                          )
2286                    );
2287 #     undef FIELD
2288    }
2289
2290    case PPC_GST_XER:
2291       return binop(Iop_Or32,
2292                    binop(Iop_Or32,
2293                          binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
2294                          binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
2295                    binop(Iop_Or32,
2296                          binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
2297                          getXER_BC32()));
2298
2299    default:
2300       vex_printf("getGST(ppc): reg = %u", reg);
2301       vpanic("getGST(ppc)");
2302    }
2303 }
2304
2305 /* Get a masked word from the given reg */
2306 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
2307 {
2308    IRTemp val = newTemp(Ity_I32);
2309    vassert( reg < PPC_GST_MAX );
2310     
2311    switch (reg) {
2312
2313    case PPC_GST_FPSCR: {
2314       /* Vex-generated code expects the FPSCR to be set as follows:
2315          all exceptions masked, round-to-nearest.
2316          This corresponds to a FPSCR value of 0x0. */
2317
2318       /* We're only keeping track of the rounding mode,
2319          so if the mask isn't asking for this, just return 0x0 */
2320       if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
2321          assign( val, IRExpr_Get( OFFB_FPROUND, Ity_I32 ) );
2322       } else {
2323          assign( val, mkU32(0x0) );
2324       }
2325       break;
2326    }
2327
2328    default:
2329       vex_printf("getGST_masked(ppc): reg = %u", reg);
2330       vpanic("getGST_masked(ppc)");
2331    }
2332
2333    if (mask != 0xFFFFFFFF) {
2334       return binop(Iop_And32, mkexpr(val), mkU32(mask));
2335    } else {
2336       return mkexpr(val);
2337    }
2338 }
2339
2340 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
2341    and return it at the bottom of an I32; the top 27 bits are
2342    guaranteed to be zero. */
2343 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
2344 {
2345    UInt shft, mask;
2346
2347    vassert( fld < 8 );
2348    vassert( reg < PPC_GST_MAX );
2349    
2350    shft = 4*(7-fld);
2351    mask = 0xF<<shft;
2352
2353    switch (reg) {
2354    case PPC_GST_XER:
2355       vassert(fld ==7);
2356       return binop(Iop_Or32,
2357                    binop(Iop_Or32,
2358                          binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
2359                          binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
2360                    binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
2361       break;
2362
2363    default:
2364       if (shft == 0)
2365          return getGST_masked( reg, mask );
2366       else
2367          return binop(Iop_Shr32,
2368                       getGST_masked( reg, mask ),
2369                       mkU8(toUChar( shft )));
2370    }
2371 }
2372
2373 static void putGST ( PPC_GST reg, IRExpr* src )
2374 {
2375    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
2376    IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
2377    vassert( reg < PPC_GST_MAX );
2378    switch (reg) {
2379    case PPC_GST_IP_AT_SYSCALL: 
2380       vassert( ty_src == ty );
2381       stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
2382       break;
2383    case PPC_GST_CIA: 
2384       vassert( ty_src == ty );
2385       stmt( IRStmt_Put( OFFB_CIA, src ) );
2386       break;
2387    case PPC_GST_LR: 
2388       vassert( ty_src == ty );
2389       stmt( IRStmt_Put( OFFB_LR, src ) );
2390       break;
2391    case PPC_GST_CTR: 
2392       vassert( ty_src == ty );
2393       stmt( IRStmt_Put( OFFB_CTR, src ) );
2394       break;
2395    case PPC_GST_VRSAVE: 
2396       vassert( ty_src == Ity_I32 );
2397       stmt( IRStmt_Put( OFFB_VRSAVE,src));
2398       break;
2399    case PPC_GST_VSCR:
2400       vassert( ty_src == Ity_I32 );
2401       stmt( IRStmt_Put( OFFB_VSCR,
2402                         binop(Iop_And32, src,
2403                               mkU32(MASK_VSCR_VALID)) ) );
2404       break;
2405    case PPC_GST_XER:
2406       vassert( ty_src == Ity_I32 );
2407       putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
2408       putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
2409       putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
2410       putXER_BC( unop(Iop_32to8, src) );
2411       break;
2412       
2413    case PPC_GST_EMWARN:
2414       vassert( ty_src == Ity_I32 );
2415       stmt( IRStmt_Put( OFFB_EMWARN,src) );
2416       break;
2417       
2418    case PPC_GST_TISTART: 
2419       vassert( ty_src == ty );
2420       stmt( IRStmt_Put( OFFB_TISTART, src) );
2421       break;
2422       
2423    case PPC_GST_TILEN: 
2424       vassert( ty_src == ty );
2425       stmt( IRStmt_Put( OFFB_TILEN, src) );
2426       break;
2427       
2428    default:
2429       vex_printf("putGST(ppc): reg = %u", reg);
2430       vpanic("putGST(ppc)");
2431    }
2432 }
2433
2434 /* Write masked src to the given reg */
2435 static void putGST_masked ( PPC_GST reg, IRExpr* src, UInt mask )
2436 {
2437    IRType ty = mode64 ? Ity_I64 : Ity_I32;
2438    vassert( reg < PPC_GST_MAX );
2439    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
2440    
2441    switch (reg) {
2442    case PPC_GST_FPSCR: {
2443       /* Allow writes to Rounding Mode */
2444       if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
2445          /* construct new fpround from new and old values as per mask:
2446             new fpround = (src & (3 & mask)) | (fpround & (3 & ~mask)) */
2447          stmt( 
2448             IRStmt_Put( 
2449                OFFB_FPROUND,
2450                binop(
2451                   Iop_Or32, 
2452                   binop(Iop_And32, src, mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & mask)),
2453                   binop(
2454                      Iop_And32, 
2455                      IRExpr_Get(OFFB_FPROUND,Ity_I32),
2456                      mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & ~mask)
2457                   )
2458                )
2459             )
2460          );
2461       }
2462
2463       /* Give EmWarn for attempted writes to:
2464          - Exception Controls
2465          - Non-IEEE Mode
2466       */
2467       if (mask & 0xFC) {  // Exception Control, Non-IEE mode
2468          VexEmWarn ew = EmWarn_PPCexns;
2469
2470          /* If any of the src::exception_control bits are actually set,
2471             side-exit to the next insn, reporting the warning,
2472             so that Valgrind's dispatcher sees the warning. */
2473          putGST( PPC_GST_EMWARN, mkU32(ew) );
2474          stmt( 
2475             IRStmt_Exit(
2476                binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)),
2477                Ijk_EmWarn,
2478                mkSzConst( ty, nextInsnAddr()) ));
2479       }
2480
2481       /* Ignore all other writes */
2482       break;
2483    }
2484
2485    default:
2486       vex_printf("putGST_masked(ppc): reg = %u", reg);
2487       vpanic("putGST_masked(ppc)");
2488    }
2489 }
2490
2491 /* Write the least significant nibble of src to the specified
2492    REG[FLD] (as per IBM/hardware notation). */
2493 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
2494 {
2495    UInt shft, mask;
2496
2497    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
2498    vassert( fld < 8 );
2499    vassert( reg < PPC_GST_MAX );
2500    
2501    shft = 4*(7-fld);
2502    mask = 0xF<<shft;
2503
2504    switch (reg) {
2505    case PPC_GST_CR:
2506       putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
2507       putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
2508       break;
2509
2510    default:
2511       if (shft == 0) {
2512          putGST_masked( reg, src, mask );
2513       } else {
2514          putGST_masked( reg,
2515                         binop(Iop_Shl32, src, mkU8(toUChar(shft))),
2516                         mask );
2517       }
2518    }
2519 }
2520
2521 /*------------------------------------------------------------*/
2522 /* Helpers for VSX instructions that do floating point
2523  * operations and need to determine if a src contains a
2524  * special FP value.
2525  *
2526  *------------------------------------------------------------*/
2527
2528 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
2529 #define FP_FRAC_PART(x) binop( Iop_And64, \
2530                                mkexpr( x ), \
2531                                mkU64( NONZERO_FRAC_MASK ) )
2532
2533 // Returns exponent part of floating point as I32
2534 static IRExpr * fp_exp_part(IRTemp src)
2535 {
2536    IRExpr * exp;
2537    if (!mode64)
2538       exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
2539                                                       mkexpr( src ) ),
2540                                      mkU8( 20 ) ), mkU32( 0x7ff ) );
2541    else
2542       exp = unop( Iop_64to32,
2543                   binop( Iop_And64,
2544                          binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
2545                          mkU64( 0x7ff ) ) );
2546    return exp;
2547 }
2548
2549
2550 // Infinity: exp = 7ff and fraction is zero; s = 0/1
2551 static IRExpr * is_Inf(IRTemp src)
2552 {
2553    IRExpr * Inf_exp, * hi32, * low32;
2554    IRTemp frac_part = newTemp(Ity_I64);
2555
2556    assign( frac_part, FP_FRAC_PART(src) );
2557    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src ), mkU32( 0x7ff ) );
2558    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
2559    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
2560    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
2561                                   mkU32( 0 ) ) );
2562 }
2563
2564 // Zero: exp is zero and fraction is zero; s = 0/1
2565 static IRExpr * is_Zero(IRTemp src)
2566 {
2567 #define SIGN_MASK 0x7fffffffffffffffULL
2568    IRExpr * hi32, * low32;
2569    IRTemp sign_less_part = newTemp(Ity_I64);
2570
2571    assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
2572    hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
2573    low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
2574    return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
2575                               mkU32( 0 ) );
2576 }
2577
2578 /*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
2579  *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
2580  *  This function returns an IRExpr value of '1' for any type of NaN.
2581  */
2582 static IRExpr * is_NaN(IRTemp src)
2583 {
2584    IRExpr * NaN_exp, * hi32, * low32;
2585    IRTemp frac_part = newTemp(Ity_I64);
2586
2587    assign( frac_part, FP_FRAC_PART(src) );
2588    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
2589    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
2590    NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src ), mkU32( 0x7ffULL ) );
2591
2592    return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
2593                                                mkU32( 0 ) ) );
2594 }
2595
2596
2597 /*------------------------------------------------------------*/
2598 /*--- Integer Instruction Translation                     --- */
2599 /*------------------------------------------------------------*/
2600
2601 /*
2602   Integer Arithmetic Instructions
2603 */
2604 static Bool dis_int_arith ( UInt theInstr )
2605 {
2606    /* D-Form, XO-Form */
2607    UChar opc1    = ifieldOPC(theInstr);
2608    UChar rD_addr = ifieldRegDS(theInstr);
2609    UChar rA_addr = ifieldRegA(theInstr);
2610    UInt  uimm16  = ifieldUIMM16(theInstr);
2611    UChar rB_addr = ifieldRegB(theInstr);
2612    UChar flag_OE = ifieldBIT10(theInstr);
2613    UInt  opc2    = ifieldOPClo9(theInstr);
2614    UChar flag_rC = ifieldBIT0(theInstr);
2615
2616    Long   simm16 = extend_s_16to64(uimm16);
2617    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
2618    IRTemp rA     = newTemp(ty);
2619    IRTemp rB     = newTemp(ty);
2620    IRTemp rD     = newTemp(ty);
2621
2622    Bool do_rc = False;
2623
2624    assign( rA, getIReg(rA_addr) );
2625    assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
2626
2627    switch (opc1) {
2628    /* D-Form */
2629    case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
2630       DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2631       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2632                          mkSzExtendS16(ty, uimm16) ) );
2633       set_XER_CA( ty, PPCG_FLAG_OP_ADD, 
2634                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2635                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2636       break;
2637     
2638    case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
2639       DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2640       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2641                          mkSzExtendS16(ty, uimm16) ) );
2642       set_XER_CA( ty, PPCG_FLAG_OP_ADD, 
2643                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2644                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2645       do_rc = True;  // Always record to CR
2646       flag_rC = 1;
2647       break;
2648
2649    case 0x0E: // addi   (Add Immediate, PPC32 p350)
2650       // li rD,val   == addi rD,0,val
2651       // la disp(rA) == addi rD,rA,disp
2652       if ( rA_addr == 0 ) {
2653          DIP("li r%u,%d\n", rD_addr, (Int)simm16);
2654          assign( rD, mkSzExtendS16(ty, uimm16) );
2655       } else {
2656          DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2657          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2658                             mkSzExtendS16(ty, uimm16) ) );
2659       }
2660       break;
2661
2662    case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
2663       // lis rD,val == addis rD,0,val
2664       if ( rA_addr == 0 ) {
2665          DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
2666          assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
2667       } else {
2668          DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
2669          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2670                             mkSzExtendS32(ty, uimm16 << 16) ) );
2671       }
2672       break;
2673
2674    case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
2675       DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2676       if (mode64)
2677          assign( rD, unop(Iop_128to64,
2678                           binop(Iop_MullS64, mkexpr(rA),
2679                                 mkSzExtendS16(ty, uimm16))) );
2680       else
2681          assign( rD, unop(Iop_64to32,
2682                           binop(Iop_MullS32, mkexpr(rA),
2683                                 mkSzExtendS16(ty, uimm16))) );
2684       break;
2685
2686    case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
2687       DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2688       // rD = simm16 - rA
2689       assign( rD, binop( mkSzOp(ty, Iop_Sub8),
2690                          mkSzExtendS16(ty, uimm16),
2691                          mkexpr(rA)) );
2692       set_XER_CA( ty, PPCG_FLAG_OP_SUBFI, 
2693                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2694                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2695       break;
2696
2697    /* XO-Form */
2698    case 0x1F:
2699       do_rc = True;    // All below record to CR
2700       
2701       switch (opc2) {
2702       case 0x10A: // add  (Add, PPC32 p347)
2703          DIP("add%s%s r%u,r%u,r%u\n",
2704              flag_OE ? "o" : "", flag_rC ? ".":"",
2705              rD_addr, rA_addr, rB_addr);
2706          assign( rD, binop( mkSzOp(ty, Iop_Add8),
2707                             mkexpr(rA), mkexpr(rB) ) );
2708          if (flag_OE) {
2709             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
2710                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2711          }
2712          break;
2713
2714       case 0x00A: // addc      (Add Carrying, PPC32 p348)
2715          DIP("addc%s%s r%u,r%u,r%u\n",
2716              flag_OE ? "o" : "", flag_rC ? ".":"",
2717              rD_addr, rA_addr, rB_addr);
2718          assign( rD, binop( mkSzOp(ty, Iop_Add8),
2719                             mkexpr(rA), mkexpr(rB)) );
2720          set_XER_CA( ty, PPCG_FLAG_OP_ADD, 
2721                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
2722                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2723          if (flag_OE) {
2724             set_XER_OV( ty, PPCG_FLAG_OP_ADD, 
2725                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2726          }
2727          break;
2728          
2729       case 0x08A: { // adde      (Add Extended, PPC32 p349)
2730          IRTemp old_xer_ca = newTemp(ty);
2731          DIP("adde%s%s r%u,r%u,r%u\n",
2732              flag_OE ? "o" : "", flag_rC ? ".":"",
2733              rD_addr, rA_addr, rB_addr);
2734          // rD = rA + rB + XER[CA]
2735          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
2736          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2737                             binop( mkSzOp(ty, Iop_Add8),
2738                                    mkexpr(rB), mkexpr(old_xer_ca))) );
2739          set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 
2740                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
2741                      mkexpr(old_xer_ca) );
2742          if (flag_OE) {
2743             set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 
2744                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2745          }
2746          break;
2747       }
2748
2749       case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
2750          IRTemp old_xer_ca = newTemp(ty);
2751          IRExpr *min_one;
2752          if (rB_addr != 0) {
2753             vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
2754             return False;
2755          }
2756          DIP("addme%s%s r%u,r%u,r%u\n",
2757              flag_OE ? "o" : "", flag_rC ? ".":"",
2758              rD_addr, rA_addr, rB_addr);
2759          // rD = rA + (-1) + XER[CA]
2760          // => Just another form of adde
2761          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
2762          min_one = mkSzImm(ty, (Long)-1);
2763          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2764                             binop( mkSzOp(ty, Iop_Add8),
2765                                    min_one, mkexpr(old_xer_ca)) ));
2766          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
2767                      mkexpr(rD), mkexpr(rA), min_one,
2768                      mkexpr(old_xer_ca) );
2769          if (flag_OE) {
2770             set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 
2771                         mkexpr(rD), mkexpr(rA), min_one );
2772          }
2773          break;
2774       }
2775
2776       case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
2777          IRTemp old_xer_ca = newTemp(ty);
2778          if (rB_addr != 0) {
2779             vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
2780             return False;
2781          }
2782          DIP("addze%s%s r%u,r%u,r%u\n",
2783              flag_OE ? "o" : "", flag_rC ? ".":"",
2784              rD_addr, rA_addr, rB_addr);
2785          // rD = rA + (0) + XER[CA]
2786          // => Just another form of adde
2787          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
2788          assign( rD, binop( mkSzOp(ty, Iop_Add8),
2789                             mkexpr(rA), mkexpr(old_xer_ca)) );
2790          set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 
2791                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 
2792                      mkexpr(old_xer_ca) );
2793          if (flag_OE) {
2794             set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 
2795                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
2796          }
2797          break;
2798       }
2799
2800       case 0x1EB: // divw       (Divide Word, PPC32 p388)
2801          DIP("divw%s%s r%u,r%u,r%u\n",
2802              flag_OE ? "o" : "", flag_rC ? ".":"",
2803              rD_addr, rA_addr, rB_addr);
2804          if (mode64) {
2805             /* Note:
2806                XER settings are mode independent, and reflect the 
2807                overflow of the low-order 32bit result
2808                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
2809             */
2810             /* rD[hi32] are undefined: setting them to sign of lo32
2811                 - makes set_CR0 happy */
2812             IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
2813             IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
2814             assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
2815                                                          divisor) ) );
2816             if (flag_OE) {
2817                set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 
2818                            mkexpr(rD), dividend, divisor );
2819             }
2820          } else {
2821             assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
2822             if (flag_OE) {
2823                set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 
2824                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2825             }
2826          }
2827          /* Note:
2828             if (0x8000_0000 / -1) or (x / 0)
2829             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
2830             => But _no_ exception raised. */
2831          break;
2832
2833       case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
2834          DIP("divwu%s%s r%u,r%u,r%u\n",
2835              flag_OE ? "o" : "", flag_rC ? ".":"",
2836              rD_addr, rA_addr, rB_addr);
2837          if (mode64) {
2838             /* Note:
2839                XER settings are mode independent, and reflect the 
2840                overflow of the low-order 32bit result
2841                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
2842             */
2843             IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
2844             IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
2845             assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
2846                                                          divisor) ) );
2847             if (flag_OE) {
2848                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 
2849                            mkexpr(rD), dividend, divisor );
2850             }
2851          } else {
2852             assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
2853             if (flag_OE) {
2854                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 
2855                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2856             }
2857          }
2858          /* Note: ditto comment divw, for (x / 0) */
2859          break;
2860
2861       case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
2862          if (flag_OE != 0) {
2863             vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
2864             return False;
2865          }
2866          DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
2867              rD_addr, rA_addr, rB_addr);
2868          if (mode64) {
2869             /* rD[hi32] are undefined: setting them to sign of lo32
2870                 - makes set_CR0 happy */
2871             assign( rD, binop(Iop_Sar64,
2872                            binop(Iop_Mul64,
2873                                  mk64lo32Sto64( mkexpr(rA) ),
2874                                  mk64lo32Sto64( mkexpr(rB) )),
2875                               mkU8(32)) );
2876          } else {
2877             assign( rD, unop(Iop_64HIto32,
2878                              binop(Iop_MullS32,
2879                                    mkexpr(rA), mkexpr(rB))) );
2880          }
2881          break;
2882
2883       case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
2884          if (flag_OE != 0) {
2885             vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
2886             return False;
2887          }
2888          DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
2889              rD_addr, rA_addr, rB_addr);
2890          if (mode64) {
2891             /* rD[hi32] are undefined: setting them to sign of lo32
2892                 - makes set_CR0 happy */
2893             assign( rD, binop(Iop_Sar64,
2894                            binop(Iop_Mul64,
2895                                  mk64lo32Uto64( mkexpr(rA) ),
2896                                  mk64lo32Uto64( mkexpr(rB) ) ),
2897                               mkU8(32)) );
2898          } else {
2899             assign( rD, unop(Iop_64HIto32, 
2900                              binop(Iop_MullU32,
2901                                    mkexpr(rA), mkexpr(rB))) );
2902          }
2903          break;
2904          
2905       case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
2906          DIP("mullw%s%s r%u,r%u,r%u\n",
2907              flag_OE ? "o" : "", flag_rC ? ".":"",
2908              rD_addr, rA_addr, rB_addr);
2909          if (mode64) {
2910             /* rD[hi32] are undefined: setting them to sign of lo32
2911                 - set_XER_OV() and set_CR0() depend on this */
2912             IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
2913             IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
2914             assign( rD, binop(Iop_MullS32, a, b) );
2915             if (flag_OE) {
2916                set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 
2917                            mkexpr(rD),
2918                            unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
2919             }
2920          } else {
2921             assign( rD, unop(Iop_64to32,
2922                              binop(Iop_MullU32,
2923                                    mkexpr(rA), mkexpr(rB))) );
2924             if (flag_OE) {
2925                set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 
2926                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2927             }
2928          }
2929          break;
2930
2931       case 0x068: // neg        (Negate, PPC32 p493)
2932          if (rB_addr != 0) {
2933             vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
2934             return False;
2935          }
2936          DIP("neg%s%s r%u,r%u\n",
2937              flag_OE ? "o" : "", flag_rC ? ".":"",
2938              rD_addr, rA_addr);
2939          // rD = (~rA) + 1
2940          assign( rD, binop( mkSzOp(ty, Iop_Add8),
2941                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
2942                             mkSzImm(ty, 1)) );
2943          if (flag_OE) {
2944             set_XER_OV( ty, PPCG_FLAG_OP_NEG, 
2945                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2946          }
2947          break;
2948
2949       case 0x028: // subf       (Subtract From, PPC32 p537)
2950          DIP("subf%s%s r%u,r%u,r%u\n",
2951              flag_OE ? "o" : "", flag_rC ? ".":"",
2952              rD_addr, rA_addr, rB_addr);
2953          // rD = rB - rA
2954          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
2955                             mkexpr(rB), mkexpr(rA)) );
2956          if (flag_OE) {
2957             set_XER_OV( ty, PPCG_FLAG_OP_SUBF, 
2958                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2959          }
2960          break;
2961
2962       case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
2963          DIP("subfc%s%s r%u,r%u,r%u\n",
2964              flag_OE ? "o" : "", flag_rC ? ".":"",
2965              rD_addr, rA_addr, rB_addr);
2966          // rD = rB - rA
2967          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
2968                             mkexpr(rB), mkexpr(rA)) );
2969          set_XER_CA( ty, PPCG_FLAG_OP_SUBFC, 
2970                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
2971                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2972          if (flag_OE) {
2973             set_XER_OV( ty, PPCG_FLAG_OP_SUBFC, 
2974                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2975          }
2976          break;
2977          
2978       case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
2979          IRTemp old_xer_ca = newTemp(ty);
2980          DIP("subfe%s%s r%u,r%u,r%u\n",
2981              flag_OE ? "o" : "", flag_rC ? ".":"",
2982              rD_addr, rA_addr, rB_addr);
2983          // rD = (log not)rA + rB + XER[CA]
2984          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
2985          assign( rD, binop( mkSzOp(ty, Iop_Add8),
2986                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
2987                             binop( mkSzOp(ty, Iop_Add8),
2988                                    mkexpr(rB), mkexpr(old_xer_ca))) );
2989          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 
2990                      mkexpr(rD), mkexpr(rA), mkexpr(rB), 
2991                      mkexpr(old_xer_ca) );
2992          if (flag_OE) {
2993             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 
2994                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2995          }
2996          break;
2997       }
2998
2999       case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
3000          IRTemp old_xer_ca = newTemp(ty);
3001          IRExpr *min_one;
3002          if (rB_addr != 0) {
3003             vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
3004             return False;
3005          }
3006          DIP("subfme%s%s r%u,r%u\n",
3007              flag_OE ? "o" : "", flag_rC ? ".":"",
3008              rD_addr, rA_addr);
3009          // rD = (log not)rA + (-1) + XER[CA]
3010          // => Just another form of subfe
3011          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3012          min_one = mkSzImm(ty, (Long)-1);
3013          assign( rD, binop( mkSzOp(ty, Iop_Add8),
3014                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3015                             binop( mkSzOp(ty, Iop_Add8),
3016                                    min_one, mkexpr(old_xer_ca))) );
3017          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3018                      mkexpr(rD), mkexpr(rA), min_one,
3019                      mkexpr(old_xer_ca) );
3020          if (flag_OE) {
3021             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 
3022                         mkexpr(rD), mkexpr(rA), min_one );
3023          }
3024          break;
3025       }
3026
3027       case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
3028          IRTemp old_xer_ca = newTemp(ty);
3029          if (rB_addr != 0) {
3030             vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
3031             return False;
3032          }
3033          DIP("subfze%s%s r%u,r%u\n",
3034              flag_OE ? "o" : "", flag_rC ? ".":"",
3035              rD_addr, rA_addr);
3036          // rD = (log not)rA + (0) + XER[CA]
3037          // => Just another form of subfe
3038          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3039          assign( rD, binop( mkSzOp(ty, Iop_Add8),
3040                            unop( mkSzOp(ty, Iop_Not8),
3041                                  mkexpr(rA)), mkexpr(old_xer_ca)) );
3042          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3043                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 
3044                      mkexpr(old_xer_ca) );
3045          if (flag_OE) {
3046             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3047                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3048          }
3049          break;
3050       }
3051
3052
3053       /* 64bit Arithmetic */
3054       case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
3055          if (flag_OE != 0) {
3056             vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
3057             return False;
3058          }
3059          DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3060              rD_addr, rA_addr, rB_addr);
3061          assign( rD, unop(Iop_128HIto64, 
3062                           binop(Iop_MullS64,
3063                                 mkexpr(rA), mkexpr(rB))) );
3064
3065          break;
3066
3067       case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
3068          if (flag_OE != 0) {
3069             vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
3070             return False;
3071          }
3072          DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3073              rD_addr, rA_addr, rB_addr);
3074          assign( rD, unop(Iop_128HIto64, 
3075                           binop(Iop_MullU64,
3076                                 mkexpr(rA), mkexpr(rB))) );
3077          break;
3078
3079       case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
3080          DIP("mulld%s%s r%u,r%u,r%u\n",
3081              flag_OE ? "o" : "", flag_rC ? ".":"",
3082              rD_addr, rA_addr, rB_addr);
3083          assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
3084          if (flag_OE) {
3085             set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 
3086                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3087          }
3088          break;
3089
3090       case 0x1E9: // divd (Divide DWord, PPC64 p419)
3091          DIP("divd%s%s r%u,r%u,r%u\n",
3092              flag_OE ? "o" : "", flag_rC ? ".":"",
3093              rD_addr, rA_addr, rB_addr);
3094          assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
3095          if (flag_OE) {
3096             set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 
3097                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3098          }
3099          break;
3100          /* Note:
3101             if (0x8000_0000_0000_0000 / -1) or (x / 0)
3102             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3103             => But _no_ exception raised. */
3104
3105       case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
3106          DIP("divdu%s%s r%u,r%u,r%u\n",
3107              flag_OE ? "o" : "", flag_rC ? ".":"",
3108              rD_addr, rA_addr, rB_addr);
3109          assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
3110          if (flag_OE) {
3111             set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 
3112                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3113          }
3114          break;
3115          /* Note: ditto comment divd, for (x / 0) */
3116
3117       default:
3118          vex_printf("dis_int_arith(ppc)(opc2)\n");
3119          return False;
3120       }
3121       break;
3122
3123    default:
3124       vex_printf("dis_int_arith(ppc)(opc1)\n");
3125       return False;
3126    }
3127
3128    putIReg( rD_addr, mkexpr(rD) );
3129
3130    if (do_rc && flag_rC) {
3131       set_CR0( mkexpr(rD) );
3132    }
3133    return True;
3134 }
3135
3136
3137
3138 /*
3139   Integer Compare Instructions
3140 */
3141 static Bool dis_int_cmp ( UInt theInstr )
3142 {
3143    /* D-Form, X-Form */
3144    UChar opc1    = ifieldOPC(theInstr);
3145    UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
3146    UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
3147    UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
3148    UChar rA_addr = ifieldRegA(theInstr);
3149    UInt  uimm16  = ifieldUIMM16(theInstr);
3150    UChar rB_addr = ifieldRegB(theInstr);
3151    UInt  opc2    = ifieldOPClo10(theInstr);
3152    UChar b0      = ifieldBIT0(theInstr);
3153
3154    IRType ty = mode64 ? Ity_I64 : Ity_I32;
3155    IRExpr *a = getIReg(rA_addr);
3156    IRExpr *b;
3157
3158    if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
3159       vex_printf("dis_int_cmp(ppc)(flag_L)\n");
3160       return False;
3161    }
3162    
3163    if (b22 != 0) {
3164       vex_printf("dis_int_cmp(ppc)(b22)\n");
3165       return False;
3166    }
3167    
3168    switch (opc1) {
3169    case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
3170       DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
3171           (Int)extend_s_16to32(uimm16));
3172       b = mkSzExtendS16( ty, uimm16 );
3173       if (flag_L == 1) {
3174          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
3175       } else {
3176          a = mkNarrowTo32( ty, a );
3177          b = mkNarrowTo32( ty, b );
3178          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
3179       }
3180       putCR0( crfD, getXER_SO() );
3181       break;
3182       
3183    case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
3184       DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
3185       b = mkSzImm( ty, uimm16 );
3186       if (flag_L == 1) {
3187          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
3188       } else {
3189          a = mkNarrowTo32( ty, a );
3190          b = mkNarrowTo32( ty, b );
3191          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
3192       }
3193       putCR0( crfD, getXER_SO() );
3194       break;
3195       
3196    /* X Form */
3197    case 0x1F:
3198       if (b0 != 0) {
3199          vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
3200          return False;
3201       }
3202       b = getIReg(rB_addr);
3203
3204       switch (opc2) {
3205       case 0x000: // cmp (Compare, PPC32 p367)
3206          DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
3207          /* Comparing a reg with itself produces a result which
3208             doesn't depend on the contents of the reg.  Therefore
3209             remove the false dependency, which has been known to cause
3210             memcheck to produce false errors. */
3211          if (rA_addr == rB_addr)
3212             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
3213                     ? mkU64(0)  : mkU32(0);
3214          if (flag_L == 1) {
3215             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
3216          } else {
3217             a = mkNarrowTo32( ty, a );
3218             b = mkNarrowTo32( ty, b );
3219             putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
3220          }
3221          putCR0( crfD, getXER_SO() );
3222          break;
3223          
3224       case 0x020: // cmpl (Compare Logical, PPC32 p369)
3225          DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
3226          /* Comparing a reg with itself produces a result which
3227             doesn't depend on the contents of the reg.  Therefore
3228             remove the false dependency, which has been known to cause
3229             memcheck to produce false errors. */
3230          if (rA_addr == rB_addr)
3231             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
3232                     ? mkU64(0)  : mkU32(0);
3233          if (flag_L == 1) {
3234             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
3235          } else {
3236             a = mkNarrowTo32( ty, a );
3237             b = mkNarrowTo32( ty, b );
3238             putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
3239          }
3240          putCR0( crfD, getXER_SO() );
3241          break;
3242
3243       default:
3244          vex_printf("dis_int_cmp(ppc)(opc2)\n");
3245          return False;
3246       }
3247       break;
3248       
3249    default:
3250       vex_printf("dis_int_cmp(ppc)(opc1)\n");
3251       return False;
3252    }
3253    
3254    return True;
3255 }
3256
3257
3258 /*
3259   Integer Logical Instructions
3260 */
3261 static Bool dis_int_logic ( UInt theInstr )
3262 {
3263    /* D-Form, X-Form */
3264    UChar opc1    = ifieldOPC(theInstr);
3265    UChar rS_addr = ifieldRegDS(theInstr);
3266    UChar rA_addr = ifieldRegA(theInstr);
3267    UInt  uimm16  = ifieldUIMM16(theInstr);
3268    UChar rB_addr = ifieldRegB(theInstr);
3269    UInt  opc2    = ifieldOPClo10(theInstr);
3270    UChar flag_rC = ifieldBIT0(theInstr);
3271    
3272    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3273    IRTemp rS     = newTemp(ty);
3274    IRTemp rA     = newTemp(ty);
3275    IRTemp rB     = newTemp(ty);
3276    IRExpr* irx;
3277    Bool do_rc    = False;
3278
3279    assign( rS, getIReg(rS_addr) );
3280    assign( rB, getIReg(rB_addr) );
3281    
3282    switch (opc1) {
3283    case 0x1C: // andi. (AND Immediate, PPC32 p358)
3284       DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3285       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3286                          mkSzImm(ty, uimm16)) );
3287       do_rc = True;  // Always record to CR
3288       flag_rC = 1;
3289       break;
3290       
3291    case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
3292       DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3293       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3294                          mkSzImm(ty, uimm16 << 16)) );
3295       do_rc = True;  // Always record to CR
3296       flag_rC = 1;
3297       break;
3298
3299    case 0x18: // ori (OR Immediate, PPC32 p497)
3300       DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3301       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3302                          mkSzImm(ty, uimm16)) );
3303       break;
3304
3305    case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
3306       DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3307       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3308                          mkSzImm(ty, uimm16 << 16)) );
3309       break;
3310
3311    case 0x1A: // xori (XOR Immediate, PPC32 p550)
3312       DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3313       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
3314                          mkSzImm(ty, uimm16)) );
3315       break;
3316
3317    case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
3318       DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3319       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
3320                          mkSzImm(ty, uimm16 << 16)) );
3321       break;
3322
3323    /* X Form */
3324    case 0x1F:
3325       do_rc = True;    // All below record to CR
3326
3327       switch (opc2) {
3328       case 0x01C: // and (AND, PPC32 p356)
3329          DIP("and%s r%u,r%u,r%u\n",
3330              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3331          assign(rA, binop( mkSzOp(ty, Iop_And8),
3332                            mkexpr(rS), mkexpr(rB)));
3333          break;
3334          
3335       case 0x03C: // andc (AND with Complement, PPC32 p357)
3336          DIP("andc%s r%u,r%u,r%u\n",
3337              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3338          assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3339                            unop( mkSzOp(ty, Iop_Not8),
3340                                  mkexpr(rB))));
3341          break;
3342          
3343       case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
3344          IRExpr* lo32;
3345          if (rB_addr!=0) {
3346             vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
3347             return False;
3348          }
3349          DIP("cntlzw%s r%u,r%u\n",
3350              flag_rC ? ".":"", rA_addr, rS_addr);
3351          
3352          // mode64: count in low word only
3353          lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
3354          
3355          // Iop_Clz32 undefined for arg==0, so deal with that case:
3356          irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
3357          assign(rA, mkWidenFrom32(ty,
3358                          IRExpr_Mux0X( unop(Iop_1Uto8, irx),
3359                                        mkU32(32),
3360                                        unop(Iop_Clz32, lo32)),
3361                          False));
3362
3363          // TODO: alternatively: assign(rA, verbose_Clz32(rS));
3364          break;
3365       }
3366          
3367       case 0x11C: // eqv (Equivalent, PPC32 p396)
3368          DIP("eqv%s r%u,r%u,r%u\n",
3369              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3370          assign( rA, unop( mkSzOp(ty, Iop_Not8),
3371                            binop( mkSzOp(ty, Iop_Xor8),
3372                                   mkexpr(rS), mkexpr(rB))) );
3373          break;
3374
3375       case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
3376          if (rB_addr!=0) {
3377             vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
3378             return False;
3379          }
3380          DIP("extsb%s r%u,r%u\n",
3381              flag_rC ? ".":"", rA_addr, rS_addr);
3382          if (mode64)
3383             assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
3384          else
3385             assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
3386          break;
3387
3388       case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
3389          if (rB_addr!=0) {
3390             vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
3391             return False;
3392          }
3393          DIP("extsh%s r%u,r%u\n",
3394              flag_rC ? ".":"", rA_addr, rS_addr);
3395          if (mode64)
3396             assign( rA, unop(Iop_16Sto64,
3397                              unop(Iop_64to16, mkexpr(rS))) );
3398          else
3399             assign( rA, unop(Iop_16Sto32,
3400                              unop(Iop_32to16, mkexpr(rS))) );
3401          break;
3402
3403       case 0x1DC: // nand (NAND, PPC32 p492)
3404          DIP("nand%s r%u,r%u,r%u\n",
3405              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3406          assign( rA, unop( mkSzOp(ty, Iop_Not8),
3407                            binop( mkSzOp(ty, Iop_And8),
3408                                   mkexpr(rS), mkexpr(rB))) );
3409          break;
3410          
3411       case 0x07C: // nor (NOR, PPC32 p494)
3412          DIP("nor%s r%u,r%u,r%u\n",
3413              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3414          assign( rA, unop( mkSzOp(ty, Iop_Not8),
3415                            binop( mkSzOp(ty, Iop_Or8),
3416                                   mkexpr(rS), mkexpr(rB))) );
3417          break;
3418
3419       case 0x1BC: // or (OR, PPC32 p495)
3420          if ((!flag_rC) && rS_addr == rB_addr) {
3421             DIP("mr r%u,r%u\n", rA_addr, rS_addr);
3422             assign( rA, mkexpr(rS) );
3423          } else {
3424             DIP("or%s r%u,r%u,r%u\n",
3425                 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3426             assign( rA, binop( mkSzOp(ty, Iop_Or8),
3427                                mkexpr(rS), mkexpr(rB)) );
3428          }
3429          break;
3430
3431       case 0x19C: // orc  (OR with Complement, PPC32 p496)
3432          DIP("orc%s r%u,r%u,r%u\n",
3433              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3434          assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3435                             unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
3436          break;
3437          
3438       case 0x13C: // xor (XOR, PPC32 p549)
3439          DIP("xor%s r%u,r%u,r%u\n",
3440              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3441          assign( rA, binop( mkSzOp(ty, Iop_Xor8),
3442                             mkexpr(rS), mkexpr(rB)) );
3443          break;
3444
3445
3446       /* 64bit Integer Logical Instructions */
3447       case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
3448          if (rB_addr!=0) {
3449             vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
3450             return False;
3451          }
3452          DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
3453          assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
3454          break;
3455
3456       case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
3457          if (rB_addr!=0) {
3458             vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
3459             return False;
3460          }
3461          DIP("cntlzd%s r%u,r%u\n",
3462              flag_rC ? ".":"", rA_addr, rS_addr);
3463          // Iop_Clz64 undefined for arg==0, so deal with that case:
3464          irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
3465          assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx),
3466                                   mkU64(64),
3467                                   unop(Iop_Clz64, mkexpr(rS)) ));
3468          // TODO: alternatively: assign(rA, verbose_Clz64(rS));
3469          break;
3470
3471       case 0x1FC: // cmpb (Power6: compare bytes)
3472          DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
3473
3474          if (mode64)
3475             assign( rA, unop( Iop_V128to64,
3476                               binop( Iop_CmpEQ8x16,
3477                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
3478                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
3479                                      )) );
3480          else
3481             assign( rA, unop( Iop_V128to32,
3482                               binop( Iop_CmpEQ8x16,
3483                                      unop( Iop_32UtoV128, mkexpr(rS) ),
3484                                      unop( Iop_32UtoV128, mkexpr(rB) )
3485                                      )) );
3486          break;
3487
3488       case 0x2DF: { // mftgpr (move floating-point to general purpose register)
3489          IRTemp frB = newTemp(Ity_F64);
3490          DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
3491
3492          assign( frB, getFReg(rB_addr));  // always F64
3493          if (mode64)
3494             assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
3495          else
3496             assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
3497
3498          putIReg( rS_addr, mkexpr(rA));
3499          return True;
3500       }
3501
3502       case 0x25F: { // mffgpr (move floating-point from general purpose register)
3503          IRTemp frA = newTemp(Ity_F64);
3504          DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
3505
3506          if (mode64)
3507             assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
3508          else
3509             assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
3510
3511          putFReg( rS_addr, mkexpr(frA));
3512          return True;
3513       }
3514       case 0x1FA: // popcntd (population count doubleword
3515       {
3516           DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
3517         IRTemp result = gen_POPCOUNT(rS);
3518           putIReg( rA_addr, mkexpr(result) );
3519           return True;
3520       }
3521
3522       default:
3523          vex_printf("dis_int_logic(ppc)(opc2)\n");
3524          return False;
3525       }
3526       break;
3527       
3528    default:
3529       vex_printf("dis_int_logic(ppc)(opc1)\n");
3530       return False;
3531    }
3532
3533    putIReg( rA_addr, mkexpr(rA) );
3534
3535    if (do_rc && flag_rC) {
3536       set_CR0( mkexpr(rA) );
3537    }
3538    return True;
3539 }
3540
3541 /*
3542   Integer Parity Instructions
3543 */
3544 static Bool dis_int_parity ( UInt theInstr )
3545 {
3546    /* X-Form */
3547    UChar opc1    = ifieldOPC(theInstr);
3548    UChar rS_addr = ifieldRegDS(theInstr);
3549    UChar rA_addr = ifieldRegA(theInstr);
3550    UChar rB_addr = ifieldRegB(theInstr);
3551    UInt  opc2    = ifieldOPClo10(theInstr);
3552    UChar b0      = ifieldBIT0(theInstr);
3553    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3554
3555    IRTemp rS     = newTemp(ty);
3556    IRTemp rA     = newTemp(ty);
3557    IRTemp iTot1  = newTemp(Ity_I32);
3558    IRTemp iTot2  = newTemp(Ity_I32);
3559    IRTemp iTot3  = newTemp(Ity_I32);
3560    IRTemp iTot4  = newTemp(Ity_I32);
3561    IRTemp iTot5  = newTemp(Ity_I32);
3562    IRTemp iTot6  = newTemp(Ity_I32);
3563    IRTemp iTot7  = newTemp(Ity_I32);
3564    IRTemp iTot8  = newTemp(Ity_I32);
3565    IRTemp rS1    = newTemp(ty);
3566    IRTemp rS2    = newTemp(ty);
3567    IRTemp rS3    = newTemp(ty);
3568    IRTemp rS4    = newTemp(ty);
3569    IRTemp rS5    = newTemp(ty);
3570    IRTemp rS6    = newTemp(ty);
3571    IRTemp rS7    = newTemp(ty);
3572    IRTemp iHi    = newTemp(Ity_I32);
3573    IRTemp iLo    = newTemp(Ity_I32);
3574    IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
3575    IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
3576
3577    if (opc1 != 0x1f || rB_addr || b0) {
3578       vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
3579       return False;
3580    }
3581
3582    assign( rS, getIReg(rS_addr) );
3583
3584    switch (opc2) {
3585    case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
3586       DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
3587       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
3588       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
3589       assign( iTot2, binop(Iop_Add32,
3590                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
3591                            mkexpr(iTot1)) );
3592       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
3593       assign( iTot3, binop(Iop_Add32,
3594                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
3595                            mkexpr(iTot2)) );
3596       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
3597       assign( iTot4, binop(Iop_Add32,
3598                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
3599                            mkexpr(iTot3)) );
3600       if (mode64) {
3601          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
3602          assign( iTot5, binop(Iop_Add32,
3603                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
3604                               mkexpr(iTot4)) );
3605          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
3606          assign( iTot6, binop(Iop_Add32,
3607                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
3608                               mkexpr(iTot5)) );
3609          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
3610          assign( iTot7, binop(Iop_Add32,
3611                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
3612                               mkexpr(iTot6)) );
3613          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
3614          assign( iTot8, binop(Iop_Add32,
3615                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
3616                               mkexpr(iTot7)) );
3617          assign( rA, unop(Iop_32Uto64,
3618                           binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
3619       } else
3620          assign( rA, mkexpr(iTot4) );
3621
3622       break;
3623    case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
3624       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
3625       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
3626       assign( iTot2, binop(Iop_Add32,
3627                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
3628                            mkexpr(iTot1)) );
3629       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
3630       assign( iTot3, binop(Iop_Add32,
3631                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
3632                            mkexpr(iTot2)) );
3633       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
3634       assign( iTot4, binop(Iop_Add32,
3635                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
3636                            mkexpr(iTot3)) );
3637       assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
3638
3639       if (mode64) {
3640          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
3641          assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
3642          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
3643          assign( iTot6, binop(Iop_Add32,
3644                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
3645                               mkexpr(iTot5)) );
3646          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
3647          assign( iTot7, binop(Iop_Add32,
3648                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
3649                               mkexpr(iTot6)) );
3650          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
3651          assign( iTot8, binop(Iop_Add32,
3652                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
3653                               mkexpr(iTot7)) );
3654          assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
3655             assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
3656       } else
3657          assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
3658       break;
3659    default:
3660       vex_printf("dis_int_parity(ppc)(opc2)\n");
3661       return False;
3662    }
3663
3664    putIReg( rA_addr, mkexpr(rA) );
3665
3666    return True;
3667 }
3668
3669
3670 /*
3671   Integer Rotate Instructions
3672 */
3673 static Bool dis_int_rot ( UInt theInstr )
3674 {
3675    /* M-Form, MDS-Form */
3676    UChar opc1    = ifieldOPC(theInstr);
3677    UChar rS_addr = ifieldRegDS(theInstr);
3678    UChar rA_addr = ifieldRegA(theInstr);
3679    UChar rB_addr = ifieldRegB(theInstr);
3680    UChar sh_imm  = rB_addr;
3681    UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
3682    UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
3683    UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
3684    UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
3685    UChar b1      = ifieldBIT1(theInstr);
3686    UChar flag_rC = ifieldBIT0(theInstr);
3687
3688    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3689    IRTemp rS     = newTemp(ty);
3690    IRTemp rA     = newTemp(ty);
3691    IRTemp rB     = newTemp(ty);
3692    IRTemp rot    = newTemp(ty);
3693    IRExpr *r;
3694    UInt   mask32;
3695    ULong  mask64;
3696
3697    assign( rS, getIReg(rS_addr) );
3698    assign( rB, getIReg(rB_addr) );
3699
3700    switch (opc1) {
3701    case 0x14: {
3702       // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
3703       DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
3704           rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
3705       if (mode64) {
3706          // tmp32 = (ROTL(rS_Lo32, Imm)
3707          // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
3708          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
3709          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
3710          r = unop(Iop_32Uto64, r);
3711          assign( rot, binop(Iop_Or64, r,
3712                             binop(Iop_Shl64, r, mkU8(32))) );
3713          assign( rA,
3714             binop(Iop_Or64,
3715                   binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
3716                   binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
3717       }
3718       else {
3719          // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
3720          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
3721          r = ROTL(mkexpr(rS), mkU8(sh_imm));
3722          assign( rA,
3723             binop(Iop_Or32,
3724                   binop(Iop_And32, mkU32(mask32), r),
3725                   binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
3726       }
3727       break;
3728    }
3729
3730    case 0x15: {
3731       // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
3732       vassert(MaskBeg < 32);
3733       vassert(MaskEnd < 32);
3734       vassert(sh_imm  < 32);
3735
3736       if (mode64) {
3737          IRTemp rTmp = newTemp(Ity_I64);
3738          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
3739          DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
3740              rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
3741          // tmp32 = (ROTL(rS_Lo32, Imm)
3742          // rA = ((tmp32 || tmp32) & mask64)
3743          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
3744          r = unop(Iop_32Uto64, r);
3745          assign( rTmp, r );
3746          r = NULL;
3747          assign( rot, binop(Iop_Or64, mkexpr(rTmp),
3748                             binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
3749          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
3750       }
3751       else {
3752          if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
3753             /* Special-case the ,n,0,31-n form as that is just n-bit
3754                shift left, PPC32 p501 */
3755             DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
3756                 rA_addr, rS_addr, sh_imm);
3757             assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
3758          }
3759          else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
3760             /* Special-case the ,32-n,n,31 form as that is just n-bit
3761                unsigned shift right, PPC32 p501 */
3762             DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
3763                 rA_addr, rS_addr, MaskBeg);
3764             assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
3765          }
3766          else {
3767             /* General case. */
3768             mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
3769             DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
3770                 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
3771             // rA = ROTL(rS, Imm) & mask
3772             assign( rA, binop(Iop_And32,
3773                               ROTL(mkexpr(rS), mkU8(sh_imm)), 
3774                               mkU32(mask32)) );
3775          }
3776       }
3777       break;
3778    }
3779
3780    case 0x17: {
3781       // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
3782       DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
3783           rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
3784       if (mode64) {
3785          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
3786          /* weird insn alert!
3787             tmp32 = (ROTL(rS_Lo32, rB[0-4])
3788             rA = ((tmp32 || tmp32) & mask64)
3789          */
3790          // note, ROTL does the masking, so we don't do it here
3791          r = ROTL( unop(Iop_64to32, mkexpr(rS)),
3792                    unop(Iop_64to8, mkexpr(rB)) );
3793          r = unop(Iop_32Uto64, r);
3794          assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
3795          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
3796       } else {
3797          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
3798          // rA = ROTL(rS, rB[0-4]) & mask
3799          // note, ROTL does the masking, so we don't do it here
3800          assign( rA, binop(Iop_And32,
3801                            ROTL(mkexpr(rS),
3802                                 unop(Iop_32to8, mkexpr(rB))),
3803                            mkU32(mask32)) );
3804       }
3805       break;
3806    }
3807
3808    /* 64bit Integer Rotates */
3809    case 0x1E: {
3810       msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
3811       sh_imm |= b1 << 5;
3812
3813       vassert( msk_imm < 64 );
3814       vassert( sh_imm < 64 );
3815
3816       switch (opc2) {
3817       case 0x4: {
3818          /* r = ROTL64( rS, rB_lo6) */
3819          r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
3820
3821          if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
3822             DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
3823                 rA_addr, rS_addr, rB_addr, msk_imm);
3824             // note, ROTL does the masking, so we don't do it here
3825             mask64 = MASK64(0, 63-msk_imm);
3826             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
3827             break;
3828          } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
3829             DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
3830                 rA_addr, rS_addr, rB_addr, msk_imm);
3831             mask64 = MASK64(63-msk_imm, 63);
3832             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
3833             break;
3834          }
3835          break;
3836       }
3837       case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
3838          DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
3839              rA_addr, rS_addr, sh_imm, msk_imm);
3840          r = ROTL(mkexpr(rS), mkU8(sh_imm));
3841          mask64 = MASK64(sh_imm, 63-msk_imm);
3842          assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
3843          break;
3844          // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
3845          /*
3846            Hmm... looks like this'll do the job more simply:
3847            r = SHL(rS, sh_imm)
3848            m = ~(1 << (63-msk_imm))
3849            assign(rA, r & m);
3850          */
3851          
3852       case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
3853          if (mode64
3854              && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
3855             /* special-case the ,64-n,n form as that is just
3856                unsigned shift-right by n */
3857             DIP("srdi%s r%u,r%u,%u\n",
3858                 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
3859             assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
3860          } else {
3861             DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
3862                 rA_addr, rS_addr, sh_imm, msk_imm);
3863             r = ROTL(mkexpr(rS), mkU8(sh_imm));
3864             mask64 = MASK64(0, 63-msk_imm);
3865             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
3866          }
3867          break;
3868          
3869       case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
3870          if (mode64 
3871              && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
3872             /* special-case the ,n,63-n form as that is just
3873                shift-left by n */
3874             DIP("sldi%s r%u,r%u,%u\n",
3875                 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
3876             assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
3877          } else {
3878             DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
3879                 rA_addr, rS_addr, sh_imm, msk_imm);
3880             r = ROTL(mkexpr(rS), mkU8(sh_imm));
3881             mask64 = MASK64(63-msk_imm, 63);
3882             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
3883          }
3884          break;
3885          
3886       case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
3887          IRTemp rA_orig = newTemp(ty);
3888          DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
3889              rA_addr, rS_addr, sh_imm, msk_imm);
3890          r = ROTL(mkexpr(rS), mkU8(sh_imm));
3891          mask64 = MASK64(sh_imm, 63-msk_imm);
3892          assign( rA_orig, getIReg(rA_addr) );
3893          assign( rA, binop(Iop_Or64,
3894                            binop(Iop_And64, mkU64(mask64),  r),
3895                            binop(Iop_And64, mkU64(~mask64),
3896                                             mkexpr(rA_orig))) );
3897          break;
3898       }
3899       default:
3900          vex_printf("dis_int_rot(ppc)(opc2)\n");
3901          return False;
3902       }
3903       break;         
3904    }
3905
3906    default:
3907       vex_printf("dis_int_rot(ppc)(opc1)\n");
3908       return False;
3909    }
3910
3911    putIReg( rA_addr, mkexpr(rA) );
3912
3913    if (flag_rC) {
3914       set_CR0( mkexpr(rA) );
3915    }
3916    return True;
3917 }
3918
3919
3920 /*
3921   Integer Load Instructions
3922 */
3923 static Bool dis_int_load ( UInt theInstr )
3924 {
3925    /* D-Form, X-Form, DS-Form */
3926    UChar opc1     = ifieldOPC(theInstr);
3927    UChar rD_addr  = ifieldRegDS(theInstr);
3928    UChar rA_addr  = ifieldRegA(theInstr);
3929    UInt  uimm16   = ifieldUIMM16(theInstr);
3930    UChar rB_addr  = ifieldRegB(theInstr);
3931    UInt  opc2     = ifieldOPClo10(theInstr);
3932    UChar b1       = ifieldBIT1(theInstr);
3933    UChar b0       = ifieldBIT0(theInstr);
3934
3935    Int     simm16 = extend_s_16to32(uimm16);
3936    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
3937    IRTemp  EA     = newTemp(ty);
3938    IRExpr* val;
3939
3940    switch (opc1) {
3941    case 0x1F: // register offset
3942       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
3943       break;
3944    case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
3945               // lowest 2 bits of immediate before forming EA
3946       simm16 = simm16 & 0xFFFFFFFC;
3947    default:   // immediate offset
3948       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
3949       break;
3950    }
3951
3952    switch (opc1) {
3953    case 0x22: // lbz (Load B & Zero, PPC32 p433)
3954       DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3955       val = loadBE(Ity_I8, mkexpr(EA));
3956       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
3957       break;
3958       
3959    case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
3960       if (rA_addr == 0 || rA_addr == rD_addr) {
3961          vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
3962          return False;
3963       }
3964       DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3965       val = loadBE(Ity_I8, mkexpr(EA));
3966       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
3967       putIReg( rA_addr, mkexpr(EA) );
3968       break;
3969       
3970    case 0x2A: // lha (Load HW Alg, PPC32 p445)
3971       DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3972       val = loadBE(Ity_I16, mkexpr(EA));
3973       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
3974       break;
3975
3976    case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
3977       if (rA_addr == 0 || rA_addr == rD_addr) {
3978          vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
3979          return False;
3980       }
3981       DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3982       val = loadBE(Ity_I16, mkexpr(EA));
3983       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
3984       putIReg( rA_addr, mkexpr(EA) );
3985       break;
3986       
3987    case 0x28: // lhz (Load HW & Zero, PPC32 p450)
3988       DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3989       val = loadBE(Ity_I16, mkexpr(EA));
3990       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
3991       break;
3992       
3993    case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
3994       if (rA_addr == 0 || rA_addr == rD_addr) {
3995          vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
3996          return False;
3997       }
3998       DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3999       val = loadBE(Ity_I16, mkexpr(EA));
4000       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4001       putIReg( rA_addr, mkexpr(EA) );
4002       break;
4003
4004    case 0x20: // lwz (Load W & Zero, PPC32 p460)
4005       DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4006       val = loadBE(Ity_I32, mkexpr(EA));
4007       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4008       break;
4009       
4010    case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
4011       if (rA_addr == 0 || rA_addr == rD_addr) {
4012          vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
4013          return False;
4014       }
4015       DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4016       val = loadBE(Ity_I32, mkexpr(EA));
4017       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4018       putIReg( rA_addr, mkexpr(EA) );
4019       break;
4020       
4021    /* X Form */
4022    case 0x1F:
4023       if (b0 != 0) {
4024          vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
4025          return False;
4026       }
4027
4028       switch (opc2) {
4029       case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
4030          DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4031          if (rA_addr == 0 || rA_addr == rD_addr) {
4032             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
4033             return False;
4034          }
4035          val = loadBE(Ity_I8, mkexpr(EA));
4036          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4037          putIReg( rA_addr, mkexpr(EA) );
4038          break;
4039          
4040       case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
4041          DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4042          val = loadBE(Ity_I8, mkexpr(EA));
4043          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4044          break;
4045          
4046       case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
4047          if (rA_addr == 0 || rA_addr == rD_addr) {
4048             vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
4049             return False;
4050          }
4051          DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4052          val = loadBE(Ity_I16, mkexpr(EA));
4053          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4054          putIReg( rA_addr, mkexpr(EA) );
4055          break;
4056          
4057       case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
4058          DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4059          val = loadBE(Ity_I16, mkexpr(EA));
4060          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4061          break;
4062          
4063       case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
4064          if (rA_addr == 0 || rA_addr == rD_addr) {
4065             vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
4066             return False;
4067          }
4068          DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4069          val = loadBE(Ity_I16, mkexpr(EA));
4070          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4071          putIReg( rA_addr, mkexpr(EA) );
4072          break;
4073          
4074       case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
4075          DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4076          val = loadBE(Ity_I16, mkexpr(EA));
4077          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4078          break;
4079
4080       case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
4081          if (rA_addr == 0 || rA_addr == rD_addr) {
4082             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
4083             return False;
4084          }
4085          DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4086          val = loadBE(Ity_I32, mkexpr(EA));
4087          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4088          putIReg( rA_addr, mkexpr(EA) );
4089          break;
4090          
4091       case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
4092          DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4093          val = loadBE(Ity_I32, mkexpr(EA));
4094          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4095          break;
4096
4097
4098       /* 64bit Loads */
4099       case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
4100          if (rA_addr == 0 || rA_addr == rD_addr) {
4101             vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
4102             return False;
4103          }
4104          DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4105          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4106          putIReg( rA_addr, mkexpr(EA) );
4107          break;
4108
4109       case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
4110          DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4111          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4112          break;
4113
4114       case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
4115          if (rA_addr == 0 || rA_addr == rD_addr) {
4116             vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
4117             return False;
4118          }
4119          DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4120          putIReg( rD_addr,
4121                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4122          putIReg( rA_addr, mkexpr(EA) );
4123          break;
4124
4125       case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
4126          DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4127          putIReg( rD_addr,
4128                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4129          break;
4130
4131       default:
4132          vex_printf("dis_int_load(ppc)(opc2)\n");
4133          return False;
4134       }
4135       break;
4136
4137    /* DS Form - 64bit Loads.  In each case EA will have been formed
4138       with the lowest 2 bits masked off the immediate offset. */
4139    case 0x3A:
4140       switch ((b1<<1) | b0) {
4141       case 0x0: // ld (Load DWord, PPC64 p472)
4142          DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4143          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4144          break;
4145
4146       case 0x1: // ldu (Load DWord, Update, PPC64 p474)
4147          if (rA_addr == 0 || rA_addr == rD_addr) {
4148             vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
4149             return False;
4150          }
4151          DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4152          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4153          putIReg( rA_addr, mkexpr(EA) );
4154          break;
4155
4156       case 0x2: // lwa (Load Word Alg, PPC64 p499)
4157          DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4158          putIReg( rD_addr,
4159                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4160          break;
4161
4162       default:
4163          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
4164          return False;
4165       }
4166       break;
4167
4168    default:
4169       vex_printf("dis_int_load(ppc)(opc1)\n");
4170       return False;
4171    }
4172    return True;
4173 }
4174
4175
4176
4177 /*
4178   Integer Store Instructions
4179 */
4180 static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi )
4181 {
4182    /* D-Form, X-Form, DS-Form */
4183    UChar opc1    = ifieldOPC(theInstr);
4184    UInt  rS_addr = ifieldRegDS(theInstr);
4185    UInt  rA_addr = ifieldRegA(theInstr);
4186    UInt  uimm16  = ifieldUIMM16(theInstr);
4187    UInt  rB_addr = ifieldRegB(theInstr);
4188    UInt  opc2    = ifieldOPClo10(theInstr);
4189    UChar b1      = ifieldBIT1(theInstr);
4190    UChar b0      = ifieldBIT0(theInstr);
4191
4192    Int    simm16 = extend_s_16to32(uimm16);
4193    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4194    IRTemp rS     = newTemp(ty);
4195    IRTemp rB     = newTemp(ty);
4196    IRTemp EA     = newTemp(ty);
4197    
4198    assign( rB, getIReg(rB_addr) );
4199    assign( rS, getIReg(rS_addr) );
4200    
4201    switch (opc1) {
4202    case 0x1F: // register offset
4203       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
4204       break;
4205    case 0x3E: // immediate offset: 64bit: std/stdu: mask off
4206               // lowest 2 bits of immediate before forming EA
4207       simm16 = simm16 & 0xFFFFFFFC;
4208    default:   // immediate offset
4209       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
4210       break;
4211    }
4212
4213    switch (opc1) {
4214    case 0x26: // stb (Store B, PPC32 p509)
4215       DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4216       storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4217       break;
4218        
4219    case 0x27: // stbu (Store B, Update, PPC32 p510)
4220       if (rA_addr == 0 ) {
4221          vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
4222          return False;
4223       }
4224       DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4225       putIReg( rA_addr, mkexpr(EA) );
4226       storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4227       break;
4228
4229    case 0x2C: // sth (Store HW, PPC32 p522)
4230       DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4231       storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4232       break;
4233       
4234    case 0x2D: // sthu (Store HW, Update, PPC32 p524)
4235       if (rA_addr == 0) {
4236          vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
4237          return False;
4238       }
4239       DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4240       putIReg( rA_addr, mkexpr(EA) );
4241       storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4242       break;
4243
4244    case 0x24: // stw (Store W, PPC32 p530)
4245       DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4246       storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4247       break;
4248
4249    case 0x25: // stwu (Store W, Update, PPC32 p534)
4250       if (rA_addr == 0) {
4251          vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
4252          return False;
4253       }
4254       DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4255       putIReg( rA_addr, mkexpr(EA) );
4256       storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4257       break;
4258       
4259    /* X Form : all these use EA_indexed */
4260    case 0x1F:
4261       if (b0 != 0) {
4262          vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
4263          return False;
4264       }
4265
4266       switch (opc2) {
4267       case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
4268          if (rA_addr == 0) {
4269             vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
4270             return False;
4271          }
4272          DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4273          putIReg( rA_addr, mkexpr(EA) );
4274          storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4275          break;
4276          
4277       case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
4278          DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4279          storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4280          break;
4281          
4282       case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
4283          if (rA_addr == 0) {
4284             vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
4285             return False;
4286          }
4287          DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4288          putIReg( rA_addr, mkexpr(EA) );
4289          storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4290          break;
4291          
4292       case 0x197: // sthx (Store HW Indexed, PPC32 p526)
4293          DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4294          storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4295          break;
4296          
4297       case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
4298          if (rA_addr == 0) {
4299             vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
4300             return False;
4301          }
4302          DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4303          putIReg( rA_addr, mkexpr(EA) );
4304          storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4305          break;
4306
4307       case 0x097: // stwx (Store W Indexed, PPC32 p536)
4308          DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4309          storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4310          break;
4311          
4312
4313       /* 64bit Stores */
4314       case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
4315          if (rA_addr == 0) {
4316             vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
4317             return False;
4318          }
4319          DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4320          putIReg( rA_addr, mkexpr(EA) );
4321          storeBE( mkexpr(EA), mkexpr(rS) );
4322          break;
4323
4324       case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
4325          DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4326          storeBE( mkexpr(EA), mkexpr(rS) );
4327          break;
4328
4329       default:
4330          vex_printf("dis_int_store(ppc)(opc2)\n");
4331          return False;
4332       }
4333       break;
4334
4335    /* DS Form - 64bit Stores.  In each case EA will have been formed
4336       with the lowest 2 bits masked off the immediate offset. */
4337    case 0x3E:
4338       switch ((b1<<1) | b0) {
4339       case 0x0: // std (Store DWord, PPC64 p580)
4340          DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4341          storeBE( mkexpr(EA), mkexpr(rS) );
4342          break;
4343
4344       case 0x1: // stdu (Store DWord, Update, PPC64 p583)
4345          DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4346          putIReg( rA_addr, mkexpr(EA) );
4347          storeBE( mkexpr(EA), mkexpr(rS) );
4348          break;
4349
4350       default:
4351          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
4352          return False;
4353       }
4354       break;
4355
4356    default:
4357       vex_printf("dis_int_store(ppc)(opc1)\n");
4358       return False;
4359    }
4360    return True;
4361 }
4362
4363
4364
4365 /*
4366   Integer Load/Store Multiple Instructions
4367 */
4368 static Bool dis_int_ldst_mult ( UInt theInstr )
4369 {
4370    /* D-Form */
4371    UChar opc1     = ifieldOPC(theInstr);
4372    UChar rD_addr  = ifieldRegDS(theInstr);
4373    UChar rS_addr  = rD_addr;
4374    UChar rA_addr  = ifieldRegA(theInstr);
4375    UInt  uimm16   = ifieldUIMM16(theInstr);
4376
4377    Int     simm16 = extend_s_16to32(uimm16);
4378    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
4379    IRTemp  EA     = newTemp(ty);
4380    UInt    r      = 0;
4381    UInt    ea_off = 0;
4382    IRExpr* irx_addr;
4383
4384    assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
4385
4386    switch (opc1) {
4387    case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
4388       if (rA_addr >= rD_addr) {
4389          vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
4390          return False;
4391       }
4392       DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4393       for (r = rD_addr; r <= 31; r++) {
4394          irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
4395          putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ),
4396                                        False) );
4397          ea_off += 4;
4398       }
4399       break;
4400       
4401    case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
4402       DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4403       for (r = rS_addr; r <= 31; r++) {
4404          irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
4405          storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
4406          ea_off += 4;
4407       }
4408       break;
4409       
4410    default:
4411       vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
4412       return False;
4413    }
4414    return True;
4415 }
4416
4417
4418
4419 /*
4420   Integer Load/Store String Instructions
4421 */
4422 static 
4423 void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
4424                              IRTemp EA,        // EA
4425                              Int    rD,        // first dst register
4426                              Int    maxBytes ) // 32 or 128
4427 {
4428    Int     i, shift = 24;
4429    IRExpr* e_nbytes = mkexpr(tNBytes);
4430    IRExpr* e_EA     = mkexpr(EA);
4431    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
4432
4433    vassert(rD >= 0 && rD < 32);
4434    rD--; if (rD < 0) rD = 31;
4435
4436    for (i = 0; i < maxBytes; i++) {
4437       /* if (nBytes < (i+1)) goto NIA; */
4438       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
4439                          Ijk_Boring, 
4440                          mkSzConst( ty, nextInsnAddr()) ));
4441       /* when crossing into a new dest register, set it to zero. */
4442       if ((i % 4) == 0) {
4443          rD++; if (rD == 32) rD = 0;
4444          putIReg(rD, mkSzImm(ty, 0));
4445          shift = 24;
4446       }
4447       /* rD |=  (8Uto32(*(EA+i))) << shift */
4448       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
4449       putIReg( 
4450          rD, 
4451          mkWidenFrom32(
4452             ty, 
4453             binop(
4454                Iop_Or32, 
4455                mkNarrowTo32(ty, getIReg(rD)),
4456                binop(
4457                   Iop_Shl32, 
4458                   unop(
4459                      Iop_8Uto32, 
4460                      loadBE(Ity_I8, 
4461                             binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)))
4462                   ), 
4463                   mkU8(toUChar(shift))
4464                )
4465             ),
4466             /*Signed*/False
4467          ) 
4468       ); 
4469       shift -= 8;
4470    }
4471 }
4472
4473 static 
4474 void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
4475                               IRTemp EA,        // EA
4476                               Int    rS,        // first src register
4477                               Int    maxBytes ) // 32 or 128
4478 {
4479    Int     i, shift = 24;
4480    IRExpr* e_nbytes = mkexpr(tNBytes);
4481    IRExpr* e_EA     = mkexpr(EA);
4482    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
4483
4484    vassert(rS >= 0 && rS < 32);
4485    rS--; if (rS < 0) rS = 31;
4486
4487    for (i = 0; i < maxBytes; i++) {
4488       /* if (nBytes < (i+1)) goto NIA; */
4489       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
4490                          Ijk_Boring, 
4491                          mkSzConst( ty, nextInsnAddr() ) ));
4492       /* check for crossing into a new src register. */
4493       if ((i % 4) == 0) {
4494          rS++; if (rS == 32) rS = 0;
4495          shift = 24;
4496       }
4497       /* *(EA+i) = 32to8(rS >> shift) */
4498       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
4499       storeBE(
4500          binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
4501          unop(Iop_32to8,
4502               binop(Iop_Shr32,
4503                     mkNarrowTo32(ty, getIReg(rS)),
4504                     mkU8(toUChar(shift))))
4505       );
4506       shift -= 8;
4507    }
4508 }
4509
4510 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
4511 {
4512    /* X-Form */
4513    UChar opc1     = ifieldOPC(theInstr);
4514    UChar rD_addr  = ifieldRegDS(theInstr);
4515    UChar rS_addr  = rD_addr;
4516    UChar rA_addr  = ifieldRegA(theInstr);
4517    UChar rB_addr  = ifieldRegB(theInstr);
4518    UChar NumBytes = rB_addr;
4519    UInt  opc2     = ifieldOPClo10(theInstr);
4520    UChar b0       = ifieldBIT0(theInstr);
4521
4522    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
4523    IRTemp t_EA    = newTemp(ty);
4524    IRTemp t_nbytes = IRTemp_INVALID;
4525
4526    *stopHere = False;
4527
4528    if (opc1 != 0x1F || b0 != 0) {
4529       vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
4530       return False;
4531    }
4532
4533    switch (opc2) {
4534    case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
4535       /* NB: does not reject the case where RA is in the range of
4536          registers to be loaded.  It should. */
4537       DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
4538       assign( t_EA, ea_rAor0(rA_addr) );
4539       if (NumBytes == 8 && !mode64) {
4540          /* Special case hack */
4541          /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
4542          putIReg( rD_addr,          
4543                   loadBE(Ity_I32, mkexpr(t_EA)) );
4544          putIReg( (rD_addr+1) % 32, 
4545                   loadBE(Ity_I32,
4546                          binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
4547       } else {
4548          t_nbytes = newTemp(Ity_I32);
4549          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
4550          generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
4551          *stopHere = True;
4552       }
4553       return True;
4554
4555    case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
4556       /* NB: does not reject the case where RA is in the range of
4557          registers to be loaded.  It should.  Although considering
4558          that that can only be detected at run time, it's not easy to
4559          do so. */
4560       if (rD_addr == rA_addr || rD_addr == rB_addr)
4561          return False;
4562       if (rD_addr == 0 && rA_addr == 0)
4563          return False;
4564       DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4565       t_nbytes = newTemp(Ity_I32);
4566       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
4567       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
4568       generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
4569       *stopHere = True;
4570       return True;
4571
4572    case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
4573       DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
4574       assign( t_EA, ea_rAor0(rA_addr) );
4575       if (NumBytes == 8 && !mode64) {
4576          /* Special case hack */
4577          /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
4578          storeBE( mkexpr(t_EA), 
4579                   getIReg(rD_addr) );
4580          storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)), 
4581                   getIReg((rD_addr+1) % 32) );
4582       } else {
4583          t_nbytes = newTemp(Ity_I32);
4584          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
4585          generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
4586          *stopHere = True;
4587       }
4588       return True;
4589
4590    case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
4591       DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4592       t_nbytes = newTemp(Ity_I32);
4593       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
4594       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
4595       generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
4596       *stopHere = True;
4597       return True;
4598
4599    default:
4600       vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
4601       return False;
4602    }
4603    return True;
4604 }
4605
4606
4607 /* ------------------------------------------------------------------
4608    Integer Branch Instructions
4609    ------------------------------------------------------------------ */
4610
4611 /*
4612   Branch helper function
4613   ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
4614   Returns an I32 which is 0x00000000 if the ctr condition failed
4615   and 0xFFFFFFFF otherwise.
4616 */
4617 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
4618 {
4619    IRType ty = mode64 ? Ity_I64 : Ity_I32;
4620    IRTemp ok = newTemp(Ity_I32);
4621
4622    if ((BO >> 2) & 1) {     // independent of ctr
4623       assign( ok, mkU32(0xFFFFFFFF) );
4624    } else {
4625       if ((BO >> 1) & 1) {  // ctr == 0 ?
4626          assign( ok, unop( Iop_1Sto32,
4627                            binop( mkSzOp(ty, Iop_CmpEQ8),
4628                                   getGST( PPC_GST_CTR ),
4629                                   mkSzImm(ty,0))) );
4630       } else {              // ctr != 0 ?
4631          assign( ok, unop( Iop_1Sto32,
4632                            binop( mkSzOp(ty, Iop_CmpNE8),
4633                                   getGST( PPC_GST_CTR ),
4634                                   mkSzImm(ty,0))) );
4635       }
4636    }
4637    return mkexpr(ok);
4638 }
4639
4640
4641 /*
4642   Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
4643   Returns an I32 which is either 0 if the condition failed or 
4644   some arbitrary nonzero value otherwise. */
4645
4646 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
4647 {
4648    Int where;
4649    IRTemp res   = newTemp(Ity_I32);
4650    IRTemp cr_bi = newTemp(Ity_I32);
4651    
4652    if ((BO >> 4) & 1) {
4653       assign( res, mkU32(1) );
4654    } else {
4655       // ok = (CR[BI] == BO[3]) Note, the following relies on
4656       // getCRbit_anywhere returning a value which
4657       // is either zero or has exactly 1 bit set.  
4658       assign( cr_bi, getCRbit_anywhere( BI, &where ) );
4659
4660       if ((BO >> 3) & 1) {
4661          /* We can use cr_bi as-is. */
4662          assign( res, mkexpr(cr_bi) );
4663       } else {
4664          /* We have to invert the sense of the information held in
4665             cr_bi.  For that we need to know which bit
4666             getCRbit_anywhere regards as significant. */
4667          assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
4668                                        mkU32(1<<where)) );
4669       }
4670    }
4671    return mkexpr(res);
4672 }
4673
4674
4675 /*
4676   Integer Branch Instructions
4677 */
4678 static Bool dis_branch ( UInt theInstr, 
4679                          VexAbiInfo* vbi,
4680                          /*OUT*/DisResult* dres,
4681                          Bool (*resteerOkFn)(void*,Addr64),
4682                          void* callback_opaque )
4683 {
4684    UChar opc1    = ifieldOPC(theInstr);
4685    UChar BO      = ifieldRegDS(theInstr);
4686    UChar BI      = ifieldRegA(theInstr);
4687    UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
4688    UChar b11to15 = ifieldRegB(theInstr);
4689    UInt  opc2    = ifieldOPClo10(theInstr);
4690    UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
4691    UChar flag_AA = ifieldBIT1(theInstr);
4692    UChar flag_LK = ifieldBIT0(theInstr);
4693
4694    IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
4695    Addr64   tgt       = 0;
4696    Int      BD        = extend_s_16to32(BD_u16);
4697    IRTemp   do_branch = newTemp(Ity_I32);
4698    IRTemp   ctr_ok    = newTemp(Ity_I32);
4699    IRTemp   cond_ok   = newTemp(Ity_I32);
4700    IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
4701    IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
4702    IRTemp   lr_old    = newTemp(ty);
4703
4704    /* Hack to pass through code that just wants to read the PC */
4705    if (theInstr == 0x429F0005) {
4706       DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
4707       putGST( PPC_GST_LR, e_nia );
4708       return True;
4709    }
4710
4711    /* The default what-next.  Individual cases can override it. */    
4712    dres->whatNext = Dis_StopHere;
4713
4714    switch (opc1) {
4715    case 0x12: // b     (Branch, PPC32 p360)
4716       if (flag_AA) {
4717          tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
4718       } else {
4719          tgt = mkSzAddr( ty, guest_CIA_curr_instr +
4720                              (Long)extend_s_26to64(LI_u26) );
4721       }
4722       if (mode64) {
4723          DIP("b%s%s 0x%llx\n",
4724              flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
4725       } else {
4726          DIP("b%s%s 0x%x\n",
4727              flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
4728       }
4729
4730       if (flag_LK) {
4731          putGST( PPC_GST_LR, e_nia );
4732          if (vbi->guest_ppc_zap_RZ_at_bl
4733              && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
4734             IRTemp t_tgt = newTemp(ty);
4735             assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
4736             make_redzone_AbiHint( vbi, t_tgt,
4737                                   "branch-and-link (unconditional call)" );
4738          }
4739       }
4740
4741       if (resteerOkFn( callback_opaque, tgt )) {
4742          dres->whatNext   = Dis_ResteerU;
4743          dres->continueAt = tgt;
4744       } else {
4745          irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
4746          irsb->next     = mkSzImm(ty, tgt);
4747       }
4748       break;
4749       
4750    case 0x10: // bc    (Branch Conditional, PPC32 p361)
4751       DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
4752           flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
4753       
4754       if (!(BO & 0x4)) {
4755          putGST( PPC_GST_CTR,
4756                  binop(mkSzOp(ty, Iop_Sub8),
4757                        getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
4758       }
4759
4760       /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
4761          cond_ok is either zero or nonzero, since that's the cheapest
4762          way to compute it.  Anding them together gives a value which
4763          is either zero or non zero and so that's what we must test
4764          for in the IRStmt_Exit. */
4765       assign( ctr_ok,  branch_ctr_ok( BO ) );
4766       assign( cond_ok, branch_cond_ok( BO, BI ) );
4767       assign( do_branch,
4768               binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
4769
4770       if (flag_AA) {
4771          tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
4772       } else {
4773          tgt = mkSzAddr(ty, guest_CIA_curr_instr +
4774                             (Long)extend_s_16to64(BD_u16));
4775       }
4776       if (flag_LK)
4777          putGST( PPC_GST_LR, e_nia );
4778       
4779       stmt( IRStmt_Exit(
4780                binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
4781                flag_LK ? Ijk_Call : Ijk_Boring,
4782                mkSzConst(ty, tgt) ) );
4783       
4784       irsb->jumpkind = Ijk_Boring;
4785       irsb->next     = e_nia;
4786       break;
4787       
4788    case 0x13:
4789       /* For bclr and bcctr, it appears that the lowest two bits of
4790          b11to15 are a branch hint, and so we only need to ensure it's
4791          of the form 000XX. */
4792       if ((b11to15 & ~3) != 0) {
4793          vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15);
4794          return False;
4795       }
4796
4797       switch (opc2) {
4798       case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363) 
4799          if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
4800             vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
4801             return False;
4802          }
4803          DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
4804          
4805          assign( cond_ok, branch_cond_ok( BO, BI ) );
4806
4807          /* FIXME: this is confusing.  lr_old holds the old value
4808             of ctr, not lr :-) */
4809          assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
4810
4811          if (flag_LK)
4812             putGST( PPC_GST_LR, e_nia );
4813          
4814          stmt( IRStmt_Exit(
4815                   binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
4816                   Ijk_Boring,
4817                   c_nia ));
4818
4819          if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
4820             make_redzone_AbiHint( vbi, lr_old,
4821                                   "b-ctr-l (indirect call)" );
4822          }
4823
4824          irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
4825          irsb->next     = mkexpr(lr_old);
4826          break;
4827          
4828       case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365) 
4829          Bool vanilla_return = False;
4830          if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
4831             DIP("blr\n");
4832             vanilla_return = True;
4833          } else {
4834             DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
4835          }
4836
4837          if (!(BO & 0x4)) {
4838             putGST( PPC_GST_CTR,
4839                     binop(mkSzOp(ty, Iop_Sub8),
4840                           getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
4841          }
4842          
4843          /* See comments above for 'bc' about this */
4844          assign( ctr_ok,  branch_ctr_ok( BO ) );
4845          assign( cond_ok, branch_cond_ok( BO, BI ) );
4846          assign( do_branch,
4847                  binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
4848          
4849          assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
4850
4851          if (flag_LK)
4852             putGST( PPC_GST_LR,  e_nia );
4853
4854          stmt( IRStmt_Exit(
4855                   binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
4856                   Ijk_Boring,
4857                   c_nia ));
4858
4859          if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
4860             make_redzone_AbiHint( vbi, lr_old,
4861                                   "branch-to-lr (unconditional return)" );
4862          }
4863
4864          /* blrl is pretty strange; it's like a return that sets the
4865             return address of its caller to the insn following this
4866             one.  Mark it as a return. */
4867          irsb->jumpkind = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
4868          irsb->next     = mkexpr(lr_old);
4869          break;
4870       }
4871       default:
4872          vex_printf("dis_int_branch(ppc)(opc2)\n");
4873          return False;
4874       }
4875       break;
4876       
4877    default:
4878       vex_printf("dis_int_branch(ppc)(opc1)\n");
4879       return False;
4880    }
4881    
4882    return True;
4883 }
4884
4885
4886
4887 /*
4888   Condition Register Logical Instructions
4889 */
4890 static Bool dis_cond_logic ( UInt theInstr )
4891 {
4892    /* XL-Form */
4893    UChar opc1      = ifieldOPC(theInstr);
4894    UChar crbD_addr = ifieldRegDS(theInstr);
4895    UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
4896    UChar crbA_addr = ifieldRegA(theInstr);
4897    UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
4898    UChar crbB_addr = ifieldRegB(theInstr);
4899    UInt  opc2      = ifieldOPClo10(theInstr);
4900    UChar b0        = ifieldBIT0(theInstr);
4901
4902    IRTemp crbD     = newTemp(Ity_I32);
4903    IRTemp crbA     = newTemp(Ity_I32);
4904    IRTemp crbB     = newTemp(Ity_I32);
4905
4906    if (opc1 != 19 || b0 != 0) {
4907       vex_printf("dis_cond_logic(ppc)(opc1)\n");
4908       return False;
4909    }
4910
4911    if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
4912       if (((crbD_addr & 0x3) != 0) ||
4913           ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
4914          vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
4915          return False;
4916       }
4917       DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
4918       putCR0(   crfD_addr, getCR0(  crfS_addr) );
4919       putCR321( crfD_addr, getCR321(crfS_addr) );
4920    } else {
4921       assign( crbA, getCRbit(crbA_addr) );
4922       if (crbA_addr == crbB_addr)
4923          crbB = crbA;
4924       else
4925          assign( crbB, getCRbit(crbB_addr) );
4926
4927       switch (opc2) {
4928       case 0x101: // crand   (Cond Reg AND, PPC32 p372)
4929          DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4930          assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
4931          break;
4932       case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
4933          DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4934          assign( crbD, binop(Iop_And32, 
4935                              mkexpr(crbA),
4936                              unop(Iop_Not32, mkexpr(crbB))) );
4937          break;
4938       case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
4939          DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4940          assign( crbD, unop(Iop_Not32,
4941                             binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
4942          break;
4943       case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
4944          DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4945          assign( crbD, unop(Iop_Not32,
4946                             binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
4947          break;
4948       case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
4949          DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4950          assign( crbD, unop(Iop_Not32,
4951                             binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
4952          break;
4953       case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
4954          DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4955          assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
4956          break;
4957       case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
4958          DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4959          assign( crbD, binop(Iop_Or32, 
4960                              mkexpr(crbA),
4961                              unop(Iop_Not32, mkexpr(crbB))) );
4962          break;
4963       case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
4964          DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4965          assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
4966          break;
4967       default:
4968          vex_printf("dis_cond_logic(ppc)(opc2)\n");
4969          return False;
4970       }
4971
4972       putCRbit( crbD_addr, mkexpr(crbD) );
4973    }
4974    return True;
4975 }
4976
4977
4978 /* 
4979   Trap instructions
4980 */
4981
4982 /* Do the code generation for a trap.  Returned Bool is true iff
4983    this is an unconditional trap.  If the two arg IRExpr*s are 
4984    Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
4985    then they are 64-bit, and we must be disassembling 64-bit
4986    instructions. */
4987 static Bool do_trap ( UChar TO, 
4988                       IRExpr* argL0, IRExpr* argR0, Addr64 cia )
4989 {
4990    IRTemp argL, argR;
4991    IRExpr *argLe, *argRe, *cond, *tmp;
4992
4993    Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
4994
4995    IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
4996    IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
4997    IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
4998    IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
4999    IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
5000    IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
5001    IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
5002    IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
5003    IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
5004    IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
5005
5006    const UChar b11100 = 0x1C;
5007    const UChar b00111 = 0x07;
5008
5009    if (is32bit) {
5010       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
5011       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
5012    } else {
5013       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
5014       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
5015       vassert( mode64 );
5016    }
5017
5018    if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
5019       /* Unconditional trap.  Just do the exit without 
5020          testing the arguments. */
5021       stmt( IRStmt_Exit( 
5022                binop(opCMPEQ, const0, const0), 
5023                Ijk_SigTRAP,
5024                mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia) 
5025       ));
5026       return True; /* unconditional trap */
5027    }
5028
5029    if (is32bit) {
5030       argL = newTemp(Ity_I32);
5031       argR = newTemp(Ity_I32);
5032    } else {
5033       argL = newTemp(Ity_I64);
5034       argR = newTemp(Ity_I64);
5035    }
5036
5037    assign( argL, argL0 );
5038    assign( argR, argR0 );
5039
5040    argLe = mkexpr(argL);
5041    argRe = mkexpr(argR);
5042
5043    cond = const0;
5044    if (TO & 16) { // L <s R
5045       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
5046       cond = binop(opOR, tmp, cond);
5047    }
5048    if (TO & 8) { // L >s R
5049       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
5050       cond = binop(opOR, tmp, cond);
5051    }
5052    if (TO & 4) { // L == R
5053       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
5054       cond = binop(opOR, tmp, cond);
5055    }
5056    if (TO & 2) { // L <u R
5057       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
5058       cond = binop(opOR, tmp, cond);
5059    }
5060    if (TO & 1) { // L >u R
5061       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
5062       cond = binop(opOR, tmp, cond);
5063    }
5064    stmt( IRStmt_Exit( 
5065             binop(opCMPNE, cond, const0), 
5066             Ijk_SigTRAP,
5067             mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia) 
5068    ));
5069    return False; /* not an unconditional trap */
5070 }
5071
5072 static Bool dis_trapi ( UInt theInstr,
5073                         /*OUT*/DisResult* dres )
5074 {
5075    /* D-Form */
5076    UChar  opc1    = ifieldOPC(theInstr);
5077    UChar  TO      = ifieldRegDS(theInstr);
5078    UChar  rA_addr = ifieldRegA(theInstr);
5079    UInt   uimm16  = ifieldUIMM16(theInstr);
5080    ULong  simm16  = extend_s_16to64(uimm16);
5081    Addr64 cia     = guest_CIA_curr_instr;
5082    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5083    Bool   uncond  = False;
5084
5085    switch (opc1) {
5086    case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
5087       uncond = do_trap( TO, 
5088                         mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 
5089                                : getIReg(rA_addr),
5090                         mkU32( (UInt)simm16 ),
5091                         cia );
5092       if (TO == 4) {
5093          DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
5094       } else {
5095          DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
5096       }
5097       break;
5098    case 0x02: // tdi
5099       if (!mode64)
5100          return False;
5101       uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
5102       if (TO == 4) {
5103          DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
5104       } else {
5105          DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
5106       }
5107       break;
5108    default:
5109       return False;
5110    }
5111
5112    if (uncond) {
5113       /* If the trap shows signs of being unconditional, don't
5114          continue decoding past it. */
5115       irsb->next     = mkSzImm( ty, nextInsnAddr() );
5116       irsb->jumpkind = Ijk_Boring;
5117       dres->whatNext = Dis_StopHere;
5118    }
5119
5120    return True;
5121 }
5122
5123 static Bool dis_trap ( UInt theInstr,
5124                         /*OUT*/DisResult* dres )
5125 {
5126    /* X-Form */
5127    UInt   opc2    = ifieldOPClo10(theInstr);
5128    UChar  TO      = ifieldRegDS(theInstr);
5129    UChar  rA_addr = ifieldRegA(theInstr);
5130    UChar  rB_addr = ifieldRegB(theInstr);
5131    Addr64 cia     = guest_CIA_curr_instr;
5132    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5133    Bool   uncond  = False;
5134
5135    if (ifieldBIT0(theInstr) != 0)
5136       return False;
5137
5138    switch (opc2) {
5139    case 0x004: // tw  (Trap Word, PPC64 p540)
5140       uncond = do_trap( TO, 
5141                         mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 
5142                                : getIReg(rA_addr),
5143                         mode64 ? unop(Iop_64to32, getIReg(rB_addr)) 
5144                                : getIReg(rB_addr),
5145                         cia );
5146       if (TO == 4) {
5147          DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
5148       } else {
5149          DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
5150       }
5151       break;
5152    case 0x044: // td (Trap Doubleword, PPC64 p534)
5153       if (!mode64)
5154          return False;
5155       uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
5156       if (TO == 4) {
5157          DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
5158       } else {
5159          DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
5160       }
5161       break;
5162    default:
5163       return False;
5164    }
5165
5166    if (uncond) {
5167       /* If the trap shows signs of being unconditional, don't
5168          continue decoding past it. */
5169       irsb->next     = mkSzImm( ty, nextInsnAddr() );
5170       irsb->jumpkind = Ijk_Boring;
5171       dres->whatNext = Dis_StopHere;
5172    }
5173
5174    return True;
5175 }
5176
5177
5178 /*
5179   System Linkage Instructions
5180 */
5181 static Bool dis_syslink ( UInt theInstr, 
5182                           VexAbiInfo* abiinfo, DisResult* dres )
5183 {
5184    IRType ty = mode64 ? Ity_I64 : Ity_I32;
5185
5186    if (theInstr != 0x44000002) {
5187       vex_printf("dis_syslink(ppc)(theInstr)\n");
5188       return False;
5189    }
5190
5191    // sc  (System Call, PPC32 p504)
5192    DIP("sc\n");
5193
5194    /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX
5195       Valgrind can back the guest up to this instruction if it needs
5196       to restart the syscall. */
5197    putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
5198
5199    /* It's important that all ArchRegs carry their up-to-date value
5200       at this point.  So we declare an end-of-block here, which
5201       forces any TempRegs caching ArchRegs to be flushed. */
5202    irsb->next     = abiinfo->guest_ppc_sc_continues_at_LR
5203                        ? getGST( PPC_GST_LR )
5204                        : mkSzImm( ty, nextInsnAddr() );
5205    irsb->jumpkind = Ijk_Sys_syscall;
5206
5207    dres->whatNext = Dis_StopHere;
5208    return True;
5209 }
5210
5211
5212 /*
5213   Memory Synchronization Instructions
5214
5215   Note on Reservations:
5216   We rely on the assumption that V will in fact only allow one thread at
5217   once to run.  In effect, a thread can make a reservation, but we don't
5218   check any stores it does.  Instead, the reservation is cancelled when
5219   the scheduler switches to another thread (run_thread_for_a_while()).
5220 */
5221 static Bool dis_memsync ( UInt theInstr )
5222 {
5223    /* X-Form, XL-Form */
5224    UChar opc1    = ifieldOPC(theInstr);
5225    UInt  b11to25 = IFIELD(theInstr, 11, 15);
5226    UChar flag_L  = ifieldRegDS(theInstr);
5227    UInt  b11to20 = IFIELD(theInstr, 11, 10);
5228    UChar rD_addr = ifieldRegDS(theInstr);
5229    UChar rS_addr = rD_addr;
5230    UChar rA_addr = ifieldRegA(theInstr);
5231    UChar rB_addr = ifieldRegB(theInstr);
5232    UInt  opc2    = ifieldOPClo10(theInstr);
5233    UChar b0      = ifieldBIT0(theInstr);
5234
5235    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
5236    IRTemp EA     = newTemp(ty);
5237
5238    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5239
5240    switch (opc1) {
5241    /* XL-Form */
5242    case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
5243       if (opc2 != 0x096) {
5244          vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
5245          return False;
5246       }
5247       if (b11to25 != 0 || b0 != 0) {
5248          vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
5249          return False;
5250       }
5251       DIP("isync\n");
5252       stmt( IRStmt_MBE(Imbe_Fence) );
5253       break;
5254
5255    /* X-Form */
5256    case 0x1F:
5257       switch (opc2) {
5258       case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394)
5259          if (b11to25 != 0 || b0 != 0) {
5260             vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n");
5261             return False;
5262          }
5263          DIP("eieio\n");
5264          /* Insert a memory fence, just to be on the safe side. */
5265          stmt( IRStmt_MBE(Imbe_Fence) );
5266          break;
5267
5268       case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
5269          IRTemp res;
5270          /* According to the PowerPC ISA version 2.05, b0 (called EH
5271             in the documentation) is merely a hint bit to the
5272             hardware, I think as to whether or not contention is
5273             likely.  So we can just ignore it. */
5274          DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
5275
5276          // trap if misaligned
5277          gen_SIGBUS_if_misaligned( EA, 4 );
5278
5279          // and actually do the load
5280          res = newTemp(Ity_I32);
5281          stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
5282
5283          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
5284          break;
5285       }
5286
5287       case 0x096: { 
5288          // stwcx. (Store Word Conditional Indexed, PPC32 p532)
5289          // Note this has to handle stwcx. in both 32- and 64-bit modes,
5290          // so isn't quite as straightforward as it might otherwise be.
5291          IRTemp rS = newTemp(Ity_I32);
5292          IRTemp resSC;
5293          if (b0 != 1) {
5294             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
5295             return False;
5296          }
5297          DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5298
5299          // trap if misaligned
5300          gen_SIGBUS_if_misaligned( EA, 4 );
5301
5302          // Get the data to be stored, and narrow to 32 bits if necessary
5303          assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
5304
5305          // Do the store, and get success/failure bit into resSC
5306          resSC = newTemp(Ity_I1);
5307          stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
5308
5309          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
5310          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
5311          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
5312          putCR0(0, getXER_SO());
5313
5314          /* Note:
5315             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
5316             whether rS is stored is dependent on that value. */
5317          /* So I guess we can just ignore this case? */
5318          break;
5319       }
5320
5321       case 0x256: // sync (Synchronize, PPC32 p543), 
5322                   // also lwsync (L==1), ptesync (L==2)
5323          /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
5324
5325             The PowerPC architecture used in IBM chips has expanded
5326             the sync instruction into two variants: lightweight sync
5327             and heavyweight sync.  The original sync instruction is
5328             the new heavyweight sync and lightweight sync is a strict
5329             subset of the heavyweight sync functionality. This allows
5330             the programmer to specify a less expensive operation on
5331             high-end systems when the full sync functionality is not
5332             necessary.
5333
5334             The basic "sync" mnemonic now utilizes an operand. "sync"
5335             without an operand now becomes a extended mnemonic for
5336             heavyweight sync.  Processors without the lwsync
5337             instruction will not decode the L field and will perform a
5338             heavyweight sync.  Everything is backward compatible.
5339
5340             sync    =       sync 0
5341             lwsync  =       sync 1
5342             ptesync =       sync 2    *** TODO - not implemented ***
5343          */
5344          if (b11to20 != 0 || b0 != 0) {
5345             vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
5346             return False;
5347          }
5348          if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
5349             vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
5350             return False;
5351          }
5352          DIP("%ssync\n", flag_L == 1 ? "lw" : "");
5353          /* Insert a memory fence.  It's sometimes important that these
5354             are carried through to the generated code. */
5355          stmt( IRStmt_MBE(Imbe_Fence) );
5356          break;
5357
5358       /* 64bit Memsync */
5359       case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
5360          IRTemp res;
5361          /* According to the PowerPC ISA version 2.05, b0 (called EH
5362             in the documentation) is merely a hint bit to the
5363             hardware, I think as to whether or not contention is
5364             likely.  So we can just ignore it. */
5365          if (!mode64)
5366             return False;
5367          DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
5368
5369          // trap if misaligned
5370          gen_SIGBUS_if_misaligned( EA, 8 );
5371
5372          // and actually do the load
5373          res = newTemp(Ity_I64);
5374          stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
5375
5376          putIReg( rD_addr, mkexpr(res) );
5377          break;
5378       }
5379       
5380       case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
5381          // A marginally simplified version of the stwcx. case
5382          IRTemp rS = newTemp(Ity_I64);
5383          IRTemp resSC;
5384          if (b0 != 1) {
5385             vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
5386             return False;
5387          }
5388          if (!mode64)
5389             return False;
5390          DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5391
5392          // trap if misaligned
5393          gen_SIGBUS_if_misaligned( EA, 8 );
5394
5395          // Get the data to be stored
5396          assign( rS, getIReg(rS_addr) );
5397
5398          // Do the store, and get success/failure bit into resSC
5399          resSC = newTemp(Ity_I1);
5400          stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
5401
5402          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
5403          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
5404          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
5405          putCR0(0, getXER_SO());
5406
5407          /* Note:
5408             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
5409             whether rS is stored is dependent on that value. */
5410          /* So I guess we can just ignore this case? */
5411          break;
5412       }
5413
5414       default:
5415          vex_printf("dis_memsync(ppc)(opc2)\n");
5416          return False;
5417       }
5418       break;
5419
5420    default:
5421       vex_printf("dis_memsync(ppc)(opc1)\n");
5422       return False;
5423    }
5424    return True;
5425 }
5426
5427
5428
5429 /*
5430   Integer Shift Instructions
5431 */
5432 static Bool dis_int_shift ( UInt theInstr )
5433 {
5434    /* X-Form, XS-Form */
5435    UChar opc1    = ifieldOPC(theInstr);
5436    UChar rS_addr = ifieldRegDS(theInstr);
5437    UChar rA_addr = ifieldRegA(theInstr);
5438    UChar rB_addr = ifieldRegB(theInstr);
5439    UChar sh_imm  = rB_addr;
5440    UInt  opc2    = ifieldOPClo10(theInstr);
5441    UChar b1      = ifieldBIT1(theInstr);
5442    UChar flag_rC = ifieldBIT0(theInstr);
5443
5444    IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
5445    IRTemp  rA         = newTemp(ty);
5446    IRTemp  rS         = newTemp(ty);
5447    IRTemp  rB         = newTemp(ty);
5448    IRTemp  outofrange = newTemp(Ity_I8);
5449    IRTemp  rS_lo32    = newTemp(Ity_I32);
5450    IRTemp  rB_lo32    = newTemp(Ity_I32);
5451    IRExpr* e_tmp;
5452
5453    assign( rS, getIReg(rS_addr) );
5454    assign( rB, getIReg(rB_addr) );
5455    assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
5456    assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
5457    
5458    if (opc1 == 0x1F) {
5459       switch (opc2) {
5460       case 0x018: { // slw (Shift Left Word, PPC32 p505)
5461          DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5462              rA_addr, rS_addr, rB_addr);
5463          /* rA = rS << rB */
5464          /* ppc32 semantics are: 
5465             slw(x,y) = (x << (y & 31))         -- primary result
5466                        & ~((y << 26) >>s 31)   -- make result 0 
5467                                                   for y in 32 .. 63
5468          */
5469          e_tmp =
5470             binop( Iop_And32,
5471                binop( Iop_Shl32,
5472                       mkexpr(rS_lo32), 
5473                       unop( Iop_32to8,
5474                             binop(Iop_And32,
5475                                   mkexpr(rB_lo32), mkU32(31)))),
5476                unop( Iop_Not32,
5477                      binop( Iop_Sar32,
5478                             binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
5479                             mkU8(31))) );
5480          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
5481          break;
5482       }
5483
5484       case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
5485          IRTemp sh_amt = newTemp(Ity_I32);
5486          DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5487              rA_addr, rS_addr, rB_addr);
5488          /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
5489             amt = rB & 63
5490             rA = Sar32( rS, amt > 31 ? 31 : amt )
5491             XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
5492          */
5493          assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
5494                                           mkexpr(rB_lo32)) );
5495          assign( outofrange,
5496                  unop( Iop_1Uto8, 
5497                        binop(Iop_CmpLT32U, mkU32(31),
5498                                            mkexpr(sh_amt)) ));
5499          e_tmp = binop( Iop_Sar32, 
5500                         mkexpr(rS_lo32), 
5501                         unop( Iop_32to8, 
5502                               IRExpr_Mux0X( mkexpr(outofrange), 
5503                                             mkexpr(sh_amt), 
5504                                             mkU32(31)) ) );
5505          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
5506
5507          set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
5508                      mkexpr(rA),
5509                      mkWidenFrom32(ty, mkexpr(rS_lo32), True),
5510                      mkWidenFrom32(ty, mkexpr(sh_amt), True ),
5511                      mkWidenFrom32(ty, getXER_CA32(), True) );
5512          break;
5513       }
5514          
5515       case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
5516          DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
5517              rA_addr, rS_addr, sh_imm);
5518          vassert(sh_imm < 32);
5519          if (mode64) {
5520             assign( rA, binop(Iop_Sar64,
5521                               binop(Iop_Shl64, getIReg(rS_addr),
5522                                                mkU8(32)),
5523                               mkU8(32 + sh_imm)) );
5524          } else {
5525             assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
5526                                          mkU8(sh_imm)) );
5527          }
5528
5529          set_XER_CA( ty, PPCG_FLAG_OP_SRAWI, 
5530                      mkexpr(rA),
5531                      mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
5532                      mkSzImm(ty, sh_imm),
5533                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
5534          break;
5535       
5536       case 0x218: // srw (Shift Right Word, PPC32 p508)
5537          DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5538              rA_addr, rS_addr, rB_addr);
5539          /* rA = rS >>u rB */
5540          /* ppc32 semantics are: 
5541             srw(x,y) = (x >>u (y & 31))        -- primary result
5542                        & ~((y << 26) >>s 31)   -- make result 0 
5543                                                   for y in 32 .. 63
5544          */
5545          e_tmp = 
5546             binop(
5547                Iop_And32,
5548                binop( Iop_Shr32, 
5549                       mkexpr(rS_lo32), 
5550                       unop( Iop_32to8, 
5551                             binop(Iop_And32, mkexpr(rB_lo32),
5552                                              mkU32(31)))),
5553                unop( Iop_Not32, 
5554                      binop( Iop_Sar32, 
5555                             binop(Iop_Shl32, mkexpr(rB_lo32),
5556                                              mkU8(26)), 
5557                             mkU8(31))));
5558          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
5559          break;
5560
5561
5562       /* 64bit Shifts */
5563       case 0x01B: // sld (Shift Left DWord, PPC64 p568)
5564          DIP("sld%s r%u,r%u,r%u\n",
5565              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
5566          /* rA = rS << rB */
5567          /* ppc64 semantics are: 
5568             slw(x,y) = (x << (y & 63))         -- primary result
5569                        & ~((y << 57) >>s 63)   -- make result 0 
5570                                                   for y in 64 .. 
5571          */
5572          assign( rA,
5573             binop(
5574                Iop_And64,
5575                binop( Iop_Shl64,
5576                       mkexpr(rS), 
5577                       unop( Iop_64to8, 
5578                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
5579                unop( Iop_Not64,
5580                      binop( Iop_Sar64,
5581                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 
5582                             mkU8(63)))) );
5583          break;
5584       
5585       case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
5586          IRTemp sh_amt = newTemp(Ity_I64);
5587          DIP("srad%s r%u,r%u,r%u\n",
5588              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
5589          /* amt = rB & 127
5590             rA = Sar64( rS, amt > 63 ? 63 : amt )
5591             XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
5592          */
5593          assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
5594          assign( outofrange,
5595                  unop( Iop_1Uto8, 
5596                        binop(Iop_CmpLT64U, mkU64(63),
5597                                            mkexpr(sh_amt)) ));
5598          assign( rA,
5599                  binop( Iop_Sar64, 
5600                         mkexpr(rS), 
5601                         unop( Iop_64to8, 
5602                               IRExpr_Mux0X( mkexpr(outofrange), 
5603                                             mkexpr(sh_amt), 
5604                                             mkU64(63)) ))
5605                );
5606          set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
5607                      mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
5608                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
5609          break;
5610       }
5611
5612       case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
5613          sh_imm |= b1<<5;
5614          vassert(sh_imm < 64);
5615          DIP("sradi%s r%u,r%u,%u\n",
5616              flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
5617          assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
5618
5619          set_XER_CA( ty, PPCG_FLAG_OP_SRADI, 
5620                      mkexpr(rA),
5621                      getIReg(rS_addr),
5622                      mkU64(sh_imm), 
5623                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
5624          break;
5625
5626       case 0x21B: // srd (Shift Right DWord, PPC64 p574)
5627          DIP("srd%s r%u,r%u,r%u\n",
5628              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
5629          /* rA = rS >>u rB */
5630          /* ppc semantics are: 
5631             srw(x,y) = (x >>u (y & 63))        -- primary result
5632                        & ~((y << 57) >>s 63)   -- make result 0 
5633                                                   for y in 64 .. 127
5634          */
5635          assign( rA,
5636             binop(
5637                Iop_And64,
5638                binop( Iop_Shr64, 
5639                       mkexpr(rS), 
5640                       unop( Iop_64to8, 
5641                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
5642                unop( Iop_Not64, 
5643                      binop( Iop_Sar64, 
5644                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 
5645                             mkU8(63)))) );
5646          break;
5647      
5648       default:
5649          vex_printf("dis_int_shift(ppc)(opc2)\n");
5650          return False;
5651       }
5652    } else {
5653       vex_printf("dis_int_shift(ppc)(opc1)\n");
5654       return False;
5655    }
5656
5657    putIReg( rA_addr, mkexpr(rA) );
5658    
5659    if (flag_rC) {
5660       set_CR0( mkexpr(rA) );
5661    }
5662    return True;
5663 }
5664
5665
5666
5667 /*
5668   Integer Load/Store Reverse Instructions
5669 */
5670 /* Generates code to swap the byte order in an Ity_I32. */
5671 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
5672 {
5673    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
5674    return
5675       binop(Iop_Or32,
5676          binop(Iop_Shl32, mkexpr(t), mkU8(24)),
5677       binop(Iop_Or32,
5678          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 
5679                           mkU32(0x00FF0000)),
5680       binop(Iop_Or32,
5681          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
5682                           mkU32(0x0000FF00)),
5683          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
5684                           mkU32(0x000000FF) )
5685       )));
5686 }
5687
5688 /* Generates code to swap the byte order in the lower half of an Ity_I32,
5689    and zeroes the upper half. */
5690 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
5691 {
5692    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
5693    return
5694       binop(Iop_Or32,
5695          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
5696                           mkU32(0x0000FF00)),
5697          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
5698                           mkU32(0x000000FF))
5699       );
5700 }
5701
5702 static Bool dis_int_ldst_rev ( UInt theInstr )
5703 {
5704    /* X-Form */
5705    UChar opc1    = ifieldOPC(theInstr);
5706    UChar rD_addr = ifieldRegDS(theInstr);
5707    UChar rS_addr = rD_addr;
5708    UChar rA_addr = ifieldRegA(theInstr);
5709    UChar rB_addr = ifieldRegB(theInstr);
5710    UInt  opc2    = ifieldOPClo10(theInstr);
5711    UChar b0      = ifieldBIT0(theInstr);
5712
5713    IRType ty = mode64 ? Ity_I64 : Ity_I32;
5714    IRTemp EA = newTemp(ty);
5715    IRTemp w1 = newTemp(Ity_I32);
5716    IRTemp w2 = newTemp(Ity_I32);
5717
5718    if (opc1 != 0x1F || b0 != 0) {
5719       vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
5720       return False;
5721    }
5722
5723    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5724    
5725    switch (opc2) {
5726
5727       case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
5728          DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5729          assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) );
5730          assign( w2, gen_byterev16(w1) );
5731          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
5732                                          /* Signed */False) );
5733          break;
5734
5735       case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
5736          DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5737          assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
5738          assign( w2, gen_byterev32(w1) );
5739          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
5740                                          /* Signed */False) );
5741          break;
5742
5743       case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
5744       {
5745          IRExpr * nextAddr;
5746          IRTemp w3 = newTemp( Ity_I32 );
5747          IRTemp w4 = newTemp( Ity_I32 );
5748          DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5749          assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) );
5750          assign( w2, gen_byterev32( w1 ) );
5751          nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
5752                            ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
5753          assign( w3, loadBE( Ity_I32, nextAddr ) );
5754          assign( w4, gen_byterev32( w3 ) );
5755          putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
5756          break;
5757       }
5758
5759       case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
5760          DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5761          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
5762          storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
5763          break;
5764       
5765       case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
5766          DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5767          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
5768          storeBE( mkexpr(EA), gen_byterev32(w1) );
5769          break;
5770       
5771       default:
5772          vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
5773          return False;
5774    }
5775    return True;
5776 }
5777
5778
5779
5780 /*
5781   Processor Control Instructions
5782 */
5783 static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr )
5784 {
5785    UChar opc1     = ifieldOPC(theInstr);
5786    
5787    /* X-Form */
5788    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
5789    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
5790    UChar rD_addr  = ifieldRegDS(theInstr);
5791    UInt  b11to20  = IFIELD( theInstr, 11, 10 );
5792
5793    /* XFX-Form */
5794    UChar rS_addr  = rD_addr;
5795    UInt  SPR      = b11to20;
5796    UInt  TBR      = b11to20;
5797    UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
5798    UInt  CRM      = IFIELD( theInstr, 12, 8 );
5799    UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
5800
5801    UInt  opc2     = ifieldOPClo10(theInstr);
5802    UChar b0       = ifieldBIT0(theInstr);
5803
5804    IRType ty = mode64 ? Ity_I64 : Ity_I32;
5805    IRTemp rS = newTemp(ty);
5806    assign( rS, getIReg(rS_addr) );
5807
5808    /* Reorder SPR field as per PPC32 p470 */
5809    SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
5810    /* Reorder TBR field as per PPC32 p475 */
5811    TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
5812    
5813    if (opc1 != 0x1F || b0 != 0) {
5814       vex_printf("dis_proc_ctl(ppc)(opc1|b0)\n");
5815       return False;
5816    }
5817    
5818    switch (opc2) {
5819    /* X-Form */
5820    case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
5821       if (b21to22 != 0 || b11to20 != 0) {
5822          vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
5823          return False;
5824       }
5825       DIP("mcrxr crf%d\n", crfD);
5826       /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
5827       putGST_field( PPC_GST_CR,
5828                     getGST_field( PPC_GST_XER, 7 ),
5829                     crfD );
5830
5831       // Clear XER[0-3]
5832       putXER_SO( mkU8(0) );
5833       putXER_OV( mkU8(0) );
5834       putXER_CA( mkU8(0) );
5835       break;
5836    }
5837       
5838    case 0x013: 
5839       // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
5840       // b20==1 & b11==0: mfocrf (Move from One CR Field)
5841       // However it seems that the 'mfcr' behaviour is an acceptable
5842       // implementation of mfocr (from the 2.02 arch spec)
5843       if (b11to20 == 0) {
5844          DIP("mfcr r%u\n", rD_addr);
5845          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
5846                                          /* Signed */False) );
5847          break;
5848       }
5849       if (b20 == 1 && b11 == 0) {
5850          DIP("mfocrf r%u,%u\n", rD_addr, CRM);
5851          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
5852                                          /* Signed */False) );
5853          break;
5854       }
5855       /* not decodable */
5856       return False;
5857     
5858    /* XFX-Form */
5859    case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
5860       
5861       switch (SPR) {  // Choose a register...
5862       case 0x1:
5863          DIP("mfxer r%u\n", rD_addr);
5864          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
5865                                          /* Signed */False) );
5866          break;
5867       case 0x8:
5868          DIP("mflr r%u\n", rD_addr);
5869          putIReg( rD_addr, getGST( PPC_GST_LR ) ); 
5870          break;
5871       case 0x9:
5872          DIP("mfctr r%u\n", rD_addr);
5873          putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 
5874          break;
5875       case 0x100: 
5876          DIP("mfvrsave r%u\n", rD_addr);
5877          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
5878                                          /* Signed */False) );
5879          break;
5880
5881       case 0x103:
5882          DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
5883          putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
5884          break;
5885
5886       /* Even a lowly PPC7400 can run the associated helper, so no
5887          obvious need for feature testing at this point. */
5888       case 268 /* 0x10C */:
5889       case 269 /* 0x10D */: {
5890          UInt     arg  = SPR==268 ? 0 : 1;
5891          IRTemp   val  = newTemp(Ity_I32);
5892          IRExpr** args = mkIRExprVec_1( mkU32(arg) );
5893          IRDirty* d    = unsafeIRDirty_1_N(
5894                             val,
5895                             0/*regparms*/,
5896                             "ppc32g_dirtyhelper_MFSPR_268_269",
5897                             fnptr_to_fnentry
5898                                (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
5899                             args
5900                          );
5901          /* execute the dirty call, dumping the result in val. */
5902          stmt( IRStmt_Dirty(d) );
5903          putIReg( rD_addr,
5904                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
5905          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
5906          break;
5907       }
5908
5909       /* Again, runs natively on PPC7400 (7447, really).  Not
5910          bothering with a feature test. */
5911       case 287: /* 0x11F */ {
5912          IRTemp   val  = newTemp(Ity_I32);
5913          IRExpr** args = mkIRExprVec_0();
5914          IRDirty* d    = unsafeIRDirty_1_N(
5915                             val,
5916                             0/*regparms*/,
5917                             "ppc32g_dirtyhelper_MFSPR_287",
5918                             fnptr_to_fnentry
5919                                (vbi, &ppc32g_dirtyhelper_MFSPR_287),
5920                             args
5921                          );
5922          /* execute the dirty call, dumping the result in val. */
5923          stmt( IRStmt_Dirty(d) );
5924          putIReg( rD_addr,
5925                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
5926          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
5927          break;
5928       }
5929
5930       default:
5931          vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
5932          return False;
5933       }
5934       break;
5935       
5936    case 0x173: { // mftb (Move from Time Base, PPC32 p475)
5937       IRTemp   val  = newTemp(Ity_I64);
5938       IRExpr** args = mkIRExprVec_0();
5939       IRDirty* d    = unsafeIRDirty_1_N(
5940                               val, 
5941                               0/*regparms*/, 
5942                               "ppcg_dirtyhelper_MFTB", 
5943                               fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB), 
5944                               args );
5945       /* execute the dirty call, dumping the result in val. */
5946       stmt( IRStmt_Dirty(d) );
5947
5948       switch (TBR) {
5949       case 269: 
5950          DIP("mftbu r%u", rD_addr);
5951          putIReg( rD_addr,
5952                   mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
5953                                 /* Signed */False) );
5954          break;
5955       case 268: 
5956          DIP("mftb r%u", rD_addr);
5957          putIReg( rD_addr, (mode64) ? mkexpr(val) :
5958                                       unop(Iop_64to32, mkexpr(val)) );
5959          break;
5960       default:
5961          return False; /* illegal instruction */
5962       }
5963       break;
5964    }
5965
5966    case 0x090: { 
5967       // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
5968       // b20==1: mtocrf (Move to One Cond Reg Field)
5969       Int   cr;
5970       UChar shft;
5971       if (b11 != 0)
5972          return False;
5973       if (b20 == 1) {
5974          /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
5975             1 field is written.  It seems more robust to decline to
5976             decode the insn if so. */
5977          switch (CRM) {
5978             case 0x01: case 0x02: case 0x04: case 0x08:
5979             case 0x10: case 0x20: case 0x40: case 0x80:
5980                break;
5981             default: 
5982                return False; 
5983          }
5984       }
5985       DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf", 
5986                            CRM, rS_addr);
5987       /* Write to each field specified by CRM */
5988       for (cr = 0; cr < 8; cr++) {
5989          if ((CRM & (1 << (7-cr))) == 0)
5990             continue;
5991          shft = 4*(7-cr);
5992          putGST_field( PPC_GST_CR,
5993                        binop(Iop_Shr32,
5994                              mkNarrowTo32(ty, mkexpr(rS)),
5995                              mkU8(shft)), cr );
5996       }
5997       break;
5998    }
5999
6000    case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
6001       
6002       switch (SPR) {  // Choose a register...
6003       case 0x1:
6004          DIP("mtxer r%u\n", rS_addr);
6005          putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
6006          break;
6007       case 0x8:
6008          DIP("mtlr r%u\n", rS_addr);
6009          putGST( PPC_GST_LR, mkexpr(rS) ); 
6010          break;
6011       case 0x9:
6012          DIP("mtctr r%u\n", rS_addr);
6013          putGST( PPC_GST_CTR, mkexpr(rS) ); 
6014          break;
6015       case 0x100:
6016          DIP("mtvrsave r%u\n", rS_addr);
6017          putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
6018          break;
6019          
6020       default:
6021          vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
6022          return False;
6023       }
6024       break;
6025       
6026    default:
6027       vex_printf("dis_proc_ctl(ppc)(opc2)\n");
6028       return False;
6029    }
6030    return True;
6031 }
6032
6033
6034 /*
6035   Cache Management Instructions
6036 */
6037 static Bool dis_cache_manage ( UInt         theInstr, 
6038                                DisResult*   dres,
6039                                VexArchInfo* guest_archinfo )
6040 {
6041    /* X-Form */
6042    UChar opc1    = ifieldOPC(theInstr);
6043    UChar b21to25 = ifieldRegDS(theInstr);
6044    UChar rA_addr = ifieldRegA(theInstr);
6045    UChar rB_addr = ifieldRegB(theInstr);
6046    UInt  opc2    = ifieldOPClo10(theInstr);
6047    UChar b0      = ifieldBIT0(theInstr);
6048    UInt  lineszB = guest_archinfo->ppc_cache_line_szB;
6049    Bool  is_dcbzl = False;
6050
6051    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6052
6053    /* For dcbt, the lowest two bits of b21to25 encode an
6054       access-direction hint (TH field) which we ignore.  Well, that's
6055       what the PowerPC documentation says.  In fact xlc -O4 on POWER5
6056       seems to generate values of 8 and 10 for b21to25. */
6057    if (opc1 == 0x1F && opc2 == 0x116) {
6058      /* b21to25 &= ~3; */ /* if the docs were true */
6059      b21to25 = 0; /* blunt instrument */
6060    }
6061    if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
6062       if (b21to25 == 1) {
6063          is_dcbzl = True;
6064          b21to25 = 0;
6065          if (!(guest_archinfo->ppc_dcbzl_szB)) {
6066             vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
6067             return False;
6068          }
6069       }
6070    }
6071
6072    if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
6073       if (0) vex_printf("dis_cache_manage %d %d %d\n", 
6074                         (Int)opc1, (Int)b21to25, (Int)b0);
6075       vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n");
6076       return False;
6077    }
6078
6079    /* stay sane .. */
6080    vassert(lineszB == 32 || lineszB == 64 || lineszB == 128);
6081    
6082    switch (opc2) {
6083 //zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
6084 //zz       vassert(0); /* AWAITING TEST CASE */
6085 //zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
6086 //zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
6087 //zz       break;
6088       
6089    case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
6090       DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
6091       /* nop as far as vex is concerned */
6092       break;
6093       
6094    case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
6095       DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
6096       /* nop as far as vex is concerned */
6097       break;
6098
6099    case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
6100       DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
6101       /* nop as far as vex is concerned */
6102       break;
6103       
6104    case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
6105       DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
6106       /* nop as far as vex is concerned */
6107       break;
6108       
6109    case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
6110                  // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
6111       /* Clear all bytes in cache block at (rA|0) + rB. */
6112       IRTemp  EA   = newTemp(ty);
6113       IRTemp  addr = newTemp(ty);
6114       IRExpr* irx_addr;
6115       UInt    i;
6116       UInt clearszB;
6117       if (is_dcbzl) {
6118           clearszB = guest_archinfo->ppc_dcbzl_szB;
6119           DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
6120       }
6121       else {
6122           clearszB = guest_archinfo->ppc_dcbz_szB;
6123           DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
6124       }
6125
6126       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6127
6128       if (mode64) {
6129          /* Round EA down to the start of the containing block. */
6130          assign( addr, binop( Iop_And64,
6131                               mkexpr(EA),
6132                               mkU64( ~((ULong)clearszB-1) )) );
6133          
6134          for (i = 0; i < clearszB / 8; i++) {
6135             irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
6136             storeBE( irx_addr, mkU64(0) );
6137          }
6138       } else {
6139          /* Round EA down to the start of the containing block. */
6140          assign( addr, binop( Iop_And32,
6141                               mkexpr(EA),
6142                               mkU32( ~(clearszB-1) )) );
6143          
6144          for (i = 0; i < clearszB / 4; i++) {
6145             irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
6146             storeBE( irx_addr, mkU32(0) );
6147          }
6148       }
6149       break;
6150    }
6151
6152    case 0x3D6: { 
6153       // icbi (Instruction Cache Block Invalidate, PPC32 p431)
6154       /* Invalidate all translations containing code from the cache
6155          block at (rA|0) + rB. */
6156       IRTemp EA   = newTemp(ty);
6157       IRTemp addr = newTemp(ty);
6158       DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
6159       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6160
6161       /* Round EA down to the start of the containing block. */
6162       assign( addr, binop( mkSzOp(ty, Iop_And8),
6163                            mkexpr(EA),
6164                            mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
6165       putGST( PPC_GST_TISTART, mkexpr(addr) );
6166       putGST( PPC_GST_TILEN, mkSzImm(ty, lineszB) );
6167
6168       /* be paranoid ... */
6169       stmt( IRStmt_MBE(Imbe_Fence) );
6170
6171       irsb->jumpkind = Ijk_TInval;
6172       irsb->next     = mkSzImm(ty, nextInsnAddr());
6173       dres->whatNext = Dis_StopHere;
6174       break;
6175    }
6176
6177    default:
6178       vex_printf("dis_cache_manage(ppc)(opc2)\n");
6179       return False;
6180    }
6181    return True;
6182 }
6183
6184
6185 /*------------------------------------------------------------*/
6186 /*--- Floating Point Helpers                               ---*/
6187 /*------------------------------------------------------------*/
6188
6189 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
6190 /* Produces a value in 0 .. 3, which is encoded as per the type
6191    IRRoundingMode.  PPCRoundingMode encoding is different to
6192    IRRoundingMode, so need to map it.
6193 */
6194 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
6195 {
6196 /* 
6197    rounding mode | PPC | IR
6198    ------------------------
6199    to nearest    | 00  | 00
6200    to zero       | 01  | 11
6201    to +infinity  | 10  | 10
6202    to -infinity  | 11  | 01
6203 */
6204    IRTemp rm_PPC32 = newTemp(Ity_I32);
6205    assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
6206
6207    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
6208    return binop( Iop_Xor32, 
6209                  mkexpr(rm_PPC32),
6210                  binop( Iop_And32, 
6211                         binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
6212                         mkU32(2) ));
6213 }
6214
6215
6216 /*------------------------------------------------------------*/
6217 /*--- Floating Point Instruction Translation               ---*/
6218 /*------------------------------------------------------------*/
6219
6220 /*
6221   Floating Point Load Instructions
6222 */
6223 static Bool dis_fp_load ( UInt theInstr )
6224 {
6225    /* X-Form, D-Form */
6226    UChar opc1      = ifieldOPC(theInstr);
6227    UChar frD_addr  = ifieldRegDS(theInstr);
6228    UChar rA_addr   = ifieldRegA(theInstr);
6229    UChar rB_addr   = ifieldRegB(theInstr);
6230    UInt  opc2      = ifieldOPClo10(theInstr);
6231    UChar b0        = ifieldBIT0(theInstr);
6232    UInt  uimm16    = ifieldUIMM16(theInstr);
6233
6234    Int    simm16 = extend_s_16to32(uimm16);
6235    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6236    IRTemp EA     = newTemp(ty);
6237    IRTemp rA     = newTemp(ty);
6238    IRTemp rB     = newTemp(ty);
6239    IRTemp iHi    = newTemp(Ity_I32);
6240    IRTemp iLo    = newTemp(Ity_I32);
6241
6242    assign( rA, getIReg(rA_addr) );
6243    assign( rB, getIReg(rB_addr) );
6244
6245    /* These are completely straightforward from a rounding and status
6246       bits perspective: no rounding involved and no funny status or CR
6247       bits affected. */
6248
6249    switch (opc1) {
6250    case 0x30: // lfs (Load Float Single, PPC32 p441)
6251       DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6252       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6253       putFReg( frD_addr,
6254                unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6255       break;
6256
6257    case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
6258       if (rA_addr == 0)
6259          return False;
6260       DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6261       assign( EA, ea_rA_simm(rA_addr, simm16) );
6262       putFReg( frD_addr,
6263                unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6264       putIReg( rA_addr, mkexpr(EA) );
6265       break;
6266       
6267    case 0x32: // lfd (Load Float Double, PPC32 p437)
6268       DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6269       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6270       putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6271       break;
6272
6273    case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
6274       if (rA_addr == 0)
6275          return False;
6276       DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6277       assign( EA, ea_rA_simm(rA_addr, simm16) );
6278       putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6279       putIReg( rA_addr, mkexpr(EA) );
6280       break;
6281
6282    case 0x1F:
6283       if (b0 != 0) {
6284          vex_printf("dis_fp_load(ppc)(instr,b0)\n");
6285          return False;
6286       }
6287
6288       switch(opc2) {
6289       case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
6290          DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6291          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6292          putFReg( frD_addr, unop( Iop_F32toF64, 
6293                                   loadBE(Ity_F32, mkexpr(EA))) );
6294          break;
6295          
6296       case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
6297          if (rA_addr == 0)
6298             return False;
6299          DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6300          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6301          putFReg( frD_addr,
6302                   unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6303          putIReg( rA_addr, mkexpr(EA) );
6304          break;
6305          
6306       case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
6307          DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6308          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6309          putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6310          break;
6311          
6312       case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
6313          if (rA_addr == 0)
6314             return False;
6315          DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6316          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6317          putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6318          putIReg( rA_addr, mkexpr(EA) );
6319          break;
6320          
6321       case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
6322          DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6323          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6324          assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
6325          assign( iHi, binop(Iop_Sub32,
6326                             mkU32(0),
6327                             binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
6328          putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
6329                                  binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
6330          break;
6331
6332       case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
6333       {
6334          IRTemp dw = newTemp( Ity_I64 );
6335          DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6336          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6337          assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
6338          assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
6339          putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
6340          break;
6341       }
6342
6343       default:
6344          vex_printf("dis_fp_load(ppc)(opc2)\n");
6345          return False;
6346       }
6347       break;
6348
6349    default:
6350       vex_printf("dis_fp_load(ppc)(opc1)\n");
6351       return False;
6352    }
6353    return True;
6354 }
6355
6356
6357
6358 /*
6359   Floating Point Store Instructions
6360 */
6361 static Bool dis_fp_store ( UInt theInstr )
6362 {
6363    /* X-Form, D-Form */
6364    UChar opc1      = ifieldOPC(theInstr);
6365    UChar frS_addr  = ifieldRegDS(theInstr);
6366    UChar rA_addr   = ifieldRegA(theInstr);
6367    UChar rB_addr   = ifieldRegB(theInstr);
6368    UInt  opc2      = ifieldOPClo10(theInstr);
6369    UChar b0        = ifieldBIT0(theInstr);
6370    Int   uimm16    = ifieldUIMM16(theInstr);
6371
6372    Int    simm16 = extend_s_16to32(uimm16);
6373    IRTemp frS    = newTemp(Ity_F64);
6374    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6375    IRTemp EA     = newTemp(ty);
6376    IRTemp rA     = newTemp(ty);
6377    IRTemp rB     = newTemp(ty);
6378
6379    assign( frS, getFReg(frS_addr) );
6380    assign( rA,  getIReg(rA_addr) );
6381    assign( rB,  getIReg(rB_addr) );
6382
6383    /* These are straightforward from a status bits perspective: no
6384       funny status or CR bits affected.  For single precision stores,
6385       the values are truncated and denormalised (not rounded) to turn
6386       them into single precision values. */
6387
6388    switch (opc1) {
6389
6390    case 0x34: // stfs (Store Float Single, PPC32 p518)
6391       DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6392       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6393       /* Use Iop_TruncF64asF32 to truncate and possible denormalise
6394          the value to be stored in the correct way, without any
6395          rounding. */
6396       storeBE( mkexpr(EA),
6397                unop(Iop_TruncF64asF32, mkexpr(frS)) );
6398       break;
6399
6400    case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
6401       if (rA_addr == 0)
6402          return False;
6403       DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6404       assign( EA, ea_rA_simm(rA_addr, simm16) );
6405       /* See comment for stfs */
6406       storeBE( mkexpr(EA),
6407                unop(Iop_TruncF64asF32, mkexpr(frS)) );
6408       putIReg( rA_addr, mkexpr(EA) );
6409       break;
6410
6411    case 0x36: // stfd (Store Float Double, PPC32 p513)
6412       DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6413       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6414       storeBE( mkexpr(EA), mkexpr(frS) );
6415       break;
6416
6417    case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
6418       if (rA_addr == 0)
6419          return False;
6420       DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6421       assign( EA, ea_rA_simm(rA_addr, simm16) );
6422       storeBE( mkexpr(EA), mkexpr(frS) );
6423       putIReg( rA_addr, mkexpr(EA) );
6424       break;
6425
6426    case 0x1F:
6427       if (b0 != 0) {
6428          vex_printf("dis_fp_store(ppc)(instr,b0)\n");
6429          return False;
6430       }
6431       switch(opc2) {
6432       case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
6433          DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6434          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6435          /* See note for stfs */
6436          storeBE( mkexpr(EA), 
6437                   unop(Iop_TruncF64asF32, mkexpr(frS)) );
6438          break;
6439          
6440       case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
6441          if (rA_addr == 0)
6442             return False;
6443          DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6444          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6445          /* See note for stfs */
6446          storeBE( mkexpr(EA), 
6447                   unop(Iop_TruncF64asF32, mkexpr(frS)) );
6448          putIReg( rA_addr, mkexpr(EA) );
6449          break;
6450
6451       case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
6452          DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6453          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6454          storeBE( mkexpr(EA), mkexpr(frS) );
6455          break;
6456          
6457       case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
6458          if (rA_addr == 0)
6459             return False;
6460          DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6461          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6462          storeBE( mkexpr(EA), mkexpr(frS) );
6463          putIReg( rA_addr, mkexpr(EA) );
6464          break;
6465
6466       case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
6467          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6468          DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6469          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6470          storeBE( mkexpr(EA),
6471                   unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
6472          break;
6473
6474       default:
6475          vex_printf("dis_fp_store(ppc)(opc2)\n");
6476          return False;
6477       }
6478       break;
6479
6480    default:
6481       vex_printf("dis_fp_store(ppc)(opc1)\n");
6482       return False;
6483    }
6484    return True;
6485 }
6486
6487
6488
6489 /*
6490   Floating Point Arith Instructions
6491 */
6492 static Bool dis_fp_arith ( UInt theInstr )
6493 {
6494    /* A-Form */
6495    UChar opc1     = ifieldOPC(theInstr);
6496    UChar frD_addr = ifieldRegDS(theInstr);
6497    UChar frA_addr = ifieldRegA(theInstr);
6498    UChar frB_addr = ifieldRegB(theInstr);
6499    UChar frC_addr = ifieldRegC(theInstr);
6500    UChar opc2     = ifieldOPClo5(theInstr);
6501    UChar flag_rC  = ifieldBIT0(theInstr);
6502
6503    IRTemp  frD = newTemp(Ity_F64);
6504    IRTemp  frA = newTemp(Ity_F64);
6505    IRTemp  frB = newTemp(Ity_F64);
6506    IRTemp  frC = newTemp(Ity_F64);
6507    IRExpr* rm  = get_IR_roundingmode();
6508
6509    /* By default, we will examine the results of the operation and set
6510       fpscr[FPRF] accordingly. */
6511    Bool set_FPRF = True;
6512
6513    /* By default, if flag_RC is set, we will clear cr1 after the
6514       operation.  In reality we should set cr1 to indicate the
6515       exception status of the operation, but since we're not
6516       simulating exceptions, the exception status will appear to be
6517       zero.  Hence cr1 should be cleared if this is a . form insn. */
6518    Bool clear_CR1 = True;
6519
6520    assign( frA, getFReg(frA_addr));
6521    assign( frB, getFReg(frB_addr));
6522    assign( frC, getFReg(frC_addr));
6523
6524    switch (opc1) {
6525    case 0x3B:
6526       switch (opc2) {
6527       case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
6528          if (frC_addr != 0)
6529             return False;
6530          DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6531              frD_addr, frA_addr, frB_addr);
6532          assign( frD, triop( Iop_DivF64r32, 
6533                              rm, mkexpr(frA), mkexpr(frB) ));
6534          break;
6535
6536       case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
6537          if (frC_addr != 0)
6538             return False;
6539          DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6540              frD_addr, frA_addr, frB_addr);
6541          assign( frD, triop( Iop_SubF64r32, 
6542                              rm, mkexpr(frA), mkexpr(frB) ));
6543          break;
6544
6545       case 0x15: // fadds (Floating Add Single, PPC32 p401)
6546          if (frC_addr != 0)
6547             return False;
6548          DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6549              frD_addr, frA_addr, frB_addr);
6550          assign( frD, triop( Iop_AddF64r32, 
6551                              rm, mkexpr(frA), mkexpr(frB) ));
6552          break;
6553
6554       case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
6555          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
6556          if (frA_addr != 0 || frC_addr != 0)
6557             return False;
6558          DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
6559              frD_addr, frB_addr);
6560          // however illogically, on ppc970 this insn behaves identically
6561          // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
6562          assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
6563          break;
6564
6565       case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
6566          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6567          if (frA_addr != 0 || frC_addr != 0)
6568             return False;
6569          DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
6570              frD_addr, frB_addr);
6571          { IRExpr* ieee_one
6572               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
6573            assign( frD, triop( Iop_DivF64r32, 
6574                                rm,
6575                                ieee_one, mkexpr(frB) ));
6576          }
6577          break;
6578
6579       case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
6580          if (frB_addr != 0)
6581             return False;
6582          DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6583              frD_addr, frA_addr, frC_addr);
6584          assign( frD, triop( Iop_MulF64r32,
6585                              rm, mkexpr(frA), mkexpr(frC) ));
6586          break;
6587
6588       case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
6589          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6590          // Undocumented instruction?
6591          if (frA_addr != 0 || frC_addr != 0)
6592             return False;
6593          DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
6594              frD_addr, frB_addr);
6595          assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
6596          break;
6597
6598       default:
6599          vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
6600          return False;
6601       }
6602       break;
6603
6604    case 0x3F:
6605       switch (opc2) {           
6606       case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
6607          if (frC_addr != 0)
6608             return False;
6609          DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6610              frD_addr, frA_addr, frB_addr);
6611          assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
6612          break;
6613
6614       case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
6615          if (frC_addr != 0)
6616             return False;
6617          DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6618              frD_addr, frA_addr, frB_addr);
6619          assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
6620          break;
6621
6622       case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
6623          if (frC_addr != 0)
6624             return False;
6625          DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6626              frD_addr, frA_addr, frB_addr);
6627          assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
6628          break;
6629
6630       case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
6631          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
6632          if (frA_addr != 0 || frC_addr != 0)
6633             return False;
6634          DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
6635              frD_addr, frB_addr);
6636          assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
6637          break;
6638
6639       case 0x17: { // fsel (Floating Select, PPC32 p426)
6640          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6641          IRTemp cc    = newTemp(Ity_I32);
6642          IRTemp cc_b0 = newTemp(Ity_I32);
6643
6644          DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6645              frD_addr, frA_addr, frC_addr, frB_addr);
6646
6647          // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
6648          // => GT|EQ == (cc & 0x1 == 0)
6649          assign( cc, binop(Iop_CmpF64, mkexpr(frA),
6650                                        IRExpr_Const(IRConst_F64(0))) );
6651          assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
6652
6653          // frD = (frA >= 0.0) ? frC : frB
6654          //     = (cc_b0 == 0) ? frC : frB
6655          assign( frD,
6656                  IRExpr_Mux0X(
6657                     unop(Iop_1Uto8,
6658                          binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0))),
6659                     mkexpr(frB),
6660                     mkexpr(frC) ));
6661
6662          /* One of the rare ones which don't mess with FPRF */
6663          set_FPRF = False;
6664          break;
6665       }
6666
6667       case 0x18: // fre (Floating Reciprocal Estimate)
6668          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6669          // Note: unclear whether this insn really exists or not
6670          // ppc970 doesn't have it, but POWER5 does
6671          if (frA_addr != 0 || frC_addr != 0)
6672             return False;
6673          DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
6674              frD_addr, frB_addr);
6675          { IRExpr* ieee_one
6676               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
6677            assign( frD, triop( Iop_DivF64, 
6678                                rm,
6679                                ieee_one, mkexpr(frB) ));
6680          }
6681          break;
6682
6683       case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
6684          if (frB_addr != 0)
6685             vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
6686          DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6687              frD_addr, frA_addr, frC_addr);
6688          assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
6689          break;
6690
6691       case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
6692          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6693          if (frA_addr != 0 || frC_addr != 0)
6694             return False;
6695          DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
6696              frD_addr, frB_addr);
6697          assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
6698          break;
6699
6700       default:
6701          vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
6702          return False;
6703       }
6704       break;
6705
6706    default:
6707       vex_printf("dis_fp_arith(ppc)(opc1)\n");
6708       return False;
6709    }
6710
6711    putFReg( frD_addr, mkexpr(frD) );
6712
6713    if (set_FPRF) {
6714       // XXX XXX XXX FIXME
6715       // set FPRF from frD
6716    }
6717
6718    if (flag_rC && clear_CR1) {
6719       putCR321( 1, mkU8(0) );
6720       putCR0( 1, mkU8(0) );
6721    }
6722
6723    return True;
6724 }
6725
6726
6727
6728 /*
6729   Floating Point Mult-Add Instructions
6730 */
6731 static Bool dis_fp_multadd ( UInt theInstr )
6732 {
6733    /* A-Form */
6734    UChar opc1     = ifieldOPC(theInstr);
6735    UChar frD_addr = ifieldRegDS(theInstr);
6736    UChar frA_addr = ifieldRegA(theInstr);
6737    UChar frB_addr = ifieldRegB(theInstr);
6738    UChar frC_addr = ifieldRegC(theInstr);
6739    UChar opc2     = ifieldOPClo5(theInstr);
6740    UChar flag_rC  = ifieldBIT0(theInstr);
6741
6742    IRTemp  frD = newTemp(Ity_F64);
6743    IRTemp  frA = newTemp(Ity_F64);
6744    IRTemp  frB = newTemp(Ity_F64);
6745    IRTemp  frC = newTemp(Ity_F64);
6746    IRTemp  rmt = newTemp(Ity_I32);
6747    IRExpr* rm;
6748
6749    /* By default, we will examine the results of the operation and set
6750       fpscr[FPRF] accordingly. */
6751    Bool set_FPRF = True;
6752
6753    /* By default, if flag_RC is set, we will clear cr1 after the
6754       operation.  In reality we should set cr1 to indicate the
6755       exception status of the operation, but since we're not
6756       simulating exceptions, the exception status will appear to be
6757       zero.  Hence cr1 should be cleared if this is a . form insn. */
6758    Bool clear_CR1 = True;
6759
6760    /* Bind the rounding mode expression to a temp; there's no
6761       point in creating gratuitous CSEs, as we know we'll need 
6762       to use it twice. */
6763    assign( rmt, get_IR_roundingmode() );
6764    rm = mkexpr(rmt);
6765
6766    assign( frA, getFReg(frA_addr));
6767    assign( frB, getFReg(frB_addr));
6768    assign( frC, getFReg(frC_addr));
6769
6770    /* The rounding in this is all a bit dodgy.  The idea is to only do
6771       one rounding.  That clearly isn't achieveable without dedicated
6772       four-input IR primops, although in the single precision case we
6773       can sort-of simulate it by doing the inner multiply in double
6774       precision. 
6775
6776       In the negated cases, the negation happens after rounding. */
6777
6778    switch (opc1) {
6779    case 0x3B:
6780       switch (opc2) {
6781       case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
6782          DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6783              frD_addr, frA_addr, frC_addr, frB_addr);
6784          assign( frD, qop( Iop_MSubF64r32, rm,
6785                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
6786          break;
6787
6788       case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
6789          DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6790              frD_addr, frA_addr, frC_addr, frB_addr);
6791          assign( frD, qop( Iop_MAddF64r32, rm,
6792                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
6793          break;
6794
6795       case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
6796          DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6797              frD_addr, frA_addr, frC_addr, frB_addr);
6798          assign( frD, unop( Iop_NegF64,
6799                       qop( Iop_MSubF64r32, rm,
6800                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
6801          break;
6802
6803       case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
6804          DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6805              frD_addr, frA_addr, frC_addr, frB_addr);
6806          assign( frD, unop( Iop_NegF64,
6807                       qop( Iop_MAddF64r32, rm,
6808                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
6809          break;
6810
6811       default:
6812          vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
6813          return False;
6814       }
6815       break;
6816
6817    case 0x3F:
6818       switch (opc2) {           
6819       case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
6820          DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6821              frD_addr, frA_addr, frC_addr, frB_addr);
6822          assign( frD, qop( Iop_MSubF64, rm,
6823                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
6824          break;
6825
6826       case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
6827          DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6828              frD_addr, frA_addr, frC_addr, frB_addr);
6829          assign( frD, qop( Iop_MAddF64, rm,
6830                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
6831          break;
6832
6833       case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
6834          DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6835              frD_addr, frA_addr, frC_addr, frB_addr);
6836          assign( frD, unop( Iop_NegF64,
6837                       qop( Iop_MSubF64, rm,
6838                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
6839          break;
6840
6841       case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
6842          DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6843              frD_addr, frA_addr, frC_addr, frB_addr);
6844          assign( frD, unop( Iop_NegF64,
6845                       qop( Iop_MAddF64, rm,
6846                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
6847          break;
6848
6849       default:
6850          vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
6851          return False;
6852       }
6853       break;
6854
6855    default:
6856       vex_printf("dis_fp_multadd(ppc)(opc1)\n");
6857       return False;
6858    }
6859
6860    putFReg( frD_addr, mkexpr(frD) );
6861
6862    if (set_FPRF) {
6863       // XXX XXX XXX FIXME
6864       // set FPRF from frD
6865    }
6866
6867    if (flag_rC && clear_CR1) {
6868       putCR321( 1, mkU8(0) );
6869       putCR0( 1, mkU8(0) );
6870    }
6871
6872    return True;
6873 }
6874
6875 /*
6876  * fe_flag is set to 1 if any of the following conditions occurs:
6877  *  - The double-precision floating-point operand in register FRA is a NaN or an
6878  *    Infinity.
6879  *  - The double-precision floating-point operand in register FRB is a Zero, a
6880  *    NaN, or an Infinity.
6881  *  - e_b is less than or equal to -1022.
6882  *  - e_b is greater than or equal to 1021.
6883  *  - The double-precision floating-point operand in register FRA is not a zero
6884  *    and the difference, e_a - e_b, is greater than or equal to 1023.
6885  *  - The double-precision floating-point operand in register FRA is not a zero
6886  *    and the difference, e_a - e_b, is less than or equal to -1021.
6887  *  - The double-precision floating-point operand in register FRA is not a zero
6888  *    and e_a is less than or equal to -970
6889  *  Otherwise fe_flag is set to 0.
6890  *
6891  * fg_flag is set to 1 if either of the following conditions occurs.
6892  *   - The double-precision floating-point operand in register FRA is an Infinity.
6893  *   - The double-precision floating-point operand in register FRB is a Zero, an
6894  *     Infinity, or a denormalized value.
6895  *  Otherwise fg_flag is set to 0.
6896  *
6897  */
6898 static Bool dis_fp_ftdiv ( UInt theInstr )
6899 {
6900    UChar opc1     = ifieldOPC(theInstr);
6901    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
6902    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
6903    UChar frA_addr = ifieldRegA(theInstr);
6904    UChar frB_addr = ifieldRegB(theInstr);
6905    UChar b0       = ifieldBIT0(theInstr);
6906
6907    // The following temps are for holding intermediate results
6908    IRTemp frA_I64     = newTemp(Ity_I64);
6909    IRTemp frB_I64     = newTemp(Ity_I64);
6910    IRTemp e_a = newTemp(Ity_I32);
6911    IRTemp e_b = newTemp(Ity_I32);
6912    IRTemp frA_exp_shR = newTemp(Ity_I32);
6913    IRTemp frB_exp_shR = newTemp(Ity_I32);
6914
6915    UInt bias = 1023;
6916
6917    /* The following variables hold boolean results from tests
6918     * that are OR'ed together for setting the fe_ and fg_ flags.
6919     * For some cases, the booleans are used more than once, so
6920     * I make those IRTemp's instead of IRExpr's.
6921     */
6922    IRExpr * fraNaN, * frbNaN, * frbDenorm;
6923    IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
6924    IRTemp  fraInf_tmp = newTemp(Ity_I1);
6925    IRTemp  frbZero_tmp = newTemp(Ity_I1);
6926    IRTemp  frbInf_tmp = newTemp(Ity_I1);
6927    IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
6928
6929 /* The following are the flags that are set by OR'ing the results of
6930  * all the tests done for ftdiv.  These flags are the input to the specified CR.
6931  */
6932    IRExpr * fe_flag, * fl_flag, * fg_flag;
6933
6934
6935    if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
6936       vex_printf("dis_fp_ftdiv(ppc)(instr)\n");
6937       return False;
6938    }
6939
6940    // Create temps that will be used throughout the following tests.
6941    assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
6942    assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
6943    assign( frA_exp_shR, fp_exp_part( frA_I64 ) );
6944    assign( frB_exp_shR, fp_exp_part( frB_I64 ) );
6945    /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
6946    assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
6947    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
6948
6949
6950    //////////////////  fe_flag tests BEGIN //////////////////////
6951    /* We first do all tests that may result in setting fe_flag to '1'. */
6952
6953    /*
6954     * Test if the double-precision floating-point operand in register FRA is
6955     * a NaN:
6956     *    exp = 7ff and fraction is non-zero; s = 0/1
6957     */
6958    fraNaN = is_NaN(frA_I64);
6959    /*
6960     * Test if the double-precision floating-point operand in register FRA is
6961     * an Infinity.
6962     *    exp = 7ff and fraction is zero; s = 0/1
6963     */
6964    assign(fraInf_tmp, is_Inf(frA_I64));
6965
6966    /*
6967     * Test if the double-precision floating-point operand in register FRB is
6968     * a NaN:
6969     *    exp = 7ff and fraction is non-zero; s = 0/1
6970     */
6971    frbNaN = is_NaN(frB_I64);
6972    /*
6973     * Test if the double-precision floating-point operand in register FRB is
6974     * an Infinity.
6975     *    exp = 7ff and fraction is zero; s = 0/1
6976     */
6977    assign( frbInf_tmp, is_Inf(frB_I64) );
6978    /*
6979     * Test if the double-precision floating-point operand in register FRB is
6980     * a Zero.
6981     *    exp is zero and fraction is zero; s = 0/1
6982     */
6983    assign( frbZero_tmp, is_Zero(frB_I64) );
6984
6985    /*
6986     * Test if e_b <= -1022
6987     */
6988    {
6989       UInt test_value = 0xfffffc02;  //Int test_value = -1022;
6990       eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
6991    }
6992
6993    /*
6994     * Test if e_b >= 1021
6995     *   ==> 1021 < e_b
6996     */
6997    {
6998       Int test_value = 1021;
6999       eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
7000    }
7001
7002    /*
7003     * Test if FRA != Zero and (e_a - e_b) >= 1023
7004     *   ==> FRA != Zero && (1023 < (e_a - e_b)
7005     */
7006    assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_I64 ) ) );
7007    ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
7008                        binop( Iop_CmpLT32S, mkU32( bias ),
7009                               binop( Iop_Sub32, mkexpr( e_a ),
7010                                      mkexpr( e_b ) ) ) );
7011
7012    /*
7013     * Test if FRA != Zero and (e_a - e_b) <= -1021
7014     */
7015    {
7016       UInt test_value = 0xfffffc03;  //Int test_value = -1021;
7017
7018       ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
7019                           binop( Iop_CmpLE32S,
7020                                  binop( Iop_Sub32,
7021                                         mkexpr( e_a ),
7022                                         mkexpr( e_b ) ),
7023                                         mkU32( test_value ) ) );
7024    }
7025
7026    /*
7027     * Test if FRA != Zero and e_a <= -970
7028     */
7029    {
7030       UInt test_value = 0xfffffc36;  //Int test_value = -970;
7031
7032       ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
7033                                                         mkexpr( e_a ),
7034                                                         mkU32( test_value ) ) );
7035    }
7036    //////////////////  fe_flag tests END //////////////////////
7037
7038    //////////////////  fg_flag tests BEGIN //////////////////////
7039    /*
7040     * The following tests were already performed above in the fe_flag
7041     * tests.  So these conditions will result in both fe_ and fg_ flags
7042     * being set.
7043     *   - Test if FRA is an Infinity
7044     *   - Test if FRB ix Zero
7045     *   - Test if FRB is an Infinity
7046     */
7047
7048    /*
7049     * Test if FRB holds a denormalized value.  A denormalized value is one where
7050     * the exp is 0 and the fraction is non-zero.
7051     */
7052    {
7053       IRExpr * hi32, * low32, * fraction_is_nonzero;
7054       IRTemp frac_part = newTemp(Ity_I64);
7055
7056       assign( frac_part, FP_FRAC_PART(frB_I64) );
7057       hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
7058       low32 = unop( Iop_64to32, mkexpr( frac_part ) );
7059       fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
7060                                                 mkU32( 0 ) );
7061       frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
7062                                  mkU32( 0x0ULL ) ), fraction_is_nonzero );
7063
7064    }
7065    //////////////////  fg_flag tests END //////////////////////
7066
7067    /////////////////////////
7068    /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
7069     * where fl_flag == 1 on ppc64.
7070     */
7071    fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
7072
7073
7074    fe_flag
7075    = mkOR1(
7076             fraNaN,
7077             mkOR1(
7078                    mkexpr( fraInf_tmp ),
7079                    mkOR1(
7080                           mkexpr( frbZero_tmp ),
7081                           mkOR1(
7082                                  frbNaN,
7083                                  mkOR1(
7084                                         mkexpr( frbInf_tmp ),
7085                                         mkOR1( eb_LTE,
7086                                                mkOR1( eb_GTE,
7087                                                       mkOR1( ea_eb_GTE,
7088                                                              mkOR1( ea_eb_LTE,
7089                                                                     ea_LTE ) ) ) ) ) ) ) ) );
7090
7091    fe_flag = unop(Iop_1Uto32, fe_flag);
7092
7093    fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
7094                                                  mkOR1( mkexpr( frbInf_tmp ),
7095                                                         frbDenorm ) ) );
7096    fg_flag = unop(Iop_1Uto32, fg_flag);
7097
7098    putGST_field( PPC_GST_CR, binop( Iop_Or32,
7099                            binop( Iop_Or32,
7100                                   binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
7101                                   binop( Iop_Shl32, fg_flag, mkU8( 2 ) ) ),
7102                            binop( Iop_Shl32, fe_flag, mkU8( 1 ) ) ), crfD );
7103
7104    DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7105    return True;
7106 }
7107
7108 /*
7109   Floating Point Compare Instructions
7110 */
7111 static Bool dis_fp_cmp ( UInt theInstr )
7112 {   
7113    /* X-Form */
7114    UChar opc1     = ifieldOPC(theInstr);
7115    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
7116    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
7117    UChar frA_addr = ifieldRegA(theInstr);
7118    UChar frB_addr = ifieldRegB(theInstr);
7119    UInt  opc2     = ifieldOPClo10(theInstr);
7120    UChar b0       = ifieldBIT0(theInstr);
7121
7122    IRTemp ccIR    = newTemp(Ity_I32);
7123    IRTemp ccPPC32 = newTemp(Ity_I32);
7124
7125    IRTemp frA     = newTemp(Ity_F64);
7126    IRTemp frB     = newTemp(Ity_F64);
7127
7128    if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
7129       vex_printf("dis_fp_cmp(ppc)(instr)\n");
7130       return False;
7131    }
7132
7133    assign( frA, getFReg(frA_addr));
7134    assign( frB, getFReg(frB_addr));
7135
7136    assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
7137    
7138    /* Map compare result from IR to PPC32 */
7139    /*
7140      FP cmp result | PPC | IR
7141      --------------------------
7142      UN            | 0x1 | 0x45
7143      EQ            | 0x2 | 0x40
7144      GT            | 0x4 | 0x00
7145      LT            | 0x8 | 0x01
7146    */
7147
7148    // ccPPC32 = Shl(1, (~(ccIR>>5) & 2) 
7149    //                    | ((ccIR ^ (ccIR>>6)) & 1)
7150    assign(
7151       ccPPC32,
7152       binop(
7153          Iop_Shl32, 
7154          mkU32(1),
7155          unop(
7156             Iop_32to8, 
7157             binop(
7158                Iop_Or32,
7159                binop(
7160                   Iop_And32, 
7161                   unop(
7162                      Iop_Not32,
7163                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
7164                   ),
7165                   mkU32(2)
7166                ),
7167                binop(
7168                   Iop_And32, 
7169                   binop(
7170                      Iop_Xor32, 
7171                      mkexpr(ccIR),
7172                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
7173                   ),
7174                   mkU32(1)
7175                )
7176             )
7177          )
7178       )
7179    );
7180
7181    putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
7182
7183    /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
7184       putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
7185    */
7186    // XXX XXX XXX FIXME
7187    // Also write the result into FPRF (it's not entirely clear how)
7188
7189    /* Note: Differences between fcmpu and fcmpo are only in exception
7190       flag settings, which aren't supported anyway. */
7191    switch (opc2) {
7192    case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
7193       DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7194       break;
7195    case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
7196       DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7197       break;
7198    default:
7199       vex_printf("dis_fp_cmp(ppc)(opc2)\n");
7200       return False;
7201    }
7202    return True;
7203 }
7204
7205
7206
7207 /*
7208   Floating Point Rounding/Conversion Instructions
7209 */
7210 static Bool dis_fp_round ( UInt theInstr )
7211 {
7212    /* X-Form */
7213    UChar opc1     = ifieldOPC(theInstr);
7214    UChar b16to20  = ifieldRegA(theInstr);
7215    UChar frD_addr = ifieldRegDS(theInstr);
7216    UChar frB_addr = ifieldRegB(theInstr);
7217    UInt  opc2     = ifieldOPClo10(theInstr);
7218    UChar flag_rC  = ifieldBIT0(theInstr);
7219
7220    IRTemp  frD     = newTemp(Ity_F64);
7221    IRTemp  frB     = newTemp(Ity_F64);
7222    IRTemp  r_tmp32 = newTemp(Ity_I32);
7223    IRTemp  r_tmp64 = newTemp(Ity_I64);
7224    IRExpr* rm      = get_IR_roundingmode();
7225
7226    /* By default, we will examine the results of the operation and set
7227       fpscr[FPRF] accordingly. */
7228    Bool set_FPRF = True;
7229
7230    /* By default, if flag_RC is set, we will clear cr1 after the
7231       operation.  In reality we should set cr1 to indicate the
7232       exception status of the operation, but since we're not
7233       simulating exceptions, the exception status will appear to be
7234       zero.  Hence cr1 should be cleared if this is a . form insn. */
7235    Bool clear_CR1 = True;
7236    if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
7237       vex_printf("dis_fp_round(ppc)(instr)\n");
7238       return False;
7239    }
7240
7241    assign( frB, getFReg(frB_addr));
7242    // TODO : add support here for fcfdus
7243    if (opc1 == 0x3B) {
7244       /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
7245        * they're very similar to the other instructions handled here, but have
7246        * a different primary opcode.
7247        */
7248       switch (opc2) {
7249          case 0x34E: // fcfids (Float convert from signed DWord to single precision)
7250             DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7251             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7252             assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
7253                                                               mkexpr( r_tmp64 ) ) ) );
7254             goto putFR;
7255
7256          case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
7257             DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7258             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7259             assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
7260             goto putFR;
7261       }
7262    }
7263
7264
7265    switch (opc2) {
7266    case 0x00C: // frsp (Float Round to Single, PPC32 p423)
7267       DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7268       assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
7269       break;
7270       
7271    case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
7272       DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7273       assign( r_tmp32,
7274               binop(Iop_F64toI32S, rm, mkexpr(frB)) );
7275       assign( frD, unop( Iop_ReinterpI64asF64,
7276                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
7277       /* FPRF is undefined after fctiw.  Leave unchanged. */
7278       set_FPRF = False;
7279       break;
7280       
7281    case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
7282       DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7283       assign( r_tmp32, 
7284               binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
7285       assign( frD, unop( Iop_ReinterpI64asF64,
7286                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
7287       /* FPRF is undefined after fctiwz.  Leave unchanged. */
7288       set_FPRF = False;
7289       break;
7290
7291    case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
7292       DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7293       assign( r_tmp64,
7294               binop(Iop_F64toI64S, rm, mkexpr(frB)) );
7295       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
7296       /* FPRF is undefined after fctid.  Leave unchanged. */
7297       set_FPRF = False;
7298       break;
7299
7300    case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
7301       DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7302       assign( r_tmp64, 
7303               binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
7304       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
7305       /* FPRF is undefined after fctidz.  Leave unchanged. */
7306       set_FPRF = False;
7307       break;
7308
7309    case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
7310       DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7311       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7312       assign( frD, 
7313               binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
7314       break;
7315
7316    case 0x3CE: // fcfidu (Float convert from unsigned DWord)
7317       DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7318       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7319       assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
7320       break;
7321
7322    case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
7323       switch(opc2) {
7324       case 0x188: // frin (Floating Round to Integer Nearest)
7325          DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7326          assign( r_tmp64,
7327                  binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
7328          break;
7329       case 0x1A8: // friz (Floating Round to Integer Toward Zero)
7330          DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7331          assign( r_tmp64,
7332                  binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
7333          break;
7334       case 0x1C8: // frip (Floating Round to Integer Plus)
7335          DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7336          assign( r_tmp64,
7337                  binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
7338          break;
7339       case 0x1E8: // frim (Floating Round to Integer Minus)
7340          DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7341          assign( r_tmp64,
7342                  binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
7343          break;
7344       }
7345
7346       /* don't use the rounded integer if frB is outside -9e18..9e18 */
7347       /* F64 has only log10(2**52) significant digits anyway */
7348       /* need to preserve sign of zero */
7349       /*   frD = (fabs(frB) > 9e18) ? frB :
7350                (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
7351       assign(frD, IRExpr_Mux0X( unop(Iop_32to8,
7352                                      binop(Iop_CmpF64,
7353                                            IRExpr_Const(IRConst_F64(9e18)),
7354                                            unop(Iop_AbsF64, mkexpr(frB)))),
7355                                 IRExpr_Mux0X(unop(Iop_32to8,
7356                                                   binop(Iop_Shr32,
7357                                                         unop(Iop_64HIto32,
7358                                                              unop(Iop_ReinterpF64asI64,
7359                                                                   mkexpr(frB))), mkU8(31))),
7360                                              binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ),
7361                                              unop(Iop_NegF64,
7362                                                   unop( Iop_AbsF64,
7363                                                         binop(Iop_I64StoF64, mkU32(0),
7364                                                               mkexpr(r_tmp64)) )) ),
7365                                 mkexpr(frB)));
7366       break;
7367
7368    default:
7369       vex_printf("dis_fp_round(ppc)(opc2)\n");
7370       return False;
7371    }
7372 putFR:
7373    putFReg( frD_addr, mkexpr(frD) );
7374
7375    if (set_FPRF) {
7376       // XXX XXX XXX FIXME
7377       // set FPRF from frD
7378    }
7379
7380    if (flag_rC && clear_CR1) {
7381       putCR321( 1, mkU8(0) );
7382       putCR0( 1, mkU8(0) );
7383    }
7384
7385    return True;
7386 }
7387
7388 /*
7389   Floating Point Pair Instructions
7390 */
7391 static Bool dis_fp_pair ( UInt theInstr )
7392 {
7393    /* X-Form/DS-Form */
7394    UChar  opc1         = ifieldOPC(theInstr);
7395    UChar  frT_hi_addr  = ifieldRegDS(theInstr);
7396    UChar  frT_lo_addr  = frT_hi_addr + 1;
7397    UChar  rA_addr      = ifieldRegA(theInstr);
7398    UChar  rB_addr      = ifieldRegB(theInstr);
7399    UInt  uimm16        = ifieldUIMM16(theInstr);
7400    Int    simm16       = extend_s_16to32(uimm16);
7401    UInt   opc2         = ifieldOPClo10(theInstr);
7402    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
7403    IRTemp EA_hi        = newTemp(ty);
7404    IRTemp EA_lo        = newTemp(ty);
7405    IRTemp frT_hi       = newTemp(Ity_F64);
7406    IRTemp frT_lo       = newTemp(Ity_F64);
7407    UChar b0            = ifieldBIT0(theInstr);
7408    Bool is_load        = 0;
7409
7410    if ((frT_hi_addr %2) != 0) {
7411       vex_printf("dis_fp_pair(ppc) : odd frT register\n");
7412       return False;
7413    }
7414
7415    switch (opc1) {
7416    case 0x1F: // register offset
7417       switch(opc2) {
7418       case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
7419          DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
7420          is_load = 1;
7421          break;
7422       case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
7423          DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
7424          break;
7425       default:
7426          vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
7427          return False;
7428       }
7429
7430       if (b0 != 0) {
7431          vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
7432          return False;
7433       }
7434       assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
7435       break;
7436    case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
7437       DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
7438       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
7439       is_load = 1;
7440       break;
7441    case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
7442       DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
7443       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
7444       break;
7445    default:   // immediate offset
7446       vex_printf("dis_fp_pair(ppc)(instr)\n");
7447       return False;
7448    }
7449
7450    if (mode64)
7451       assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
7452    else
7453       assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
7454
7455    assign( frT_hi, getFReg(frT_hi_addr) );
7456    assign( frT_lo, getFReg(frT_lo_addr) );
7457
7458    if (is_load) {
7459       putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) );
7460       putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) );
7461    } else {
7462       storeBE( mkexpr(EA_hi), mkexpr(frT_hi) );
7463       storeBE( mkexpr(EA_lo), mkexpr(frT_lo) );
7464    }
7465
7466    return True;
7467 }
7468
7469
7470 /*
7471   Floating Point Move Instructions
7472 */
7473 static Bool dis_fp_move ( UInt theInstr )
7474 {
7475    /* X-Form */
7476    UChar opc1     = ifieldOPC(theInstr);
7477    UChar frD_addr = ifieldRegDS(theInstr);
7478    UChar frA_addr = ifieldRegA(theInstr);
7479    UChar frB_addr = ifieldRegB(theInstr);
7480    UInt  opc2     = ifieldOPClo10(theInstr);
7481    UChar flag_rC  = ifieldBIT0(theInstr);
7482
7483    IRTemp frD = newTemp(Ity_F64);
7484    IRTemp frB = newTemp(Ity_F64);
7485    IRTemp itmpB = newTemp(Ity_F64);
7486    IRTemp frA;
7487    IRTemp signA;
7488    IRTemp hiD;
7489
7490    if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
7491       vex_printf("dis_fp_move(ppc)(instr)\n");
7492       return False;
7493    }
7494
7495    assign( frB, getFReg(frB_addr));
7496
7497    switch (opc2) {
7498    case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
7499       DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
7500           frB_addr);
7501       signA = newTemp(Ity_I32);
7502       hiD = newTemp(Ity_I32);
7503       itmpB = newTemp(Ity_I64);
7504       frA = newTemp(Ity_F64);
7505       assign( frA, getFReg(frA_addr) );
7506
7507       /* get A's sign bit */
7508       assign(signA, binop(Iop_And32,
7509                           unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
7510                                                   mkexpr(frA))),
7511                           mkU32(0x80000000)) );
7512
7513       assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
7514
7515       /* mask off B's sign bit and or in A's sign bit */
7516       assign(hiD, binop(Iop_Or32,
7517                         binop(Iop_And32,
7518                               unop(Iop_64HIto32,
7519                                    mkexpr(itmpB)),  /* frB's high 32 bits */
7520                               mkU32(0x7fffffff)),
7521                         mkexpr(signA)) );
7522
7523       /* combine hiD/loB into frD */
7524       assign( frD, unop(Iop_ReinterpI64asF64,
7525                         binop(Iop_32HLto64,
7526                               mkexpr(hiD),
7527                               unop(Iop_64to32,
7528                                    mkexpr(itmpB)))) );   /* frB's low 32 bits */
7529       break;
7530
7531    case 0x028: // fneg (Floating Negate, PPC32 p416)
7532       DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7533       assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
7534       break;
7535       
7536    case 0x048: // fmr (Floating Move Register, PPC32 p410)
7537       DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7538       assign( frD, mkexpr(frB) );
7539       break;
7540       
7541    case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
7542       DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7543       assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
7544       break;
7545       
7546    case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
7547       DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7548       assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
7549       break;
7550       
7551    default:
7552       vex_printf("dis_fp_move(ppc)(opc2)\n");
7553       return False;
7554    }
7555
7556    putFReg( frD_addr, mkexpr(frD) );
7557
7558    /* None of these change FPRF.  cr1 is set in the usual way though,
7559       if flag_rC is set. */
7560
7561    if (flag_rC) {
7562       putCR321( 1, mkU8(0) );
7563       putCR0( 1, mkU8(0) );
7564    }
7565
7566    return True;
7567 }
7568
7569
7570
7571 /*
7572   Floating Point Status/Control Register Instructions
7573 */
7574 static Bool dis_fp_scr ( UInt theInstr )
7575 {
7576    /* Many forms - see each switch case */
7577    UChar opc1    = ifieldOPC(theInstr);
7578    UInt  opc2    = ifieldOPClo10(theInstr);
7579    UChar flag_rC = ifieldBIT0(theInstr);
7580
7581    if (opc1 != 0x3F) {
7582       vex_printf("dis_fp_scr(ppc)(instr)\n");
7583       return False;
7584    }
7585
7586    switch (opc2) {
7587    case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
7588       // Bit crbD of the FPSCR is set.
7589       UChar crbD    = ifieldRegDS(theInstr);
7590       UInt  b11to20 = IFIELD(theInstr, 11, 10);
7591
7592       if (b11to20 != 0) {
7593          vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
7594          return False;
7595       }
7596       DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
7597       putGST_masked( PPC_GST_FPSCR, mkU32(1<<(31-crbD)), 1<<(31-crbD) );
7598       break;
7599    }
7600
7601    case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
7602       UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
7603       UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
7604       UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
7605       UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
7606       IRTemp  tmp     = newTemp(Ity_I32);
7607       IRExpr* fpscr_all;
7608       if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
7609          vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
7610          return False;
7611       }
7612       DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
7613       vassert(crfD < 8);
7614       vassert(crfS < 8);
7615       fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
7616       assign( tmp, binop(Iop_And32,
7617                          binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
7618                         mkU32(0xF)) );
7619       putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
7620       break;
7621    }
7622
7623    case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
7624       // Bit crbD of the FPSCR is cleared.
7625       UChar crbD    = ifieldRegDS(theInstr);
7626       UInt  b11to20 = IFIELD(theInstr, 11, 10);
7627
7628       if (b11to20 != 0) {
7629          vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
7630          return False;
7631       }      
7632       DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
7633       putGST_masked( PPC_GST_FPSCR, mkU32(0), 1<<(31-crbD) );
7634       break;
7635    }
7636
7637    case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
7638       UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
7639       UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
7640       UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
7641       UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
7642
7643       if (b16to22 != 0 || b11 != 0) {
7644          vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
7645          return False;
7646       }      
7647       DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM);
7648       putGST_field( PPC_GST_FPSCR, mkU32(IMM), crfD );
7649       break;
7650    }
7651
7652    case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
7653       UChar   frD_addr  = ifieldRegDS(theInstr);
7654       UInt    b11to20   = IFIELD(theInstr, 11, 10);
7655       IRExpr* fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
7656
7657       if (b11to20 != 0) {
7658          vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
7659          return False;
7660       }
7661       DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
7662       putFReg( frD_addr,
7663           unop( Iop_ReinterpI64asF64,
7664                 unop( Iop_32Uto64, fpscr_all )));
7665       break;
7666    }
7667
7668    case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
7669       UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
7670       UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
7671       UChar frB_addr = ifieldRegB(theInstr);
7672       IRTemp frB   = newTemp(Ity_F64);
7673       IRTemp rB_32 = newTemp(Ity_I32);
7674       Int i, mask;
7675
7676       if (b25 == 1) {
7677          /* new 64 bit move variant for power 6.  If L field (bit 25) is
7678           * a one do a full 64 bit move.  Note, the FPSCR is not really
7679           * properly modeled.  This instruciton only changes the value of
7680           * the rounding mode.  The HW exception bits do not get set in
7681           * the simulator.  1/12/09
7682           */
7683          DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
7684          mask = 0xFF;
7685
7686       } else {
7687          DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
7688          // Build 32bit mask from FM:
7689          mask = 0;
7690          for (i=0; i<8; i++) {
7691             if ((FM & (1<<(7-i))) == 1) {
7692                mask |= 0xF << (7-i);
7693             }
7694          }
7695       }
7696       assign( frB, getFReg(frB_addr));
7697       assign( rB_32, unop( Iop_64to32,
7698                            unop( Iop_ReinterpF64asI64, mkexpr(frB) )));
7699       putGST_masked( PPC_GST_FPSCR, mkexpr(rB_32), mask );
7700       break;
7701    }
7702
7703    default:
7704       vex_printf("dis_fp_scr(ppc)(opc2)\n");
7705       return False;
7706    }
7707    return True;
7708 }
7709
7710
7711
7712 /*------------------------------------------------------------*/
7713 /*--- AltiVec Instruction Translation                      ---*/
7714 /*------------------------------------------------------------*/
7715
7716 /*
7717   Altivec Cache Control Instructions (Data Streams)
7718 */
7719 static Bool dis_av_datastream ( UInt theInstr )
7720 {
7721    /* X-Form */
7722    UChar opc1     = ifieldOPC(theInstr);
7723    UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
7724    UChar flag_A   = flag_T;
7725    UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
7726    UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
7727    UChar rA_addr  = ifieldRegA(theInstr);
7728    UChar rB_addr  = ifieldRegB(theInstr);
7729    UInt  opc2     = ifieldOPClo10(theInstr);
7730    UChar b0       = ifieldBIT0(theInstr);
7731
7732    if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
7733       vex_printf("dis_av_datastream(ppc)(instr)\n");
7734       return False;
7735    }
7736
7737    switch (opc2) {
7738    case 0x156: // dst (Data Stream Touch, AV p115)
7739       DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
7740                                 rA_addr, rB_addr, STRM);
7741       break;
7742
7743    case 0x176: // dstst (Data Stream Touch for Store, AV p117)
7744       DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
7745                                   rA_addr, rB_addr, STRM);
7746       break;
7747
7748    case 0x336: // dss (Data Stream Stop, AV p114)
7749       if (rA_addr != 0 || rB_addr != 0) {
7750          vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
7751          return False;
7752       }
7753       if (flag_A == 0) {
7754          DIP("dss %d\n", STRM);
7755       } else {
7756          DIP("dssall\n");
7757       }
7758       break;
7759
7760    default:
7761       vex_printf("dis_av_datastream(ppc)(opc2)\n");
7762       return False;
7763    }
7764    return True;
7765 }
7766
7767 /*
7768   AltiVec Processor Control Instructions
7769 */
7770 static Bool dis_av_procctl ( UInt theInstr )
7771 {
7772    /* VX-Form */
7773    UChar opc1    = ifieldOPC(theInstr);
7774    UChar vD_addr = ifieldRegDS(theInstr);
7775    UChar vA_addr = ifieldRegA(theInstr);
7776    UChar vB_addr = ifieldRegB(theInstr);
7777    UInt  opc2    = IFIELD( theInstr, 0, 11 );
7778
7779    if (opc1 != 0x4) {
7780       vex_printf("dis_av_procctl(ppc)(instr)\n");
7781       return False;
7782    }
7783
7784    switch (opc2) {
7785    case 0x604: // mfvscr (Move from VSCR, AV p129)
7786       if (vA_addr != 0 || vB_addr != 0) {
7787          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
7788          return False;
7789       }
7790       DIP("mfvscr v%d\n", vD_addr);
7791       putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) ); 
7792       break;
7793
7794    case 0x644: { // mtvscr (Move to VSCR, AV p130)
7795       IRTemp vB = newTemp(Ity_V128);
7796       if (vD_addr != 0 || vA_addr != 0) {
7797          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
7798          return False;
7799       }
7800       DIP("mtvscr v%d\n", vB_addr);
7801       assign( vB, getVReg(vB_addr));
7802       putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) ); 
7803       break;
7804    }
7805    default:
7806       vex_printf("dis_av_procctl(ppc)(opc2)\n");
7807       return False;
7808    }
7809    return True;
7810 }
7811
7812 /*
7813  *
7814  */
7815 static Bool
7816 dis_vx_conv ( UInt theInstr, UInt opc2 )
7817 {
7818    /* XX2-Form */
7819    UChar opc1 = ifieldOPC( theInstr );
7820    UChar XT = ifieldRegXT( theInstr );
7821    UChar XB = ifieldRegXB( theInstr );
7822    IRTemp frB = newTemp(Ity_F64);
7823    IRTemp r_tmp64 = newTemp(Ity_I64);
7824    IRExpr* rm = get_IR_roundingmode();
7825
7826    if (opc1 != 0x3C) {
7827       vex_printf( "dis_vx_conv(ppc)(instr)\n" );
7828       return False;
7829    }
7830
7831    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
7832    /* For all the VSX convert instructions, the contents of doubleword element 1
7833     * of VSX[XT] are undefined after the operation; therefore, we can simply
7834     * move the entire array element where it makes sense to do so.
7835     */
7836
7837    switch (opc2) {
7838    case 0x2B0:
7839       // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
7840       //             to Signed Integer Doubleword format with Saturate)
7841       DIP("xscvdpsxds fr%u,fr%u\n",  (UInt)XT, (UInt)XB);
7842       putVSReg( XT,
7843                    binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
7844                                                  mkU32( Irrm_ZERO ),
7845                                                  mkexpr( frB ) ), mkU64( 0 ) ) );
7846       break;
7847    case 0x2F0:
7848       // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
7849       //            Double-Precision format)
7850       DIP("xscvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
7851
7852       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7853       putVSReg( XT,
7854                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7855                                                 binop( Iop_I64StoF64, rm,
7856                                                        mkexpr( r_tmp64 ) ) ),
7857                           mkU64( 0 ) ) );
7858       break;
7859    case 0x2D0:
7860       // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
7861       //            Double-Precision format)
7862       DIP("xscvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
7863
7864       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7865       putVSReg( XT,
7866                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7867                                                 binop( Iop_I64UtoF64, rm,
7868                                                        mkexpr( r_tmp64 ) ) ),
7869                           mkU64( 0 ) ) );
7870       break;
7871
7872    default:
7873       vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
7874       return False;
7875    }
7876    return True;
7877 }
7878
7879 /*
7880  * VSX Scalar Floating Point Arithmetic Instructions
7881  */
7882 static Bool
7883 dis_vx_arith ( UInt theInstr, UInt opc2 )
7884 {
7885    /* XX3-Form */
7886    UChar opc1 = ifieldOPC( theInstr );
7887    UChar XT = ifieldRegXT( theInstr );
7888    UChar XA = ifieldRegXA( theInstr );
7889    UChar XB = ifieldRegXB( theInstr );
7890    IRExpr* rm = get_IR_roundingmode();
7891    IRTemp frA = newTemp(Ity_F64);
7892    IRTemp frB = newTemp(Ity_F64);
7893
7894    if (opc1 != 0x3C) {
7895       vex_printf( "dis_vx_arith(ppc)(instr)\n" );
7896       return False;
7897    }
7898
7899    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
7900    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
7901
7902    /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
7903     * of VSX[XT] are undefined after the operation; therefore, we can simply set
7904     * element to zero where it makes sense to do so.
7905     */
7906    switch (opc2) {
7907       case 0x080: // xsadddp (VSX scalar add double-precision)
7908          DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
7909          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7910                                                     triop( Iop_AddF64, rm,
7911                                                            mkexpr( frA ),
7912                                                            mkexpr( frB ) ) ),
7913                               mkU64( 0 ) ) );
7914          break;
7915       case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
7916          DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
7917          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7918                                                     triop( Iop_DivF64, rm,
7919                                                            mkexpr( frA ),
7920                                                            mkexpr( frB ) ) ),
7921                               mkU64( 0 ) ) );
7922          break;
7923       case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
7924       {
7925          IRTemp frT = newTemp(Ity_F64);
7926          Bool mdp = opc2 == 0x0A4;
7927          DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
7928          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
7929                                                         getVSReg( XT ) ) ) );
7930          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7931                                                     qop( Iop_MAddF64, rm,
7932                                                          mkexpr( frA ),
7933                                                          mkexpr( mdp ? frT : frB ),
7934                                                          mkexpr( mdp ? frB : frT ) ) ),
7935                               mkU64( 0 ) ) );
7936          break;
7937       }
7938       case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
7939       {
7940          IRTemp frT = newTemp(Ity_F64);
7941          Bool mdp = opc2 == 0x0E4;
7942          DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
7943          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
7944                                                         getVSReg( XT ) ) ) );
7945          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7946                                                     qop( Iop_MSubF64, rm,
7947                                                          mkexpr( frA ),
7948                                                          mkexpr( mdp ? frT : frB ),
7949                                                          mkexpr( mdp ? frB : frT ) ) ),
7950                               mkU64( 0 ) ) );
7951          break;
7952       }
7953       case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
7954       {
7955          /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
7956           * of fnmadd and use pretty much the same code. However, that code has a bug in the
7957           * way it blindly negates the signbit, even if the floating point result is a NaN.
7958           * So, the TODO is to fix fnmadd (which I'll do in a different patch).
7959           */
7960          ULong signbit_mask = 0x8000000000000000ULL;
7961          Bool mdp = opc2 == 0x2A4;
7962          IRTemp frT = newTemp(Ity_F64);
7963          IRTemp maddResult = newTemp(Ity_I64);
7964          IRTemp negatedResult = newTemp(Ity_I64);
7965          IRTemp signbit_32 = newTemp(Ity_I32);
7966          IRTemp resultantSignbit = newTemp(Ity_I1);
7967
7968          DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
7969          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
7970                                                         getVSReg( XT ) ) ) );
7971          assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
7972                                                               mkexpr( frA ),
7973                                                               mkexpr( mdp ? frT : frB ),
7974                                                               mkexpr( mdp ? frB : frT ) ) ) );
7975          assign( signbit_32, binop( Iop_Shr32,
7976                                 unop( Iop_64HIto32,
7977                                        binop( Iop_And64, mkexpr( maddResult ),
7978                                               mkU64( signbit_mask ) ) ),
7979                                        mkU8( 31 ) ) );
7980          /* We negate the signbit if and only if the intermediate result from the
7981           * multiply-add was NOT a NaN.  This is an XNOR predicate.
7982           */
7983          assign( resultantSignbit,
7984                  unop( Iop_Not1,
7985                        binop( Iop_CmpEQ32,
7986                                      binop( Iop_Xor32, mkexpr( signbit_32 ),
7987                                             unop( Iop_1Uto32,
7988                                                   is_NaN( maddResult ) ) ),
7989                                      mkU32( 1 ) ) ) );
7990
7991          assign( negatedResult,
7992                  binop( Iop_Or64, binop( Iop_And64, mkexpr( maddResult ),
7993                                          mkU64( ~signbit_mask ) ),
7994                         binop( Iop_32HLto64,
7995                                binop( Iop_Shl32,
7996                                       unop( Iop_1Uto32,
7997                                             mkexpr( resultantSignbit ) ),
7998                                       mkU8( 31 ) ), mkU32( 0 ) ) ) );
7999
8000          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( negatedResult ),
8001                               mkU64( 0 ) ) );
8002          break;
8003       }
8004       case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
8005          DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8006          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
8007                                                     triop( Iop_MulF64, rm,
8008                                                            mkexpr( frA ),
8009                                                            mkexpr( frB ) ) ),
8010                               mkU64( 0 ) ) );
8011          break;
8012       case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
8013          DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8014          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
8015                                                     triop( Iop_SubF64, rm,
8016                                                            mkexpr( frA ),
8017                                                            mkexpr( frB ) ) ),
8018                               mkU64( 0 ) ) );
8019          break;
8020
8021       default:
8022          vex_printf( "dis_vx_arith(ppc)(opc2)\n" );
8023          return False;
8024    }
8025    return True;
8026 }
8027
8028 /*
8029  * VSX Floating Point Compare Instructions
8030  */
8031 static Bool
8032 dis_vx_cmp( UInt theInstr, UInt opc2 )
8033 {
8034    /* XX3-Form and XX2-Form */
8035    UChar opc1 = ifieldOPC( theInstr );
8036    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
8037    IRTemp ccPPC32 = newTemp(Ity_I32);
8038    IRTemp ccIR    = newTemp(Ity_I32);
8039    UChar XA       = ifieldRegXA ( theInstr );
8040    UChar XB       = ifieldRegXB ( theInstr );
8041    IRTemp frA     = newTemp(Ity_F64);
8042    IRTemp frB     = newTemp(Ity_F64);
8043
8044    if (opc1 != 0x3C) {
8045       vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
8046       return False;
8047    }
8048
8049    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
8050    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
8051    switch (opc2) {
8052       case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
8053          /* Note: Differences between xscmpudp and xscmpodp are only in
8054           * exception flag settings, which aren't supported anyway. */
8055          DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
8056                                            crfD, (UInt)XA, (UInt)XB);
8057          assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
8058
8059          /* Map compare result from IR to PPC32 */
8060          /*
8061            FP cmp result | PPC | IR
8062            --------------------------
8063            UN            | 0x1 | 0x45
8064            EQ            | 0x2 | 0x40
8065            GT            | 0x4 | 0x00
8066            LT            | 0x8 | 0x01
8067          */
8068
8069          // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
8070          //                    | ((ccIR ^ (ccIR>>6)) & 1)
8071          assign(
8072             ccPPC32,
8073             binop(
8074                Iop_Shl32,
8075                mkU32(1),
8076                unop(
8077                   Iop_32to8,
8078                   binop(
8079                      Iop_Or32,
8080                      binop(
8081                         Iop_And32,
8082                         unop(
8083                            Iop_Not32,
8084                            binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
8085                         ),
8086                         mkU32(2)
8087                      ),
8088                      binop(
8089                         Iop_And32,
8090                         binop(
8091                            Iop_Xor32,
8092                            mkexpr(ccIR),
8093                            binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
8094                         ),
8095                         mkU32(1)
8096                      )
8097                   )
8098                )
8099             )
8100          );
8101
8102          putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
8103
8104          break;
8105       default:
8106          vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
8107          return False;
8108    }
8109    return True;
8110 }
8111 /*
8112  * VSX Move Instructions
8113  */
8114 static Bool
8115 dis_vx_move( UInt theInstr, UInt opc2 )
8116 {
8117    /* XX3-Form and XX2-Form */
8118    UChar opc1 = ifieldOPC( theInstr );
8119    UChar XT = ifieldRegXT ( theInstr );
8120    UChar XA = ifieldRegXA ( theInstr );
8121    UChar XB = ifieldRegXB ( theInstr );
8122    IRTemp vA = newTemp( Ity_V128 );
8123    IRTemp vB = newTemp( Ity_V128 );
8124
8125    if (opc1 != 0x3C) {
8126       vex_printf( "dis_vx_move(ppc)(instr)\n" );
8127       return False;
8128    }
8129
8130    assign( vA, getVSReg( XA ) );
8131    assign( vB, getVSReg( XB ) );
8132
8133    /* For all the VSX move instructions, the contents of doubleword element 1
8134     * of VSX[XT] are undefined after the operation; therefore, we can simply
8135     * move the entire array element where it makes sense to do so.
8136     */
8137
8138    switch (opc2) {
8139       case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
8140       {
8141          /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
8142          IRTemp absVal = newTemp(Ity_V128);
8143          assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1)));
8144          DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
8145          putVSReg(XT, mkexpr(absVal));
8146          break;
8147       }
8148       case 0x2C0: // xscpsgndp
8149       {
8150          /* Scalar copy sign double-precision */
8151          IRTemp vecA_signbit = newTemp(Ity_V128);
8152          IRTemp vecB_no_signbit = newTemp(Ity_V128);
8153          IRTemp vec_result = newTemp(Ity_V128);
8154          DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8155          assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
8156                                                              mkexpr( vB ),
8157                                                              mkU8( 1 ) ),
8158                                          mkU8( 1 ) ) );
8159          assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128,
8160                                                           mkexpr( vA ),
8161                                                           mkU8( 127 ) ),
8162                                       mkU8( 127 ) ) );
8163          assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) );
8164          putVSReg(XT, mkexpr(vec_result));
8165          break;
8166       }
8167       case 0x2D2: // xsnabsdp
8168       {
8169          /* Scalar negative absolute value double-precision */
8170          IRTemp vec_neg_signbit = newTemp(Ity_V128);
8171          DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
8172          assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128,
8173                                                             mkV128( 0xffff ),
8174                                                             mkU8( 1 ) ) ) );
8175          putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB)));
8176          break;
8177       }
8178       case 0x2F2: // xsnegdp
8179       {
8180          /* Scalar negate double-precision */
8181          IRTemp vecB_no_signbit = newTemp(Ity_V128);
8182          IRTemp vecB_signbit_comp = newTemp(Ity_V128);
8183          DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
8184          assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
8185                                                              mkexpr( vB ),
8186                                                              mkU8( 1 ) ),
8187                                          mkU8( 1 ) ) );
8188          assign( vecB_signbit_comp, binop( Iop_ShlV128,
8189                                            unop( Iop_NotV128,
8190                                                  binop( Iop_ShrV128,
8191                                                         mkexpr( vB ),
8192                                                         mkU8( 127 ) ) ),
8193                                            mkU8( 127 ) ) );
8194          putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ),
8195                               mkexpr( vecB_signbit_comp ) ) );
8196          break;
8197       }
8198
8199       default:
8200          vex_printf( "dis_vx_move(ppc)(opc2)\n" );
8201          return False;
8202    }
8203    return True;
8204 }
8205
8206 /*
8207  * VSX Logical Instructions
8208  */
8209 static Bool
8210 dis_vx_logic ( UInt theInstr, UInt opc2 )
8211 {
8212    /* XX3-Form */
8213    UChar opc1 = ifieldOPC( theInstr );
8214    UChar XT = ifieldRegXT ( theInstr );
8215    UChar XA = ifieldRegXA ( theInstr );
8216    UChar XB = ifieldRegXB ( theInstr );
8217    IRTemp vA = newTemp( Ity_V128 );
8218    IRTemp vB = newTemp( Ity_V128 );
8219
8220    if (opc1 != 0x3C) {
8221       vex_printf( "dis_vx_logic(ppc)(instr)\n" );
8222       return False;
8223    }
8224
8225    assign( vA, getVSReg( XA ) );
8226    assign( vB, getVSReg( XB ) );
8227
8228    switch (opc2) {
8229       case 0x268: // xxlxor
8230          DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8231          putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
8232          break;
8233       case 0x248: // xxlor
8234          DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8235          putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
8236          break;
8237       case 0x288: // xxlnor
8238          DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8239          putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
8240                                                  mkexpr( vB ) ) ) );
8241          break;
8242       case 0x208: // xxland
8243          DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8244          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
8245          break;
8246       case 0x228: //xxlandc
8247          DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8248          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
8249                                                                mkexpr( vB ) ) ) );
8250          break;
8251       default:
8252          vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
8253          return False;
8254    }
8255    return True;
8256 }
8257
8258 /*
8259  * VSX Load Instructions
8260  * NOTE: VSX supports word-aligned storage access.
8261  */
8262 static Bool
8263 dis_vx_load ( UInt theInstr )
8264 {
8265    /* XX1-Form */
8266    UChar opc1 = ifieldOPC( theInstr );
8267    UChar XT = ifieldRegXT ( theInstr );
8268    UChar rA_addr = ifieldRegA( theInstr );
8269    UChar rB_addr = ifieldRegB( theInstr );
8270    UInt opc2 = ifieldOPClo10( theInstr );
8271
8272    IRType ty = mode64 ? Ity_I64 : Ity_I32;
8273    IRTemp EA = newTemp( ty );
8274
8275    if (opc1 != 0x1F) {
8276       vex_printf( "dis_vx_load(ppc)(instr)\n" );
8277       return False;
8278    }
8279
8280    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
8281
8282    switch (opc2) {
8283    case 0x24C: // lxsdx
8284    {
8285       IRExpr * exp;
8286       DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
8287       exp = loadBE( Ity_I64, mkexpr( EA ) );
8288       // We need to pass an expression of type Ity_V128 with putVSReg, but the load
8289       // we just performed is only a DW.  But since the contents of VSR[XT] element 1
8290       // are undefined after this operation, we can just do a splat op.
8291       putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
8292       break;
8293    }
8294    case 0x34C: // lxvd2x
8295    {
8296       IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
8297       IRExpr * high, *low;
8298       ULong ea_off = 8;
8299       IRExpr* high_addr;
8300       DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
8301       high = loadBE( Ity_I64, mkexpr( EA ) );
8302       high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
8303             : mkU32( ea_off ) );
8304       low = loadBE( Ity_I64, high_addr );
8305       putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
8306       break;
8307    }
8308    case 0x14C: // lxvdsx
8309    {
8310       IRTemp data = newTemp(Ity_I64);
8311       DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
8312       assign( data, loadBE( Ity_I64, mkexpr( EA ) ) );
8313       putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
8314       break;
8315    }
8316    case 0x30C:
8317    {
8318       IRExpr * t3, *t2, *t1, *t0;
8319       UInt ea_off = 0;
8320       IRExpr* irx_addr;
8321
8322       DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
8323       t3 = loadBE( Ity_I32,  mkexpr( EA ) );
8324       ea_off += 4;
8325       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8326                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8327       t2 = loadBE( Ity_I32, irx_addr );
8328       ea_off += 4;
8329       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8330                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8331       t1 = loadBE( Ity_I32, irx_addr );
8332       ea_off += 4;
8333       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8334                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8335       t0 = loadBE( Ity_I32, irx_addr );
8336       putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ),
8337                            binop( Iop_32HLto64, t1, t0 ) ) );
8338       break;
8339    }
8340    default:
8341       vex_printf( "dis_vx_load(ppc)(opc2)\n" );
8342       return False;
8343    }
8344    return True;
8345 }
8346
8347 /*
8348  * VSX Store Instructions
8349  * NOTE: VSX supports word-aligned storage access.
8350  */
8351 static Bool
8352 dis_vx_store ( UInt theInstr )
8353 {
8354    /* XX1-Form */
8355    UChar opc1 = ifieldOPC( theInstr );
8356    UChar XS = ifieldRegXS( theInstr );
8357    UChar rA_addr = ifieldRegA( theInstr );
8358    UChar rB_addr = ifieldRegB( theInstr );
8359    IRTemp vS = newTemp( Ity_V128 );
8360    UInt opc2 = ifieldOPClo10( theInstr );
8361
8362    IRType ty = mode64 ? Ity_I64 : Ity_I32;
8363    IRTemp EA = newTemp( ty );
8364
8365    if (opc1 != 0x1F) {
8366       vex_printf( "dis_vx_store(ppc)(instr)\n" );
8367       return False;
8368    }
8369
8370    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
8371    assign( vS, getVSReg( XS ) );
8372
8373    switch (opc2) {
8374    case 0x2CC:
8375    {
8376       IRExpr * high64;
8377       DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
8378       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
8379       storeBE( mkexpr( EA ), high64 );
8380       break;
8381    }
8382    case 0x3CC:
8383    {
8384       IRExpr * high64, *low64;
8385       DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
8386       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
8387       low64 = unop( Iop_V128to64, mkexpr( vS ) );
8388       storeBE( mkexpr( EA ), high64 );
8389       storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 )
8390             : mkU32( 8 ) ), low64 );
8391       break;
8392    }
8393    case 0x38C:
8394    {
8395       UInt ea_off = 0;
8396       IRExpr* irx_addr;
8397       IRTemp hi64 = newTemp( Ity_I64 );
8398       IRTemp lo64 = newTemp( Ity_I64 );
8399
8400       DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
8401
8402       // This instruction supports word-aligned stores, so EA may not be
8403       // quad-word aligned.  Therefore, do 4 individual word-size stores.
8404       assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
8405       assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
8406
8407       storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
8408       ea_off += 4;
8409       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8410                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8411       storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
8412       ea_off += 4;
8413       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8414                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8415       storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
8416       ea_off += 4;
8417       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8418                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8419       storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
8420
8421       break;
8422    }
8423    default:
8424       vex_printf( "dis_vx_store(ppc)(opc2)\n" );
8425       return False;
8426    }
8427    return True;
8428 }
8429
8430 /*
8431  * VSX Permute Instructions
8432  */
8433 static Bool
8434 dis_vx_permute( UInt theInstr, UInt opc2 )
8435 {
8436    /* XX3-Form */
8437    UChar opc1 = ifieldOPC( theInstr );
8438    UChar XT = ifieldRegXT ( theInstr );
8439    UChar XA = ifieldRegXA ( theInstr );
8440    UChar XB = ifieldRegXB ( theInstr );
8441    IRTemp vT = newTemp( Ity_V128 );
8442    IRTemp vA = newTemp( Ity_V128 );
8443    IRTemp vB = newTemp( Ity_V128 );
8444
8445    if (opc1 != 0x3C) {
8446       vex_printf( "dis_vx_permute(ppc)(instr)\n" );
8447       return False;
8448    }
8449
8450    assign( vA, getVSReg( XA ) );
8451    assign( vB, getVSReg( XB ) );
8452
8453    switch (opc2) {
8454       case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
8455       {
8456          UChar SHW = ifieldSHW ( theInstr );
8457          IRTemp result = newTemp(Ity_V128);
8458          if ( SHW != 0 ) {
8459              IRTemp hi = newTemp(Ity_V128);
8460              IRTemp lo = newTemp(Ity_V128);
8461              assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
8462              assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
8463              assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
8464          } else
8465              assign ( result, mkexpr(vA) );
8466          DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW);
8467          putVSReg( XT, mkexpr(result) );
8468          break;
8469       }
8470       case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
8471       {
8472          UChar DM = ifieldDM ( theInstr );
8473          IRTemp hi = newTemp(Ity_I64);
8474          IRTemp lo = newTemp(Ity_I64);
8475
8476          if (DM & 0x2)
8477            assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
8478          else
8479            assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
8480
8481          if (DM & 0x1)
8482            assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
8483          else
8484            assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
8485
8486          assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
8487
8488          DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM);
8489          putVSReg( XT, mkexpr( vT ) );
8490          break;
8491       }
8492       case 0x48: // xxmrghw (VSX Merge High Word)
8493       case 0xc8: // xxmrglw (VSX Merge Low Word)
8494       {
8495          char type = (opc2 == 0x48) ? 'h' : 'l';
8496          IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
8497          IRTemp a64 = newTemp(Ity_I64);
8498          IRTemp ahi32 = newTemp(Ity_I32);
8499          IRTemp alo32 = newTemp(Ity_I32);
8500          IRTemp b64 = newTemp(Ity_I64);
8501          IRTemp bhi32 = newTemp(Ity_I32);
8502          IRTemp blo32 = newTemp(Ity_I32);
8503
8504          assign( a64, unop(word_op, mkexpr(vA)) );
8505          assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
8506          assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
8507
8508          assign( b64, unop(word_op, mkexpr(vB)) );
8509          assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
8510          assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
8511
8512          assign( vT, binop(Iop_64HLtoV128,
8513                            binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
8514                            binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
8515
8516          DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB);
8517          putVSReg( XT, mkexpr( vT ) );
8518          break;
8519       }
8520
8521       default:
8522          vex_printf( "dis_vx_permute(ppc)(opc2)\n" );
8523          return False;
8524    }
8525    return True;
8526 }
8527
8528 /*
8529   AltiVec Load Instructions
8530 */
8531 static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
8532 {
8533    /* X-Form */
8534    UChar opc1     = ifieldOPC(theInstr);
8535    UChar vD_addr  = ifieldRegDS(theInstr);
8536    UChar rA_addr  = ifieldRegA(theInstr);
8537    UChar rB_addr  = ifieldRegB(theInstr);
8538    UInt  opc2     = ifieldOPClo10(theInstr);
8539    UChar b0       = ifieldBIT0(theInstr);
8540
8541    IRType ty         = mode64 ? Ity_I64 : Ity_I32;
8542    IRTemp EA         = newTemp(ty);
8543    IRTemp EA_align16 = newTemp(ty);
8544
8545    if (opc1 != 0x1F || b0 != 0) {
8546       vex_printf("dis_av_load(ppc)(instr)\n");
8547       return False;
8548    }
8549
8550    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8551    assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
8552
8553    switch (opc2) {
8554
8555    case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
8556       IRDirty* d;
8557       UInt vD_off = vectorGuestRegOffset(vD_addr);
8558       IRExpr** args = mkIRExprVec_3(
8559                          mkU32(vD_off), 
8560                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
8561                                           mkU32(0xF)),
8562                          mkU32(0)/*left*/ );
8563       if (!mode64) {
8564          d = unsafeIRDirty_0_N (
8565                         0/*regparms*/, 
8566                         "ppc32g_dirtyhelper_LVS",
8567                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
8568                         args );
8569       } else {
8570          d = unsafeIRDirty_0_N (
8571                         0/*regparms*/, 
8572                         "ppc64g_dirtyhelper_LVS",
8573                         fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
8574                         args );
8575       }
8576       DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8577       /* declare guest state effects */
8578       d->needsBBP = True;
8579       d->nFxState = 1;
8580       d->fxState[0].fx     = Ifx_Write;
8581       d->fxState[0].offset = vD_off;
8582       d->fxState[0].size   = sizeof(U128);
8583
8584       /* execute the dirty call, side-effecting guest state */
8585       stmt( IRStmt_Dirty(d) );
8586       break;
8587    }
8588    case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
8589       IRDirty* d;
8590       UInt vD_off = vectorGuestRegOffset(vD_addr);
8591       IRExpr** args = mkIRExprVec_3(
8592                          mkU32(vD_off), 
8593                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
8594                                           mkU32(0xF)),
8595                          mkU32(1)/*right*/ );
8596       if (!mode64) {
8597          d = unsafeIRDirty_0_N (
8598                         0/*regparms*/, 
8599                         "ppc32g_dirtyhelper_LVS",
8600                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
8601                         args );
8602       } else {
8603          d = unsafeIRDirty_0_N (
8604                         0/*regparms*/, 
8605                         "ppc64g_dirtyhelper_LVS",
8606                         fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
8607                         args );
8608       }
8609       DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8610       /* declare guest state effects */
8611       d->needsBBP = True;
8612       d->nFxState = 1;
8613       d->fxState[0].fx     = Ifx_Write;
8614       d->fxState[0].offset = vD_off;
8615       d->fxState[0].size   = sizeof(U128);
8616
8617       /* execute the dirty call, side-effecting guest state */
8618       stmt( IRStmt_Dirty(d) );
8619       break;
8620    }
8621    case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
8622       DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8623       /* loads addressed byte into vector[EA[0:3]
8624          since all other destination bytes are undefined,
8625          can simply load entire vector from 16-aligned EA */
8626       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
8627       break;
8628
8629    case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
8630       DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8631       /* see note for lvebx */
8632       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
8633       break;
8634
8635    case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
8636       DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8637       /* see note for lvebx */
8638       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
8639       break;
8640
8641    case 0x067: // lvx (Load Vector Indexed, AV p127)
8642       DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8643       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
8644       break;
8645
8646    case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
8647       DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8648       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
8649       break;
8650
8651    default:
8652       vex_printf("dis_av_load(ppc)(opc2)\n");
8653       return False;
8654    }
8655    return True;
8656 }
8657
8658 /*
8659   AltiVec Store Instructions
8660 */
8661 static Bool dis_av_store ( UInt theInstr )
8662 {
8663    /* X-Form */
8664    UChar opc1     = ifieldOPC(theInstr);
8665    UChar vS_addr  = ifieldRegDS(theInstr);
8666    UChar rA_addr  = ifieldRegA(theInstr);
8667    UChar rB_addr  = ifieldRegB(theInstr);
8668    UInt  opc2     = ifieldOPClo10(theInstr);
8669    UChar b0       = ifieldBIT0(theInstr);
8670
8671    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
8672    IRTemp EA           = newTemp(ty);
8673    IRTemp addr_aligned = newTemp(ty);
8674    IRTemp vS           = newTemp(Ity_V128);
8675    IRTemp eb           = newTemp(Ity_I8);
8676    IRTemp idx          = newTemp(Ity_I8);
8677
8678    if (opc1 != 0x1F || b0 != 0) {
8679       vex_printf("dis_av_store(ppc)(instr)\n");
8680       return False;
8681    }
8682
8683    assign( vS, getVReg(vS_addr));
8684    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8685
8686    switch (opc2) {
8687    case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
8688       DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
8689       assign( eb, binop(Iop_And8, mkU8(0xF),
8690                         unop(Iop_32to8,
8691                              mkNarrowTo32(ty, mkexpr(EA)) )) );
8692       assign( idx, binop(Iop_Shl8,
8693                          binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
8694                          mkU8(3)) );
8695       storeBE( mkexpr(EA),
8696                unop(Iop_32to8, unop(Iop_V128to32,
8697                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
8698       break;
8699    }
8700    case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
8701       DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
8702       assign( addr_aligned, addr_align(mkexpr(EA), 2) );
8703       assign( eb, binop(Iop_And8, mkU8(0xF),
8704                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
8705       assign( idx, binop(Iop_Shl8,
8706                          binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
8707                          mkU8(3)) );
8708       storeBE( mkexpr(addr_aligned),
8709                unop(Iop_32to16, unop(Iop_V128to32,
8710                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
8711       break;
8712    }
8713    case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
8714       DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
8715       assign( addr_aligned, addr_align(mkexpr(EA), 4) );
8716       assign( eb, binop(Iop_And8, mkU8(0xF),
8717                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
8718       assign( idx, binop(Iop_Shl8,
8719                          binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
8720                          mkU8(3)) );
8721       storeBE( mkexpr(addr_aligned),
8722                unop(Iop_V128to32,
8723                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
8724       break;
8725    }
8726
8727    case 0x0E7: // stvx (Store Vector Indexed, AV p134)
8728       DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
8729       storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
8730       break;
8731
8732    case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
8733       DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
8734       storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
8735       break;
8736
8737    default:
8738       vex_printf("dis_av_store(ppc)(opc2)\n");
8739       return False;
8740    }
8741    return True;
8742 }
8743
8744 /*
8745   AltiVec Arithmetic Instructions
8746 */
8747 static Bool dis_av_arith ( UInt theInstr )
8748 {
8749    /* VX-Form */
8750    UChar opc1     = ifieldOPC(theInstr);
8751    UChar vD_addr  = ifieldRegDS(theInstr);
8752    UChar vA_addr  = ifieldRegA(theInstr);
8753    UChar vB_addr  = ifieldRegB(theInstr);
8754    UInt  opc2     = IFIELD( theInstr, 0, 11 );
8755
8756    IRTemp vA = newTemp(Ity_V128);
8757    IRTemp vB = newTemp(Ity_V128);
8758    IRTemp z3 = newTemp(Ity_I64);
8759    IRTemp z2 = newTemp(Ity_I64);
8760    IRTemp z1 = newTemp(Ity_I64);
8761    IRTemp z0 = newTemp(Ity_I64);
8762    IRTemp aEvn, aOdd;
8763    IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
8764    IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
8765    IRTemp b3, b2, b1, b0;
8766
8767    aEvn = aOdd = IRTemp_INVALID;
8768    a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
8769    a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
8770    b3 = b2 = b1 = b0 = IRTemp_INVALID;
8771
8772    assign( vA, getVReg(vA_addr));
8773    assign( vB, getVReg(vB_addr));
8774
8775    if (opc1 != 0x4) {
8776       vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
8777       return False;
8778    }
8779
8780    switch (opc2) {
8781    /* Add */
8782    case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
8783       DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8784       /* unsigned_ov(x+y) = (y >u not(x)) */
8785       putVReg( vD_addr, binop(Iop_ShrN32x4,
8786                               binop(Iop_CmpGT32Ux4, mkexpr(vB),
8787                                     unop(Iop_NotV128, mkexpr(vA))),
8788                               mkU8(31)) );
8789       break;
8790    }
8791    case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
8792       DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8793       putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
8794       break;
8795
8796    case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
8797       DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8798       putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
8799       break;
8800
8801    case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
8802       DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8803       putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
8804       break;
8805
8806    case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
8807       DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8808       putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
8809       // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
8810       break;
8811
8812    case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
8813       DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8814       putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
8815       // TODO: set VSCR[SAT]
8816       break;
8817
8818    case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
8819       DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8820       putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
8821       // TODO: set VSCR[SAT]
8822       break;
8823
8824    case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
8825       DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8826       putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
8827       // TODO: set VSCR[SAT]
8828       break;
8829
8830    case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
8831       DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8832       putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
8833       // TODO: set VSCR[SAT]
8834       break;
8835
8836    case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
8837       DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8838       putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
8839       // TODO: set VSCR[SAT]
8840       break;
8841
8842
8843    /* Subtract */
8844    case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
8845       DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8846       /* unsigned_ov(x-y) = (y >u x) */
8847       putVReg( vD_addr, binop(Iop_ShrN32x4,
8848                               unop(Iop_NotV128,
8849                                    binop(Iop_CmpGT32Ux4, mkexpr(vB),
8850                                          mkexpr(vA))),
8851                               mkU8(31)) );
8852       break;
8853    }     
8854    case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
8855       DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8856       putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
8857       break;
8858
8859    case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
8860       DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8861       putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
8862       break;
8863
8864    case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
8865       DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8866       putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
8867       break;
8868
8869    case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
8870       DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8871       putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
8872       // TODO: set VSCR[SAT]
8873       break;
8874
8875    case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
8876       DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8877       putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
8878       // TODO: set VSCR[SAT]
8879       break;
8880
8881    case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
8882       DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8883       putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
8884       // TODO: set VSCR[SAT]
8885       break;
8886
8887    case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
8888       DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8889       putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
8890       // TODO: set VSCR[SAT]
8891       break;
8892
8893    case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
8894       DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8895       putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
8896       // TODO: set VSCR[SAT]
8897       break;
8898
8899    case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
8900       DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8901       putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
8902       // TODO: set VSCR[SAT]
8903       break;
8904
8905
8906    /* Maximum */
8907    case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
8908       DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8909       putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
8910       break;
8911
8912    case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
8913       DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8914       putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
8915       break;
8916
8917    case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
8918       DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8919       putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
8920       break;
8921
8922    case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
8923       DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8924       putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
8925       break;
8926
8927    case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
8928       DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8929       putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
8930       break;
8931
8932    case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
8933       DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8934       putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
8935       break;
8936
8937
8938    /* Minimum */
8939    case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
8940       DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8941       putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
8942       break;
8943
8944    case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
8945       DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8946       putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
8947       break;
8948
8949    case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
8950       DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8951       putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
8952       break;
8953
8954    case 0x302: // vminsb (Minimum Signed Byte, AV p188)
8955       DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8956       putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
8957       break;
8958
8959    case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
8960       DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8961       putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
8962       break;
8963
8964    case 0x382: // vminsw (Minimum Signed Word, AV p190)
8965       DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8966       putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
8967       break;
8968
8969
8970    /* Average */
8971    case 0x402: // vavgub (Average Unsigned Byte, AV p152)
8972       DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8973       putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
8974       break;
8975
8976    case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
8977       DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8978       putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
8979       break;
8980
8981    case 0x482: // vavguw (Average Unsigned Word, AV p154)
8982       DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8983       putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
8984       break;
8985
8986    case 0x502: // vavgsb (Average Signed Byte, AV p149)
8987       DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8988       putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
8989       break;
8990
8991    case 0x542: // vavgsh (Average Signed Half Word, AV p150)
8992       DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8993       putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
8994       break;
8995
8996    case 0x582: // vavgsw (Average Signed Word, AV p151)
8997       DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8998       putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
8999       break;
9000
9001
9002    /* Multiply */
9003    case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
9004       DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9005       putVReg( vD_addr,
9006                binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
9007       break;
9008
9009    case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
9010       DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9011       putVReg( vD_addr,
9012                binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
9013       break;
9014
9015    case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
9016       DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9017       putVReg( vD_addr,
9018                binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
9019       break;
9020
9021    case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
9022       DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9023       putVReg( vD_addr,
9024                binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
9025       break;
9026
9027    case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
9028       DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9029       putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
9030       break;
9031
9032    case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
9033       DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9034       putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
9035       break;
9036
9037    case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
9038       DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9039       putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
9040       break;
9041
9042    case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
9043       DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9044       putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
9045       break;
9046
9047
9048    /* Sum Across Partial */
9049    case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
9050       IRTemp aEE, aEO, aOE, aOO;
9051       aEE = aEO = aOE = aOO = IRTemp_INVALID;
9052       DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9053
9054       /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
9055       expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
9056       expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
9057       expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
9058
9059       /* break V128 to 4xI32's, zero-extending to I64's */
9060       breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
9061       breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
9062       breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
9063       breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
9064       breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
9065
9066       /* add lanes */
9067       assign( z3, binop(Iop_Add64, mkexpr(b3),
9068                      binop(Iop_Add64,
9069                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
9070                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
9071       assign( z2, binop(Iop_Add64, mkexpr(b2),
9072                      binop(Iop_Add64,
9073                          binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
9074                          binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
9075       assign( z1, binop(Iop_Add64, mkexpr(b1),
9076                      binop(Iop_Add64,
9077                          binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
9078                          binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
9079       assign( z0, binop(Iop_Add64, mkexpr(b0),
9080                      binop(Iop_Add64,
9081                          binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
9082                          binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
9083       
9084       /* saturate-narrow to 32bit, and combine to V128 */
9085       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
9086                                          mkexpr(z1), mkexpr(z0)) );
9087       break;
9088    }
9089    case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
9090       IRTemp aEE, aEO, aOE, aOO;
9091       aEE = aEO = aOE = aOO = IRTemp_INVALID;
9092       DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9093
9094       /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
9095       expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
9096       expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
9097       expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
9098
9099       /* break V128 to 4xI32's, sign-extending to I64's */
9100       breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
9101       breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
9102       breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
9103       breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
9104       breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
9105
9106       /* add lanes */
9107       assign( z3, binop(Iop_Add64, mkexpr(b3),
9108                      binop(Iop_Add64,
9109                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
9110                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
9111       assign( z2, binop(Iop_Add64, mkexpr(b2),
9112                      binop(Iop_Add64,
9113                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
9114                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
9115       assign( z1, binop(Iop_Add64, mkexpr(b1),
9116                      binop(Iop_Add64,
9117                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
9118                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
9119       assign( z0, binop(Iop_Add64, mkexpr(b0),
9120                      binop(Iop_Add64,
9121                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
9122                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
9123       
9124       /* saturate-narrow to 32bit, and combine to V128 */
9125       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
9126                                          mkexpr(z1), mkexpr(z0)) );
9127       break;
9128    }
9129    case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
9130       DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9131
9132       /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
9133       expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
9134
9135       /* break V128 to 4xI32's, sign-extending to I64's */
9136       breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
9137       breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
9138       breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
9139
9140       /* add lanes */
9141       assign( z3, binop(Iop_Add64, mkexpr(b3),
9142                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
9143       assign( z2, binop(Iop_Add64, mkexpr(b2),
9144                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
9145       assign( z1, binop(Iop_Add64, mkexpr(b1),
9146                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
9147       assign( z0, binop(Iop_Add64, mkexpr(b0),
9148                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
9149
9150       /* saturate-narrow to 32bit, and combine to V128 */
9151       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
9152                                          mkexpr(z1), mkexpr(z0)) );
9153       break;
9154    }
9155    case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
9156       DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9157
9158       /* break V128 to 4xI32's, sign-extending to I64's */
9159       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
9160       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
9161
9162       /* add lanes */
9163       assign( z2, binop(Iop_Add64, mkexpr(b2),
9164                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
9165       assign( z0, binop(Iop_Add64, mkexpr(b0),
9166                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
9167
9168       /* saturate-narrow to 32bit, and combine to V128 */
9169       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
9170                                          mkU64(0), mkexpr(z0)) );
9171       break;
9172    }
9173    case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
9174       DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9175
9176       /* break V128 to 4xI32's, sign-extending to I64's */
9177       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
9178       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
9179
9180       /* add lanes */
9181       assign( z0, binop(Iop_Add64, mkexpr(b0),
9182                      binop(Iop_Add64,
9183                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
9184                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
9185
9186       /* saturate-narrow to 32bit, and combine to V128 */
9187       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
9188                                          mkU64(0), mkexpr(z0)) );
9189       break;
9190    }
9191    default:
9192       vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
9193       return False;
9194    }
9195    return True;
9196 }
9197
9198 /*
9199   AltiVec Logic Instructions
9200 */
9201 static Bool dis_av_logic ( UInt theInstr )
9202 {
9203    /* VX-Form */
9204    UChar opc1    = ifieldOPC(theInstr);
9205    UChar vD_addr = ifieldRegDS(theInstr);
9206    UChar vA_addr = ifieldRegA(theInstr);
9207    UChar vB_addr = ifieldRegB(theInstr);
9208    UInt  opc2    = IFIELD( theInstr, 0, 11 );
9209
9210    IRTemp vA = newTemp(Ity_V128);
9211    IRTemp vB = newTemp(Ity_V128);
9212    assign( vA, getVReg(vA_addr));
9213    assign( vB, getVReg(vB_addr));
9214
9215    if (opc1 != 0x4) {
9216       vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
9217       return False;
9218    }
9219
9220    switch (opc2) {
9221    case 0x404: // vand (And, AV p147)
9222       DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9223       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
9224       break;
9225
9226    case 0x444: // vandc (And, AV p148)
9227       DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9228       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
9229                               unop(Iop_NotV128, mkexpr(vB))) );
9230       break;
9231
9232    case 0x484: // vor (Or, AV p217)
9233       DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9234       putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
9235       break;
9236
9237    case 0x4C4: // vxor (Xor, AV p282)
9238       DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9239       putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
9240       break;
9241
9242    case 0x504: // vnor (Nor, AV p216)
9243       DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9244       putVReg( vD_addr,
9245          unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
9246       break;
9247
9248    default:
9249       vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
9250       return False;
9251    }
9252    return True;
9253 }
9254
9255 /*
9256   AltiVec Compare Instructions
9257 */
9258 static Bool dis_av_cmp ( UInt theInstr )
9259 {
9260    /* VXR-Form */
9261    UChar opc1     = ifieldOPC(theInstr);
9262    UChar vD_addr  = ifieldRegDS(theInstr);
9263    UChar vA_addr  = ifieldRegA(theInstr);
9264    UChar vB_addr  = ifieldRegB(theInstr);
9265    UChar flag_rC  = ifieldBIT10(theInstr);
9266    UInt  opc2     = IFIELD( theInstr, 0, 10 );
9267
9268    IRTemp vA = newTemp(Ity_V128);
9269    IRTemp vB = newTemp(Ity_V128);
9270    IRTemp vD = newTemp(Ity_V128);
9271    assign( vA, getVReg(vA_addr));
9272    assign( vB, getVReg(vB_addr));
9273
9274    if (opc1 != 0x4) {
9275       vex_printf("dis_av_cmp(ppc)(instr)\n");
9276       return False;
9277    }
9278
9279    switch (opc2) {
9280    case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
9281       DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9282                                       vD_addr, vA_addr, vB_addr);
9283       assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
9284       break;
9285
9286    case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
9287       DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9288                                       vD_addr, vA_addr, vB_addr);
9289       assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
9290       break;
9291
9292    case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
9293       DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9294                                       vD_addr, vA_addr, vB_addr);
9295       assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
9296       break;
9297
9298    case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
9299       DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9300                                       vD_addr, vA_addr, vB_addr);
9301       assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
9302       break;
9303
9304    case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
9305       DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9306                                       vD_addr, vA_addr, vB_addr);
9307       assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
9308       break;
9309
9310    case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
9311       DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9312                                        vD_addr, vA_addr, vB_addr);
9313       assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
9314       break;
9315
9316    case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
9317       DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9318                                        vD_addr, vA_addr, vB_addr);
9319       assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
9320       break;
9321
9322    case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
9323       DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9324                                       vD_addr, vA_addr, vB_addr);
9325       assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
9326       break;
9327
9328    case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
9329       DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9330                                       vD_addr, vA_addr, vB_addr);
9331       assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
9332       break;
9333
9334    default:
9335       vex_printf("dis_av_cmp(ppc)(opc2)\n");
9336       return False;
9337    }
9338
9339    putVReg( vD_addr, mkexpr(vD) );
9340
9341    if (flag_rC) {
9342       set_AV_CR6( mkexpr(vD), True );
9343    }
9344    return True;
9345 }
9346
9347 /*
9348   AltiVec Multiply-Sum Instructions
9349 */
9350 static Bool dis_av_multarith ( UInt theInstr )
9351 {
9352    /* VA-Form */
9353    UChar opc1     = ifieldOPC(theInstr);
9354    UChar vD_addr  = ifieldRegDS(theInstr);
9355    UChar vA_addr  = ifieldRegA(theInstr);
9356    UChar vB_addr  = ifieldRegB(theInstr);
9357    UChar vC_addr  = ifieldRegC(theInstr);
9358    UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
9359
9360    IRTemp vA    = newTemp(Ity_V128);
9361    IRTemp vB    = newTemp(Ity_V128);
9362    IRTemp vC    = newTemp(Ity_V128);
9363    IRTemp zeros = newTemp(Ity_V128);
9364    IRTemp aLo   = newTemp(Ity_V128);
9365    IRTemp bLo   = newTemp(Ity_V128);
9366    IRTemp cLo   = newTemp(Ity_V128);
9367    IRTemp zLo   = newTemp(Ity_V128);
9368    IRTemp aHi   = newTemp(Ity_V128);
9369    IRTemp bHi   = newTemp(Ity_V128);
9370    IRTemp cHi   = newTemp(Ity_V128);
9371    IRTemp zHi   = newTemp(Ity_V128);
9372    IRTemp abEvn = newTemp(Ity_V128);
9373    IRTemp abOdd = newTemp(Ity_V128);
9374    IRTemp z3    = newTemp(Ity_I64);
9375    IRTemp z2    = newTemp(Ity_I64);
9376    IRTemp z1    = newTemp(Ity_I64);
9377    IRTemp z0    = newTemp(Ity_I64);
9378    IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
9379    IRTemp c3, c2, c1, c0;
9380
9381    ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
9382    c3 = c2 = c1 = c0 = IRTemp_INVALID;
9383
9384    assign( vA, getVReg(vA_addr));
9385    assign( vB, getVReg(vB_addr));
9386    assign( vC, getVReg(vC_addr));
9387    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
9388
9389    if (opc1 != 0x4) {
9390       vex_printf("dis_av_multarith(ppc)(instr)\n");
9391       return False;
9392    }
9393
9394    switch (opc2) {
9395    /* Multiply-Add */
9396    case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
9397       IRTemp cSigns = newTemp(Ity_V128);
9398       DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
9399           vD_addr, vA_addr, vB_addr, vC_addr);
9400       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
9401       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
9402       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
9403       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
9404       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
9405       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
9406       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
9407
9408       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
9409                          binop(Iop_SarN32x4,
9410                                binop(Iop_MullEven16Sx8,
9411                                      mkexpr(aLo), mkexpr(bLo)),
9412                                mkU8(15))) );
9413
9414       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
9415                          binop(Iop_SarN32x4,
9416                                binop(Iop_MullEven16Sx8,
9417                                      mkexpr(aHi), mkexpr(bHi)),
9418                                mkU8(15))) );
9419
9420       putVReg( vD_addr,
9421                binop(Iop_QNarrow32Sx4, mkexpr(zHi), mkexpr(zLo)) );
9422       break;
9423    }
9424    case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
9425       IRTemp zKonst = newTemp(Ity_V128);
9426       IRTemp cSigns = newTemp(Ity_V128);
9427       DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
9428           vD_addr, vA_addr, vB_addr, vC_addr);
9429       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
9430       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
9431       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
9432       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
9433       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
9434       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
9435       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
9436
9437       /* shifting our const avoids store/load version of Dup */
9438       assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
9439                             mkU8(14)) );
9440
9441       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
9442                          binop(Iop_SarN32x4,
9443                                binop(Iop_Add32x4, mkexpr(zKonst),
9444                                      binop(Iop_MullEven16Sx8,
9445                                            mkexpr(aLo), mkexpr(bLo))),
9446                                mkU8(15))) );
9447
9448       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
9449                          binop(Iop_SarN32x4,
9450                                binop(Iop_Add32x4, mkexpr(zKonst),
9451                                      binop(Iop_MullEven16Sx8,
9452                                            mkexpr(aHi), mkexpr(bHi))),
9453                                mkU8(15))) );
9454
9455       putVReg( vD_addr, binop(Iop_QNarrow32Sx4, mkexpr(zHi), mkexpr(zLo)) );
9456       break;
9457    }
9458    case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
9459       DIP("vmladduhm v%d,v%d,v%d,v%d\n",
9460           vD_addr, vA_addr, vB_addr, vC_addr);
9461       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
9462       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
9463       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
9464       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
9465       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
9466       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
9467       assign(zLo, binop(Iop_Add32x4,
9468                      binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
9469                      mkexpr(cLo)) );
9470       assign(zHi, binop(Iop_Add32x4,
9471                      binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
9472                      mkexpr(cHi)));
9473       putVReg(vD_addr, binop(Iop_Narrow32x4, mkexpr(zHi), mkexpr(zLo)));
9474       break;
9475    }
9476
9477
9478    /* Multiply-Sum */
9479    case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
9480       IRTemp abEE, abEO, abOE, abOO;
9481       abEE = abEO = abOE = abOO = IRTemp_INVALID;
9482       DIP("vmsumubm v%d,v%d,v%d,v%d\n",
9483           vD_addr, vA_addr, vB_addr, vC_addr);
9484
9485       /* multiply vA,vB (unsigned, widening) */
9486       assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
9487       assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
9488       
9489       /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
9490       expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
9491       expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
9492       
9493       putVReg( vD_addr,
9494          binop(Iop_Add32x4, mkexpr(vC),
9495                binop(Iop_Add32x4,
9496                      binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
9497                      binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
9498       break;
9499    }
9500    case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
9501       IRTemp aEvn, aOdd, bEvn, bOdd;
9502       IRTemp abEE = newTemp(Ity_V128);
9503       IRTemp abEO = newTemp(Ity_V128);
9504       IRTemp abOE = newTemp(Ity_V128);
9505       IRTemp abOO = newTemp(Ity_V128);
9506       aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
9507       DIP("vmsummbm v%d,v%d,v%d,v%d\n",
9508           vD_addr, vA_addr, vB_addr, vC_addr);
9509
9510       /* sign-extend vA, zero-extend vB, for mixed-sign multiply
9511          (separating out adjacent lanes to different vectors) */
9512       expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
9513       expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
9514
9515       /* multiply vA, vB, again separating adjacent lanes */
9516       assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
9517       assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
9518       assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
9519       assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
9520
9521       /* add results together, + vC */
9522       putVReg( vD_addr,
9523          binop(Iop_QAdd32Sx4, mkexpr(vC),
9524                binop(Iop_QAdd32Sx4,
9525                      binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
9526                      binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
9527       break;
9528    }
9529    case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
9530       DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
9531           vD_addr, vA_addr, vB_addr, vC_addr);
9532       assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
9533       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
9534       putVReg( vD_addr,
9535          binop(Iop_Add32x4, mkexpr(vC),
9536                binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
9537       break;
9538    }
9539    case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
9540       DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
9541           vD_addr, vA_addr, vB_addr, vC_addr);
9542       /* widening multiply, separating lanes */
9543       assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
9544       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
9545
9546       /* break V128 to 4xI32's, zero-extending to I64's */
9547       breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
9548       breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
9549       breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
9550
9551       /* add lanes */
9552       assign( z3, binop(Iop_Add64, mkexpr(c3),
9553                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
9554       assign( z2, binop(Iop_Add64, mkexpr(c2),
9555                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
9556       assign( z1, binop(Iop_Add64, mkexpr(c1),
9557                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
9558       assign( z0, binop(Iop_Add64, mkexpr(c0),
9559                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
9560
9561       /* saturate-narrow to 32bit, and combine to V128 */
9562       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
9563                                          mkexpr(z1), mkexpr(z0)) );
9564
9565       break;
9566    }
9567    case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
9568       DIP("vmsumshm v%d,v%d,v%d,v%d\n",
9569           vD_addr, vA_addr, vB_addr, vC_addr);
9570       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
9571       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
9572       putVReg( vD_addr,
9573          binop(Iop_Add32x4, mkexpr(vC),
9574                binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
9575       break;
9576    }
9577    case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
9578       DIP("vmsumshs v%d,v%d,v%d,v%d\n",
9579           vD_addr, vA_addr, vB_addr, vC_addr);
9580       /* widening multiply, separating lanes */
9581       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
9582       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
9583
9584       /* break V128 to 4xI32's, sign-extending to I64's */
9585       breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
9586       breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
9587       breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
9588
9589       /* add lanes */
9590       assign( z3, binop(Iop_Add64, mkexpr(c3),
9591                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
9592       assign( z2, binop(Iop_Add64, mkexpr(c2),
9593                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
9594       assign( z1, binop(Iop_Add64, mkexpr(c1),
9595                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
9596       assign( z0, binop(Iop_Add64, mkexpr(c0),
9597                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
9598
9599       /* saturate-narrow to 32bit, and combine to V128 */
9600       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
9601                                          mkexpr(z1), mkexpr(z0)) );
9602       break;
9603    }
9604    default:
9605       vex_printf("dis_av_multarith(ppc)(opc2)\n");
9606       return False;
9607    }
9608    return True;
9609 }
9610
9611 /*
9612   AltiVec Shift/Rotate Instructions
9613 */
9614 static Bool dis_av_shift ( UInt theInstr )
9615 {
9616    /* VX-Form */
9617    UChar opc1    = ifieldOPC(theInstr);
9618    UChar vD_addr = ifieldRegDS(theInstr);
9619    UChar vA_addr = ifieldRegA(theInstr);
9620    UChar vB_addr = ifieldRegB(theInstr);
9621    UInt  opc2    = IFIELD( theInstr, 0, 11 );
9622
9623    IRTemp vA = newTemp(Ity_V128);
9624    IRTemp vB = newTemp(Ity_V128);
9625    assign( vA, getVReg(vA_addr));
9626    assign( vB, getVReg(vB_addr));
9627
9628    if (opc1 != 0x4){
9629       vex_printf("dis_av_shift(ppc)(instr)\n");
9630       return False;
9631    }
9632
9633    switch (opc2) {
9634    /* Rotate */
9635    case 0x004: // vrlb (Rotate Left Integer B, AV p234)
9636       DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9637       putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
9638       break;
9639
9640    case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
9641       DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9642       putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
9643       break;
9644
9645    case 0x084: // vrlw (Rotate Left Integer W, AV p236)
9646       DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9647       putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
9648       break;
9649
9650
9651    /* Shift Left */
9652    case 0x104: // vslb (Shift Left Integer B, AV p240)
9653       DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9654       putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
9655       break;
9656
9657    case 0x144: // vslh (Shift Left Integer HW, AV p242)
9658       DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9659       putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
9660       break;
9661
9662    case 0x184: // vslw (Shift Left Integer W, AV p244)
9663       DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9664       putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
9665       break;
9666
9667    case 0x1C4: { // vsl (Shift Left, AV p239)
9668       IRTemp sh = newTemp(Ity_I8);
9669       DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9670       assign( sh, binop(Iop_And8, mkU8(0x7),
9671                         unop(Iop_32to8,
9672                              unop(Iop_V128to32, mkexpr(vB)))) );
9673       putVReg( vD_addr,
9674                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
9675       break;
9676    }
9677    case 0x40C: { // vslo (Shift Left by Octet, AV p243)
9678       IRTemp sh = newTemp(Ity_I8);
9679       DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9680       assign( sh, binop(Iop_And8, mkU8(0x78),
9681                         unop(Iop_32to8,
9682                              unop(Iop_V128to32, mkexpr(vB)))) );
9683       putVReg( vD_addr,
9684                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
9685       break;
9686    }
9687
9688
9689    /* Shift Right */
9690    case 0x204: // vsrb (Shift Right B, AV p256)
9691       DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9692       putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
9693       break;
9694
9695    case 0x244: // vsrh (Shift Right HW, AV p257)
9696       DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9697       putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
9698       break;
9699
9700    case 0x284: // vsrw (Shift Right W, AV p259)
9701       DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9702       putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
9703       break;
9704
9705    case 0x2C4: { // vsr (Shift Right, AV p251)
9706       IRTemp sh = newTemp(Ity_I8);
9707       DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9708       assign( sh, binop(Iop_And8, mkU8(0x7),
9709                         unop(Iop_32to8,
9710                              unop(Iop_V128to32, mkexpr(vB)))) );
9711       putVReg( vD_addr,
9712                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
9713       break;
9714    }
9715    case 0x304: // vsrab (Shift Right Alg B, AV p253)
9716       DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9717       putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
9718       break;
9719
9720    case 0x344: // vsrah (Shift Right Alg HW, AV p254)
9721       DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9722       putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
9723       break;
9724
9725    case 0x384: // vsraw (Shift Right Alg W, AV p255)
9726       DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9727       putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
9728       break;
9729
9730    case 0x44C: { // vsro (Shift Right by Octet, AV p258)
9731       IRTemp sh = newTemp(Ity_I8);
9732       DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9733       assign( sh, binop(Iop_And8, mkU8(0x78),
9734                         unop(Iop_32to8,
9735                              unop(Iop_V128to32, mkexpr(vB)))) );
9736       putVReg( vD_addr,
9737                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
9738       break;
9739    }
9740
9741    default:
9742       vex_printf("dis_av_shift(ppc)(opc2)\n");
9743       return False;
9744    }
9745    return True;
9746 }
9747
9748 /*
9749   AltiVec Permute Instructions
9750 */
9751 static Bool dis_av_permute ( UInt theInstr )
9752 {
9753    /* VA-Form, VX-Form */
9754    UChar opc1      = ifieldOPC(theInstr);
9755    UChar vD_addr   = ifieldRegDS(theInstr);
9756    UChar vA_addr   = ifieldRegA(theInstr);
9757    UChar UIMM_5    = vA_addr;
9758    UChar vB_addr   = ifieldRegB(theInstr);
9759    UChar vC_addr   = ifieldRegC(theInstr);
9760    UChar b10       = ifieldBIT10(theInstr);
9761    UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
9762    UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
9763
9764    UChar SIMM_8 = extend_s_5to8(UIMM_5);
9765
9766    IRTemp vA = newTemp(Ity_V128);
9767    IRTemp vB = newTemp(Ity_V128);
9768    IRTemp vC = newTemp(Ity_V128);
9769    assign( vA, getVReg(vA_addr));
9770    assign( vB, getVReg(vB_addr));
9771    assign( vC, getVReg(vC_addr));
9772
9773    if (opc1 != 0x4) {
9774       vex_printf("dis_av_permute(ppc)(instr)\n");
9775       return False;
9776    }
9777
9778    switch (opc2) {
9779    case 0x2A: // vsel (Conditional Select, AV p238)
9780       DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
9781       /* vD = (vA & ~vC) | (vB & vC) */
9782       putVReg( vD_addr, binop(Iop_OrV128,
9783          binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
9784          binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
9785       return True;
9786      
9787    case 0x2B: { // vperm (Permute, AV p218)
9788       /* limited to two args for IR, so have to play games... */
9789       IRTemp a_perm  = newTemp(Ity_V128);
9790       IRTemp b_perm  = newTemp(Ity_V128);
9791       IRTemp mask    = newTemp(Ity_V128);
9792       IRTemp vC_andF = newTemp(Ity_V128);
9793       DIP("vperm v%d,v%d,v%d,v%d\n",
9794           vD_addr, vA_addr, vB_addr, vC_addr);
9795       /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
9796          IR specifies, and also to hide irrelevant bits from
9797          memcheck */
9798       assign( vC_andF,
9799               binop(Iop_AndV128, mkexpr(vC),
9800                                  unop(Iop_Dup8x16, mkU8(0xF))) );
9801       assign( a_perm,
9802               binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
9803       assign( b_perm,
9804               binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
9805       // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
9806       assign( mask, binop(Iop_SarN8x16,
9807                           binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
9808                           mkU8(7)) );
9809       // dst = (a & ~mask) | (b & mask)
9810       putVReg( vD_addr, binop(Iop_OrV128,
9811                               binop(Iop_AndV128, mkexpr(a_perm),
9812                                     unop(Iop_NotV128, mkexpr(mask))),
9813                               binop(Iop_AndV128, mkexpr(b_perm),
9814                                     mkexpr(mask))) );
9815       return True;
9816    }
9817    case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
9818       if (b10 != 0) {
9819          vex_printf("dis_av_permute(ppc)(vsldoi)\n");
9820          return False;
9821       }
9822       DIP("vsldoi v%d,v%d,v%d,%d\n",
9823           vD_addr, vA_addr, vB_addr, SHB_uimm4);
9824       if (SHB_uimm4 == 0)
9825          putVReg( vD_addr, mkexpr(vA) );
9826       else
9827          putVReg( vD_addr,
9828             binop(Iop_OrV128,
9829                   binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
9830                   binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
9831       return True;
9832
9833    default:
9834      break; // Fall through...
9835    }
9836
9837    opc2 = IFIELD( theInstr, 0, 11 );
9838    switch (opc2) {
9839
9840    /* Merge */
9841    case 0x00C: // vmrghb (Merge High B, AV p195)
9842       DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9843       putVReg( vD_addr,
9844                binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
9845       break;
9846
9847    case 0x04C: // vmrghh (Merge High HW, AV p196)
9848       DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9849       putVReg( vD_addr,
9850                binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
9851       break;
9852
9853    case 0x08C: // vmrghw (Merge High W, AV p197)
9854       DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9855       putVReg( vD_addr,
9856                binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
9857       break;
9858
9859    case 0x10C: // vmrglb (Merge Low B, AV p198)
9860       DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9861       putVReg( vD_addr,
9862                binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
9863       break;
9864
9865    case 0x14C: // vmrglh (Merge Low HW, AV p199)
9866       DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9867       putVReg( vD_addr,
9868                binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
9869       break;
9870
9871    case 0x18C: // vmrglw (Merge Low W, AV p200)
9872       DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9873       putVReg( vD_addr,
9874                binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
9875       break;
9876
9877
9878    /* Splat */
9879    case 0x20C: { // vspltb (Splat Byte, AV p245)
9880       /* vD = Dup8x16( vB[UIMM_5] ) */
9881       UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
9882       DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
9883       putVReg( vD_addr, unop(Iop_Dup8x16,
9884            unop(Iop_32to8, unop(Iop_V128to32, 
9885                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
9886       break;
9887    }
9888    case 0x24C: { // vsplth (Splat Half Word, AV p246)
9889       UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
9890       DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
9891       putVReg( vD_addr, unop(Iop_Dup16x8,
9892            unop(Iop_32to16, unop(Iop_V128to32, 
9893                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
9894       break;
9895    }
9896    case 0x28C: { // vspltw (Splat Word, AV p250)
9897       /* vD = Dup32x4( vB[UIMM_5] ) */
9898       UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
9899       DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
9900       putVReg( vD_addr, unop(Iop_Dup32x4,
9901          unop(Iop_V128to32,
9902               binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
9903       break;
9904    }
9905    case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
9906       DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
9907       putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
9908       break;
9909
9910    case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
9911       DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
9912       putVReg( vD_addr,
9913                unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
9914       break;
9915
9916    case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
9917       DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
9918       putVReg( vD_addr,
9919                unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
9920       break;
9921
9922    default:
9923       vex_printf("dis_av_permute(ppc)(opc2)\n");
9924       return False;
9925    }
9926    return True;
9927 }
9928
9929 /*
9930   AltiVec Pack/Unpack Instructions
9931 */
9932 static Bool dis_av_pack ( UInt theInstr )
9933 {
9934    /* VX-Form */
9935    UChar opc1     = ifieldOPC(theInstr);
9936    UChar vD_addr  = ifieldRegDS(theInstr);
9937    UChar vA_addr  = ifieldRegA(theInstr);
9938    UChar vB_addr  = ifieldRegB(theInstr);
9939    UInt  opc2     = IFIELD( theInstr, 0, 11 );
9940
9941    IRTemp signs = IRTemp_INVALID;
9942    IRTemp zeros = IRTemp_INVALID;
9943    IRTemp vA    = newTemp(Ity_V128);
9944    IRTemp vB    = newTemp(Ity_V128);
9945    assign( vA, getVReg(vA_addr));
9946    assign( vB, getVReg(vB_addr));
9947
9948    if (opc1 != 0x4) {
9949       vex_printf("dis_av_pack(ppc)(instr)\n");
9950       return False;
9951    }
9952
9953    switch (opc2) {
9954    /* Packing */
9955    case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
9956       DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9957       putVReg( vD_addr, binop(Iop_Narrow16x8, mkexpr(vA), mkexpr(vB)) );
9958       return True;
9959
9960    case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
9961       DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9962       putVReg( vD_addr, binop(Iop_Narrow32x4, mkexpr(vA), mkexpr(vB)) );
9963       return True;
9964
9965    case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
9966       DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9967       putVReg( vD_addr,
9968                binop(Iop_QNarrow16Ux8, mkexpr(vA), mkexpr(vB)) );
9969       // TODO: set VSCR[SAT]
9970       return True;
9971
9972    case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
9973       DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9974       putVReg( vD_addr,
9975                binop(Iop_QNarrow32Ux4, mkexpr(vA), mkexpr(vB)) );
9976       // TODO: set VSCR[SAT]
9977       return True;
9978
9979    case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
9980       // This insn does a signed->unsigned saturating conversion.
9981       // Conversion done here, then uses unsigned->unsigned vpk insn:
9982       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
9983       IRTemp vA_tmp = newTemp(Ity_V128);
9984       IRTemp vB_tmp = newTemp(Ity_V128);
9985       DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9986       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
9987                             unop(Iop_NotV128,
9988                                  binop(Iop_SarN16x8,
9989                                        mkexpr(vA), mkU8(15)))) );
9990       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
9991                             unop(Iop_NotV128,
9992                                  binop(Iop_SarN16x8,
9993                                        mkexpr(vB), mkU8(15)))) );
9994       putVReg( vD_addr, binop(Iop_QNarrow16Ux8,
9995                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
9996       // TODO: set VSCR[SAT]
9997       return True;
9998    }
9999    case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
10000       // This insn does a signed->unsigned saturating conversion.
10001       // Conversion done here, then uses unsigned->unsigned vpk insn:
10002       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
10003       IRTemp vA_tmp = newTemp(Ity_V128);
10004       IRTemp vB_tmp = newTemp(Ity_V128);
10005       DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10006       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
10007                             unop(Iop_NotV128,
10008                                  binop(Iop_SarN32x4,
10009                                        mkexpr(vA), mkU8(31)))) );
10010       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
10011                             unop(Iop_NotV128,
10012                                  binop(Iop_SarN32x4,
10013                                        mkexpr(vB), mkU8(31)))) );
10014       putVReg( vD_addr, binop(Iop_QNarrow32Ux4,
10015                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
10016       // TODO: set VSCR[SAT]
10017       return True;
10018    }
10019    case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
10020       DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10021       putVReg( vD_addr,
10022                binop(Iop_QNarrow16Sx8, mkexpr(vA), mkexpr(vB)) );
10023       // TODO: set VSCR[SAT]
10024       return True;
10025
10026    case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
10027       DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10028       putVReg( vD_addr,
10029                binop(Iop_QNarrow32Sx4, mkexpr(vA), mkexpr(vB)) );
10030       // TODO: set VSCR[SAT]
10031       return True;
10032
10033    case 0x30E: { // vpkpx (Pack Pixel, AV p219)
10034       /* CAB: Worth a new primop? */
10035       /* Using shifts to compact pixel elements, then packing them */
10036       IRTemp a1 = newTemp(Ity_V128);
10037       IRTemp a2 = newTemp(Ity_V128);
10038       IRTemp a3 = newTemp(Ity_V128);
10039       IRTemp a_tmp = newTemp(Ity_V128);
10040       IRTemp b1 = newTemp(Ity_V128);
10041       IRTemp b2 = newTemp(Ity_V128);
10042       IRTemp b3 = newTemp(Ity_V128);
10043       IRTemp b_tmp = newTemp(Ity_V128);
10044       DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10045       assign( a1, binop(Iop_ShlN16x8,
10046                         binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
10047                         mkU8(10)) );
10048       assign( a2, binop(Iop_ShlN16x8, 
10049                         binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
10050                         mkU8(5)) );
10051       assign( a3,  binop(Iop_ShrN16x8, 
10052                          binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
10053                          mkU8(11)) );
10054       assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
10055                            binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
10056
10057       assign( b1, binop(Iop_ShlN16x8,
10058                         binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
10059                         mkU8(10)) );
10060       assign( b2, binop(Iop_ShlN16x8, 
10061                         binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
10062                         mkU8(5)) );
10063       assign( b3,  binop(Iop_ShrN16x8, 
10064                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
10065                          mkU8(11)) );
10066       assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
10067                            binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
10068
10069       putVReg( vD_addr, binop(Iop_Narrow32x4,
10070                               mkexpr(a_tmp), mkexpr(b_tmp)) );
10071       return True;
10072    }
10073
10074    default:
10075       break; // Fall through...
10076    }
10077
10078
10079    if (vA_addr != 0) {
10080       vex_printf("dis_av_pack(ppc)(vA_addr)\n");
10081       return False;
10082    }
10083
10084    signs = newTemp(Ity_V128);
10085    zeros = newTemp(Ity_V128);
10086    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
10087
10088    switch (opc2) {
10089    /* Unpacking */
10090    case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
10091       DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
10092       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
10093       putVReg( vD_addr,
10094                binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
10095       break;
10096    }
10097    case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
10098       DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
10099       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
10100       putVReg( vD_addr,
10101                binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
10102       break;
10103    }
10104    case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
10105       DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
10106       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
10107       putVReg( vD_addr,
10108                binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
10109       break;
10110    }
10111    case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
10112       DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
10113       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
10114       putVReg( vD_addr,
10115                binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
10116       break;
10117    }
10118    case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
10119       /* CAB: Worth a new primop? */
10120       /* Using shifts to isolate pixel elements, then expanding them */
10121       IRTemp z0  = newTemp(Ity_V128);
10122       IRTemp z1  = newTemp(Ity_V128);
10123       IRTemp z01 = newTemp(Ity_V128);
10124       IRTemp z2  = newTemp(Ity_V128);
10125       IRTemp z3  = newTemp(Ity_V128);
10126       IRTemp z23 = newTemp(Ity_V128);
10127       DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
10128       assign( z0,  binop(Iop_ShlN16x8,
10129                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
10130                          mkU8(8)) );
10131       assign( z1,  binop(Iop_ShrN16x8, 
10132                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
10133                          mkU8(11)) );
10134       assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
10135                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
10136       assign( z2,  binop(Iop_ShrN16x8,
10137                          binop(Iop_ShlN16x8, 
10138                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
10139                                mkU8(11)),
10140                          mkU8(3)) );
10141       assign( z3,  binop(Iop_ShrN16x8, 
10142                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
10143                          mkU8(11)) );
10144       assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
10145                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
10146       putVReg( vD_addr,
10147                binop(Iop_OrV128,
10148                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
10149                      mkexpr(z23)) );
10150       break;
10151    }
10152    case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
10153       /* identical to vupkhpx, except interleaving LO */
10154       IRTemp z0  = newTemp(Ity_V128);
10155       IRTemp z1  = newTemp(Ity_V128);
10156       IRTemp z01 = newTemp(Ity_V128);
10157       IRTemp z2  = newTemp(Ity_V128);
10158       IRTemp z3  = newTemp(Ity_V128);
10159       IRTemp z23 = newTemp(Ity_V128);
10160       DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
10161       assign( z0,  binop(Iop_ShlN16x8,
10162                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
10163                          mkU8(8)) );
10164       assign( z1,  binop(Iop_ShrN16x8, 
10165                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
10166                          mkU8(11)) );
10167       assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
10168                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
10169       assign( z2,  binop(Iop_ShrN16x8,
10170                          binop(Iop_ShlN16x8, 
10171                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
10172                                mkU8(11)),
10173                          mkU8(3)) );
10174       assign( z3,  binop(Iop_ShrN16x8, 
10175                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
10176                          mkU8(11)) );
10177       assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
10178                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
10179       putVReg( vD_addr,
10180                binop(Iop_OrV128,
10181                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
10182                      mkexpr(z23)) );
10183       break;
10184    }
10185    default:
10186       vex_printf("dis_av_pack(ppc)(opc2)\n");
10187       return False;
10188    }
10189    return True;
10190 }
10191
10192
10193 /*
10194   AltiVec Floating Point Arithmetic Instructions
10195 */
10196 static Bool dis_av_fp_arith ( UInt theInstr )
10197 {
10198    /* VA-Form */
10199    UChar opc1     = ifieldOPC(theInstr);
10200    UChar vD_addr  = ifieldRegDS(theInstr);
10201    UChar vA_addr  = ifieldRegA(theInstr);
10202    UChar vB_addr  = ifieldRegB(theInstr);
10203    UChar vC_addr  = ifieldRegC(theInstr);
10204    UInt  opc2=0;
10205
10206    IRTemp vA = newTemp(Ity_V128);
10207    IRTemp vB = newTemp(Ity_V128);
10208    IRTemp vC = newTemp(Ity_V128);
10209    assign( vA, getVReg(vA_addr));
10210    assign( vB, getVReg(vB_addr));
10211    assign( vC, getVReg(vC_addr));
10212
10213    if (opc1 != 0x4) {
10214       vex_printf("dis_av_fp_arith(ppc)(instr)\n");
10215       return False;
10216    }
10217
10218    opc2 = IFIELD( theInstr, 0, 6 );
10219    switch (opc2) {
10220    case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
10221       DIP("vmaddfp v%d,v%d,v%d,v%d\n",
10222           vD_addr, vA_addr, vC_addr, vB_addr);
10223       putVReg( vD_addr,
10224                binop(Iop_Add32Fx4, mkexpr(vB),
10225                      binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
10226       return True;
10227
10228    case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
10229       DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
10230           vD_addr, vA_addr, vC_addr, vB_addr);
10231       putVReg( vD_addr,
10232                binop(Iop_Sub32Fx4,
10233                      mkexpr(vB),
10234                      binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
10235       return True;
10236    }
10237
10238    default:
10239      break; // Fall through...
10240    }
10241
10242    opc2 = IFIELD( theInstr, 0, 11 );
10243    switch (opc2) {
10244    case 0x00A: // vaddfp (Add FP, AV p137)
10245       DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10246       putVReg( vD_addr, binop(Iop_Add32Fx4, mkexpr(vA), mkexpr(vB)) );
10247       return True;
10248
10249   case 0x04A: // vsubfp (Subtract FP, AV p261)
10250       DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10251       putVReg( vD_addr, binop(Iop_Sub32Fx4, mkexpr(vA), mkexpr(vB)) );
10252       return True;
10253
10254    case 0x40A: // vmaxfp (Maximum FP, AV p178)
10255       DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10256       putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
10257       return True;
10258
10259    case 0x44A: // vminfp (Minimum FP, AV p187)
10260       DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10261       putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
10262       return True;
10263
10264    default:
10265       break; // Fall through...
10266    }
10267
10268
10269    if (vA_addr != 0) {
10270       vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
10271       return False;
10272    }
10273
10274    switch (opc2) {
10275    case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
10276       DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
10277       putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) );
10278       return True;
10279
10280    case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
10281       DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
10282       putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) );
10283       return True;
10284
10285    case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
10286       DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
10287       DIP(" => not implemented\n");
10288       return False;
10289
10290    case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
10291       DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
10292       DIP(" => not implemented\n");
10293       return False;
10294
10295    default:
10296       vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
10297       return False;
10298    }
10299    return True;
10300 }
10301
10302 /*
10303   AltiVec Floating Point Compare Instructions
10304 */
10305 static Bool dis_av_fp_cmp ( UInt theInstr )
10306 {
10307    /* VXR-Form */
10308    UChar opc1     = ifieldOPC(theInstr);
10309    UChar vD_addr  = ifieldRegDS(theInstr);
10310    UChar vA_addr  = ifieldRegA(theInstr);
10311    UChar vB_addr  = ifieldRegB(theInstr);
10312    UChar flag_rC  = ifieldBIT10(theInstr);
10313    UInt  opc2     = IFIELD( theInstr, 0, 10 );
10314
10315    Bool cmp_bounds = False;
10316
10317    IRTemp vA = newTemp(Ity_V128);
10318    IRTemp vB = newTemp(Ity_V128);
10319    IRTemp vD = newTemp(Ity_V128);
10320    assign( vA, getVReg(vA_addr));
10321    assign( vB, getVReg(vB_addr));
10322
10323    if (opc1 != 0x4) {
10324       vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
10325       return False;
10326    }
10327
10328    switch (opc2) {
10329    case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
10330       DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
10331                                       vD_addr, vA_addr, vB_addr);
10332       assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
10333       break;
10334
10335    case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
10336       DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
10337                                       vD_addr, vA_addr, vB_addr);
10338       assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
10339       break;
10340
10341    case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
10342       DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
10343                                       vD_addr, vA_addr, vB_addr);
10344       assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
10345       break;
10346
10347    case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
10348       IRTemp gt      = newTemp(Ity_V128);
10349       IRTemp lt      = newTemp(Ity_V128);
10350       IRTemp zeros   = newTemp(Ity_V128);
10351       DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
10352                                      vD_addr, vA_addr, vB_addr);
10353       cmp_bounds = True;
10354       assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
10355
10356       /* Note: making use of fact that the ppc backend for compare insns
10357          return zero'd lanes if either of the corresponding arg lanes is
10358          a nan.
10359
10360          Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
10361          need this for the other compares too (vcmpeqfp etc)...
10362          Better still, tighten down the spec for compare irops.
10363        */
10364       assign( gt, unop(Iop_NotV128,
10365                        binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
10366       assign( lt, unop(Iop_NotV128,
10367                        binop(Iop_CmpGE32Fx4, mkexpr(vA),
10368                              binop(Iop_Sub32Fx4, mkexpr(zeros),
10369                                                  mkexpr(vB)))) );
10370
10371       // finally, just shift gt,lt to correct position
10372       assign( vD, binop(Iop_ShlN32x4,
10373                         binop(Iop_OrV128,
10374                               binop(Iop_AndV128, mkexpr(gt),
10375                                     unop(Iop_Dup32x4, mkU32(0x2))),
10376                               binop(Iop_AndV128, mkexpr(lt),
10377                                     unop(Iop_Dup32x4, mkU32(0x1)))),
10378                         mkU8(30)) );
10379       break;
10380    }
10381
10382    default:
10383       vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
10384       return False;
10385    }
10386
10387    putVReg( vD_addr, mkexpr(vD) );
10388
10389    if (flag_rC) {
10390       set_AV_CR6( mkexpr(vD), !cmp_bounds );
10391    }
10392    return True;
10393 }
10394
10395 /*
10396   AltiVec Floating Point Convert/Round Instructions
10397 */
10398 static Bool dis_av_fp_convert ( UInt theInstr )
10399 {
10400    /* VX-Form */
10401    UChar opc1     = ifieldOPC(theInstr);
10402    UChar vD_addr  = ifieldRegDS(theInstr);
10403    UChar UIMM_5   = ifieldRegA(theInstr);
10404    UChar vB_addr  = ifieldRegB(theInstr);
10405    UInt  opc2     = IFIELD( theInstr, 0, 11 );
10406
10407    IRTemp vB        = newTemp(Ity_V128);
10408    IRTemp vScale    = newTemp(Ity_V128);
10409    IRTemp vInvScale = newTemp(Ity_V128);
10410
10411    float scale, inv_scale;
10412
10413    assign( vB, getVReg(vB_addr));
10414
10415    /* scale = 2^UIMM, cast to float, reinterpreted as uint */
10416    scale = (float)( (unsigned int) 1<<UIMM_5 );
10417    assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
10418    inv_scale = 1/scale;
10419    assign( vInvScale,
10420            unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
10421
10422    if (opc1 != 0x4) {
10423       vex_printf("dis_av_fp_convert(ppc)(instr)\n");
10424       return False;
10425    }
10426
10427    switch (opc2) {
10428    case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
10429       DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
10430       putVReg( vD_addr, binop(Iop_Mul32Fx4,
10431                               unop(Iop_I32UtoFx4, mkexpr(vB)),
10432                               mkexpr(vInvScale)) );
10433       return True;
10434
10435    case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
10436       DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
10437
10438       putVReg( vD_addr, binop(Iop_Mul32Fx4,
10439                               unop(Iop_I32StoFx4, mkexpr(vB)),
10440                               mkexpr(vInvScale)) );
10441       return True;
10442
10443    case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
10444       DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
10445       putVReg( vD_addr,
10446                unop(Iop_QFtoI32Ux4_RZ, 
10447                     binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
10448       return True;
10449
10450    case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
10451       DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
10452       putVReg( vD_addr, 
10453                unop(Iop_QFtoI32Sx4_RZ, 
10454                      binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
10455       return True;
10456
10457    default:
10458      break;    // Fall through...
10459    }
10460
10461    if (UIMM_5 != 0) {
10462       vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
10463       return False;
10464    }
10465
10466    switch (opc2) {
10467    case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
10468       DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
10469       putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
10470       break;
10471
10472    case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
10473       DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
10474       putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
10475       break;
10476
10477    case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
10478       DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
10479       putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
10480       break;
10481
10482    case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
10483       DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
10484       putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
10485       break;
10486
10487    default:
10488       vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
10489       return False;
10490    }
10491    return True;
10492 }
10493
10494
10495 /* The 0x3C primary opcode (VSX category) uses several different forms of
10496  * extended opcodes:
10497  *   o XX2-form:
10498  *      - [10:2] (IBM notation [21:29])
10499  *   o XX3-form variants:
10500  *       - variant 1: [10:3] (IBM notation [21:28])
10501  *       - variant 2: [9:3] (IBM notation [22:28])
10502  *       - variant 3: [7:3] (IBM notation [24:28])
10503  *   o XX-4 form:
10504  *      - [10:6] (IBM notation [21:25])
10505  *
10506  * The XX2-form needs bit 0 masked from the standard extended opcode
10507  * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
10508  * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
10509  * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
10510  * front end since their encoding does not begin at bit 21 like the standard
10511  * format.
10512  *
10513  * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
10514  * secondary opcode for such VSX instructions.
10515  *
10516 */
10517
10518
10519 struct vsx_insn {
10520    UInt opcode;
10521    Char * name;
10522 };
10523
10524 //  ATTENTION:  Keep this array sorted on the opcocde!!!
10525 static struct vsx_insn vsx_all[] = {
10526       { 0x8, "xxsldwi" },
10527       { 0x18, "xxsel" },
10528       { 0x28, "xxpermdi" },
10529       { 0x48, "xxmrghw" },
10530       { 0x80, "xsadddp" },
10531       { 0x84, "xsmaddadp" },
10532       { 0x8c, "xscmpudp" },
10533       { 0x90, "xscvdpuxws" },
10534       { 0x92, "xsrdpi" },
10535       { 0x94, "xsrsqrtedp" },
10536       { 0x96, "xssqrtdp" },
10537       { 0xa0, "xssubdp" },
10538       { 0xa4, "xsmaddmdp" },
10539       { 0xac, "xscmpodp" },
10540       { 0xb0, "xscvdpsxws" },
10541       { 0xb2, "xsrdpiz" },
10542       { 0xb4, "xsredp" },
10543       { 0xc0, "xsmuldp" },
10544       { 0xc4, "xsmsubadp" },
10545       { 0xc8, "xxmrglw" },
10546       { 0xd2, "xsrdpip" },
10547       { 0xd4, "xstsqrtdp" },
10548       { 0xd6, "xsrdpic" },
10549       { 0xe0, "xsdivdp" },
10550       { 0xe4, "xsmsubmdp" },
10551       { 0xf2, "xsrdpim" },
10552       { 0xf4, "xstdivdp" },
10553       { 0x100, "xvaddsp" },
10554       { 0x104, "xvmaddasp" },
10555       { 0x10c, "xvcmpeqsp" },
10556       { 0x110, "xvcvspuxws" },
10557       { 0x112, "xvrspi" },
10558       { 0x114, "xvrsqrtesp" },
10559       { 0x116, "xvsqrtsp" },
10560       { 0x120, "xvsubsp" },
10561       { 0x124, "xvmaddmsp" },
10562       { 0x12c, "xvcmpgtsp" },
10563       { 0x130, "xvcvspsxws" },
10564       { 0x132, "xvrspiz" },
10565       { 0x134, "xvresp" },
10566       { 0x140, "xvmulsp" },
10567       { 0x144, "xvmsubasp" },
10568       { 0x148, "xxspltw" },
10569       { 0x14c, "xvcmpgesp" },
10570       { 0x150, "xvcvuxwsp" },
10571       { 0x152, "xvrspip" },
10572       { 0x154, "xvtsqrtsp" },
10573       { 0x156, "xvrspic" },
10574       { 0x160, "xvdivsp" },
10575       { 0x164, "xvmsubmsp" },
10576       { 0x170, "xvcvsxwsp" },
10577       { 0x172, "xvrspim" },
10578       { 0x174, "xvtdivsp" },
10579       { 0x180, "xvadddp" },
10580       { 0x184, "xvmaddadp" },
10581       { 0x18c, "xvcmpeqdp" },
10582       { 0x190, "xvcvdpuxws" },
10583       { 0x192, "xvrdpi" },
10584       { 0x194, "xvrsqrtedp" },
10585       { 0x196, "xvsqrtdp" },
10586       { 0x1a0, "xvsubdp" },
10587       { 0x1a4, "xvmaddmdp" },
10588       { 0x1ac, "xvcmpgtdp" },
10589       { 0x1b0, "xvcvdpsxws" },
10590       { 0x1b2, "xvrdpiz" },
10591       { 0x1b4, "xvredp" },
10592       { 0x1c0, "xvmuldp" },
10593       { 0x1c4, "xvmsubadp" },
10594       { 0x1cc, "xvcmpgedp" },
10595       { 0x1d0, "xvcvuxwdp" },
10596       { 0x1d2, "xvrdpip" },
10597       { 0x1d4, "xvtsqrtdp" },
10598       { 0x1d6, "xvrdpic" },
10599       { 0x1e0, "xvdivdp" },
10600       { 0x1e4, "xvmsubmdp" },
10601       { 0x1f0, "xvcvsxwdp" },
10602       { 0x1f2, "xvrdpim" },
10603       { 0x1f4, "xvtdivdp" },
10604       { 0x208, "xxland" },
10605       { 0x212, "xscvdpsp" },
10606       { 0x228, "xxlandc" },
10607       { 0x248 , "xxlor" },
10608       { 0x268, "xxlxor" },
10609       { 0x280, "xsmaxdp" },
10610       { 0x284, "xsnmaddadp" },
10611       { 0x288, "xxlnor" },
10612       { 0x290, "xscvdpuxds" },
10613       { 0x292, "xscvspdp" },
10614       { 0x2a0, "xsmindp" },
10615       { 0x2a4, "xsnmaddmdp" },
10616       { 0x2b0, "xscvdpsxds" },
10617       { 0x2b2, "xsabsdp" },
10618       { 0x2c0, "xscpsgndp" },
10619       { 0x2c4, "xsnmsubadp" },
10620       { 0x2d0, "xscvuxddp" },
10621       { 0x2d2, "xsnabsdp" },
10622       { 0x2e4, "xsnmsubmdp" },
10623       { 0x2f0, "xscvsxddp" },
10624       { 0x2f2, "xsnegdp" },
10625       { 0x300, "xvmaxsp" },
10626       { 0x304, "xvnmaddasp" },
10627       { 0x30c, "xvcmpeqsp." },
10628       { 0x310, "xvcvspuxds" },
10629       { 0x312, "xvcvdpsp" },
10630       { 0x320, "xvminsp" },
10631       { 0x324, "xvnmaddmsp" },
10632       { 0x32c, "xvcmpgtsp." },
10633       { 0x330, "xvcvspsxds" },
10634       { 0x332, "xvabssp" },
10635       { 0x340, "xvcpsgnsp" },
10636       { 0x344, "xvnmsubasp" },
10637       { 0x34c, "xvcmpgesp." },
10638       { 0x350, "xvcvuxdsp" },
10639       { 0x352, "xvnabssp" },
10640       { 0x364, "xvnmsubmsp" },
10641       { 0x370, "xvcvsxdsp" },
10642       { 0x372, "xvnegsp" },
10643       { 0x380, "xvmaxdp" },
10644       { 0x384, "xvnmaddadp" },
10645       { 0x38c, "xvcmpeqdp." },
10646       { 0x390, "xvcvdpuxds" },
10647       { 0x392, "xvcvspdp" },
10648       { 0x3a0, "xvmindp" },
10649       { 0x3a4, "xvnmaddmdp" },
10650       { 0x3ac, "xvcmpgtdp." },
10651       { 0x3b0, "xvcvdpsxds" },
10652       { 0x3b2, "xvabsdp" },
10653       { 0x3c0, "xvcpsgndp" },
10654       { 0x3c4, "xvnmsubadp" },
10655       { 0x3cc, "xvcmpgedp." },
10656       { 0x3d0, "xvcvuxddp" },
10657       { 0x3d2, "xvnabsdp" },
10658       { 0x3e4, "xvnmsubmdp" },
10659       { 0x3f0, "xvcvsxddp" },
10660       { 0x3f2, "xvnegdp" }
10661 };
10662 #define VSX_ALL_LEN 135
10663
10664 // ATTENTION: This search function assumes vsx_all array is sorted.
10665 static Int findVSXextOpCode(UInt opcode)
10666 {
10667    Int low, mid, high;
10668    low = 0;
10669    high = VSX_ALL_LEN - 1;
10670    while (low <= high) {
10671       mid = (low + high)/2;
10672       if (opcode < vsx_all[mid].opcode)
10673          high = mid - 1;
10674       else if (opcode > vsx_all[mid].opcode)
10675          low = mid + 1;
10676       else
10677          return mid;
10678    }
10679    return -1;
10680 }
10681
10682
10683 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
10684  * passed, and we then try to match it up with one of the above
10685  * VSX forms.
10686  */
10687 static UInt get_VSX60_opc2(UInt opc2_full)
10688 {
10689 #define XX2_MASK 0x000003FE
10690 #define XX3_1_MASK 0x000003FC
10691 #define XX3_2_MASK 0x000001FC
10692 #define XX3_3_MASK 0x0000007C
10693 #define XX4_MASK 0x000003E0
10694    Int ret;
10695    UInt vsxExtOpcode = 0;
10696
10697    if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
10698       vsxExtOpcode = vsx_all[ret].opcode;
10699    else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
10700       vsxExtOpcode = vsx_all[ret].opcode;
10701    else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
10702       vsxExtOpcode = vsx_all[ret].opcode;
10703    else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
10704       vsxExtOpcode = vsx_all[ret].opcode;
10705    else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
10706       vsxExtOpcode = vsx_all[ret].opcode;
10707
10708    return vsxExtOpcode;
10709 }
10710
10711 /*------------------------------------------------------------*/
10712 /*--- Disassemble a single instruction                     ---*/
10713 /*------------------------------------------------------------*/
10714
10715 /* Disassemble a single instruction into IR.  The instruction
10716    is located in host memory at &guest_code[delta]. */
10717
10718 static   
10719 DisResult disInstr_PPC_WRK ( 
10720              Bool         put_IP,
10721              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
10722              Bool         resteerCisOk,
10723              void*        callback_opaque,
10724              Long         delta64,
10725              VexArchInfo* archinfo,
10726              VexAbiInfo*  abiinfo
10727           )
10728 {
10729    UChar     opc1;
10730    UInt      opc2;
10731    DisResult dres;
10732    UInt      theInstr;
10733    IRType    ty = mode64 ? Ity_I64 : Ity_I32;
10734    Bool      allow_F  = False;
10735    Bool      allow_V  = False;
10736    Bool      allow_FX = False;
10737    Bool      allow_GX = False;
10738    Bool      allow_VX = False;
10739    UInt      hwcaps = archinfo->hwcaps;
10740    Long      delta;
10741
10742    /* What insn variants are we supporting today? */
10743    if (mode64) {
10744       allow_F  = True;
10745       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
10746       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
10747       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
10748       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
10749    } else {
10750       allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
10751       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
10752       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
10753       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
10754       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
10755    }
10756
10757    /* The running delta */
10758    delta = (Long)mkSzAddr(ty, (ULong)delta64);
10759
10760    /* Set result defaults. */
10761    dres.whatNext   = Dis_Continue;
10762    dres.len        = 0;
10763    dres.continueAt = 0;
10764
10765    /* At least this is simple on PPC32: insns are all 4 bytes long, and
10766       4-aligned.  So just fish the whole thing out of memory right now
10767       and have done. */
10768    theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) );
10769
10770    if (0) vex_printf("insn: 0x%x\n", theInstr);
10771
10772    DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
10773
10774    /* We may be asked to update the guest CIA before going further. */
10775    if (put_IP)
10776       putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
10777
10778    /* Spot "Special" instructions (see comment at top of file). */
10779    {
10780       UChar* code = (UChar*)(guest_code + delta);
10781       /* Spot the 16-byte preamble: 
10782          32-bit mode:
10783             54001800  rlwinm 0,0,3,0,0
10784             54006800  rlwinm 0,0,13,0,0
10785             5400E800  rlwinm 0,0,29,0,0
10786             54009800  rlwinm 0,0,19,0,0
10787          64-bit mode:
10788             78001800  rotldi 0,0,3
10789             78006800  rotldi 0,0,13
10790             7800E802  rotldi 0,0,61
10791             78009802  rotldi 0,0,51
10792       */
10793       UInt word1 = mode64 ? 0x78001800 : 0x54001800;
10794       UInt word2 = mode64 ? 0x78006800 : 0x54006800;
10795       UInt word3 = mode64 ? 0x7800E802 : 0x5400E800;
10796       UInt word4 = mode64 ? 0x78009802 : 0x54009800;
10797       if (getUIntBigendianly(code+ 0) == word1 &&
10798           getUIntBigendianly(code+ 4) == word2 &&
10799           getUIntBigendianly(code+ 8) == word3 &&
10800           getUIntBigendianly(code+12) == word4) {
10801          /* Got a "Special" instruction preamble.  Which one is it? */
10802          if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
10803             /* %R3 = client_request ( %R4 ) */
10804             DIP("r3 = client_request ( %%r4 )\n");
10805             delta += 20;
10806             irsb->next     = mkSzImm( ty, guest_CIA_bbstart + delta );
10807             irsb->jumpkind = Ijk_ClientReq;
10808             dres.whatNext  = Dis_StopHere;
10809             goto decode_success;
10810          }
10811          else
10812          if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
10813             /* %R3 = guest_NRADDR */
10814             DIP("r3 = guest_NRADDR\n");
10815             delta += 20;
10816             dres.len = 20;
10817             putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
10818             goto decode_success;
10819          }
10820          else
10821          if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
10822             /*  branch-and-link-to-noredir %R11 */
10823             DIP("branch-and-link-to-noredir r11\n");
10824             delta += 20;
10825             putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
10826             irsb->next     = getIReg(11);
10827             irsb->jumpkind = Ijk_NoRedir;
10828             dres.whatNext  = Dis_StopHere;
10829             goto decode_success;
10830          }
10831          else
10832          if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
10833             /* %R3 = guest_NRADDR_GPR2 */
10834             DIP("r3 = guest_NRADDR_GPR2\n");
10835             delta += 20;
10836             dres.len = 20;
10837             putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
10838             goto decode_success;
10839          }
10840          /* We don't know what it is.  Set opc1/opc2 so decode_failure
10841             can print the insn following the Special-insn preamble. */
10842          theInstr = getUIntBigendianly(code+16);
10843          opc1     = ifieldOPC(theInstr);
10844          opc2     = ifieldOPClo10(theInstr);
10845          goto decode_failure;
10846          /*NOTREACHED*/
10847       }
10848    }
10849
10850    opc1 = ifieldOPC(theInstr);
10851    opc2 = ifieldOPClo10(theInstr);
10852
10853    // Note: all 'reserved' bits must be cleared, else invalid
10854    switch (opc1) {
10855
10856    /* Integer Arithmetic Instructions */
10857    case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
10858    case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
10859       if (dis_int_arith( theInstr )) goto decode_success;
10860       goto decode_failure;
10861
10862    /* Integer Compare Instructions */
10863    case 0x0B: case 0x0A: // cmpi, cmpli
10864       if (dis_int_cmp( theInstr )) goto decode_success;
10865       goto decode_failure;
10866
10867    /* Integer Logical Instructions */
10868    case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
10869    case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
10870       if (dis_int_logic( theInstr )) goto decode_success;
10871       goto decode_failure;
10872
10873    /* Integer Rotate Instructions */
10874    case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
10875       if (dis_int_rot( theInstr )) goto decode_success;
10876       goto decode_failure;
10877
10878    /* 64bit Integer Rotate Instructions */
10879    case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
10880       if (dis_int_rot( theInstr )) goto decode_success;
10881       goto decode_failure;
10882
10883    /* Integer Load Instructions */
10884    case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
10885    case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
10886    case 0x20: case 0x21:            // lwz,  lwzu
10887       if (dis_int_load( theInstr )) goto decode_success;
10888       goto decode_failure;
10889
10890    /* Integer Store Instructions */
10891    case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
10892    case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
10893       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
10894       goto decode_failure;
10895
10896    /* Integer Load and Store Multiple Instructions */
10897    case 0x2E: case 0x2F: // lmw, stmw
10898       if (dis_int_ldst_mult( theInstr )) goto decode_success;
10899       goto decode_failure;
10900
10901    /* Branch Instructions */
10902    case 0x12: case 0x10: // b, bc
10903       if (dis_branch(theInstr, abiinfo, &dres, 
10904                                resteerOkFn, callback_opaque)) 
10905          goto decode_success;
10906       goto decode_failure;
10907
10908    /* System Linkage Instructions */
10909    case 0x11: // sc
10910       if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
10911       goto decode_failure;
10912
10913    /* Trap Instructions */
10914    case 0x02: case 0x03: // tdi, twi
10915       if (dis_trapi(theInstr, &dres)) goto decode_success;
10916       goto decode_failure;
10917
10918    /* Floating Point Load Instructions */
10919    case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
10920    case 0x33:                       // lfdu
10921       if (!allow_F) goto decode_noF;
10922       if (dis_fp_load( theInstr )) goto decode_success;
10923       goto decode_failure;
10924
10925    /* Floating Point Store Instructions */
10926    case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
10927    case 0x37:                       // stfdux
10928       if (!allow_F) goto decode_noF;
10929       if (dis_fp_store( theInstr )) goto decode_success;
10930       goto decode_failure;
10931
10932       /* Floating Point Load Double Pair Instructions */
10933    case 0x39: case 0x3D:
10934       if (!allow_F) goto decode_noF;
10935       if (dis_fp_pair( theInstr )) goto decode_success;
10936       goto decode_failure;
10937
10938    /* 64bit Integer Loads */
10939    case 0x3A:  // ld, ldu, lwa
10940       if (!mode64) goto decode_failure;
10941       if (dis_int_load( theInstr )) goto decode_success;
10942       goto decode_failure;
10943
10944    case 0x3B:
10945       if (!allow_F) goto decode_noF;
10946       opc2 = ifieldOPClo10(theInstr);
10947       switch (opc2) {
10948          case 0x3CE: // fcfidus (implemented as native insn
10949             if (!allow_VX)
10950                goto decode_noVX;
10951             if (dis_fp_round( theInstr ))
10952                goto decode_success;
10953             goto decode_failure;
10954          case 0x34E: // fcfids
10955             if (dis_fp_round( theInstr ))
10956                goto decode_success;
10957             goto decode_failure;
10958       }
10959
10960       opc2 = IFIELD(theInstr, 1, 5);
10961       switch (opc2) {
10962       /* Floating Point Arith Instructions */
10963       case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
10964       case 0x19:                       // fmuls
10965          if (dis_fp_arith(theInstr)) goto decode_success;
10966          goto decode_failure;
10967       case 0x16:                       // fsqrts
10968          if (!allow_FX) goto decode_noFX;
10969          if (dis_fp_arith(theInstr)) goto decode_success;
10970          goto decode_failure;
10971       case 0x18:                       // fres
10972          if (!allow_GX) goto decode_noGX;
10973          if (dis_fp_arith(theInstr)) goto decode_success;
10974          goto decode_failure;
10975
10976       /* Floating Point Mult-Add Instructions */
10977       case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
10978       case 0x1F:                       // fnmadds
10979          if (dis_fp_multadd(theInstr)) goto decode_success;
10980          goto decode_failure;
10981
10982       case 0x1A:                       // frsqrtes
10983          if (!allow_GX) goto decode_noGX;
10984          if (dis_fp_arith(theInstr)) goto decode_success;
10985          goto decode_failure;
10986
10987       default:
10988          goto decode_failure;
10989       }
10990       break;
10991
10992    case 0x3C: // VSX instructions (except load/store)
10993    {
10994       UInt vsxOpc2 = get_VSX60_opc2(opc2);
10995       /* The vsxOpc2 returned is the "normalized" value, representing the
10996        * instructions secondary opcode as taken from the standard secondary
10997        * opcode field [21:30] (IBM notatition), even if the actual field
10998        * is non-standard.  These normalized values are given in the opcode
10999        * appendices of the ISA 2.06 document.
11000        */
11001       if (vsxOpc2 == 0)
11002          goto decode_failure;
11003
11004       switch (vsxOpc2) {
11005          case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
11006             if (dis_vx_permute(theInstr, vsxOpc2)) goto decode_success;
11007             goto decode_failure;
11008          case 0x268: case 0x248: case 0x288: case 0x208: case 0x228: // xxlxor, xxlor, xxlnor, xxland, xxlandc
11009             if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
11010             goto decode_failure;
11011          case 0x2B2: // xsabsdp
11012             if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
11013             goto decode_failure;
11014          case 0x2C0: // xscpsgndp
11015             if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
11016             goto decode_failure;
11017          case 0x2D2: // xsnabsdp
11018             if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
11019             goto decode_failure;
11020          case 0x2F2: // xsnegdp
11021             if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
11022             goto decode_failure;
11023          case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
11024             if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
11025             goto decode_failure;
11026          case 0x080: case 0x0E0: // xsadddp, xsdivdp
11027          case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
11028          case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
11029          case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
11030          case 0x0C0: // xsmuldp
11031          case 0x0A0: // xssubdp
11032             if (dis_vx_arith(theInstr, vsxOpc2)) goto decode_success;
11033             goto decode_failure;
11034          case 0x2B0: case 0x2F0: case 0x2D0: // xscvdpsxds, xscvsxddp, xscvuxddp
11035             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
11036             goto decode_failure;
11037
11038          default:
11039             goto decode_failure;
11040       }
11041       break;
11042    }
11043
11044    /* 64bit Integer Stores */
11045    case 0x3E:  // std, stdu
11046       if (!mode64) goto decode_failure;
11047       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
11048       goto decode_failure;
11049
11050    case 0x3F:
11051       if (!allow_F) goto decode_noF;
11052       /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
11053          so we can simply fall through the first switch statement */
11054
11055       opc2 = IFIELD(theInstr, 1, 5);
11056       switch (opc2) {
11057       /* Floating Point Arith Instructions */
11058       case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
11059       case 0x19:                       // fmul
11060          if (dis_fp_arith(theInstr)) goto decode_success;
11061          goto decode_failure;
11062       case 0x16:                       // fsqrt
11063          if (!allow_FX) goto decode_noFX;
11064          if (dis_fp_arith(theInstr)) goto decode_success;
11065          goto decode_failure;
11066       case 0x17: case 0x1A:            // fsel, frsqrte
11067          if (!allow_GX) goto decode_noGX;
11068          if (dis_fp_arith(theInstr)) goto decode_success;
11069          goto decode_failure;
11070          
11071       /* Floating Point Mult-Add Instructions */         
11072       case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
11073       case 0x1F:                       // fnmadd
11074          if (dis_fp_multadd(theInstr)) goto decode_success;
11075          goto decode_failure;
11076
11077       case 0x18:                       // fre
11078          if (!allow_GX) goto decode_noGX;
11079          if (dis_fp_arith(theInstr)) goto decode_success;
11080          goto decode_failure;
11081          
11082       default:
11083          break; // Fall through
11084       }
11085
11086       opc2 = IFIELD(theInstr, 1, 10);
11087       switch (opc2) {
11088       /* Floating Point Compare Instructions */         
11089       case 0x000: // fcmpu
11090       case 0x020: // fcmpo
11091          if (dis_fp_cmp(theInstr)) goto decode_success;
11092          goto decode_failure;
11093          
11094       case 0x080: // ftdiv
11095          if (dis_fp_ftdiv(theInstr)) goto decode_success;
11096          goto decode_failure;
11097
11098       /* Floating Point Rounding/Conversion Instructions */         
11099       case 0x00C: // frsp
11100       case 0x00E: // fctiw
11101       case 0x00F: // fctiwz
11102       case 0x32E: // fctid
11103       case 0x32F: // fctidz
11104       case 0x34E: // fcfid
11105          if (dis_fp_round(theInstr)) goto decode_success;
11106          goto decode_failure;
11107       case 0x3CE: // fcfidu (implemented as native insn)
11108          if (!allow_VX) goto decode_noVX;
11109          if (dis_fp_round(theInstr)) goto decode_success;
11110          goto decode_failure;
11111
11112
11113       /* Power6 rounding stuff */
11114       case 0x1E8: // frim
11115       case 0x1C8: // frip
11116       case 0x188: // frin
11117       case 0x1A8: // friz
11118          /* A hack to check for P6 capability . . . */
11119          if ((allow_F && allow_V && allow_FX && allow_GX) &&
11120              (dis_fp_round(theInstr)))
11121             goto decode_success;
11122          goto decode_failure;
11123          
11124       /* Floating Point Move Instructions */         
11125       case 0x008: // fcpsgn
11126       case 0x028: // fneg
11127       case 0x048: // fmr
11128       case 0x088: // fnabs
11129       case 0x108: // fabs
11130          if (dis_fp_move( theInstr )) goto decode_success;
11131          goto decode_failure;
11132
11133       /* Floating Point Status/Control Register Instructions */         
11134       case 0x026: // mtfsb1
11135       case 0x040: // mcrfs
11136       case 0x046: // mtfsb0
11137       case 0x086: // mtfsfi
11138       case 0x247: // mffs
11139       case 0x2C7: // mtfsf
11140          if (dis_fp_scr( theInstr )) goto decode_success;
11141          goto decode_failure;
11142
11143       default:
11144          goto decode_failure;
11145       }
11146       break;
11147       
11148    case 0x13:
11149       switch (opc2) {
11150
11151       /* Condition Register Logical Instructions */
11152       case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
11153       case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
11154       case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
11155          if (dis_cond_logic( theInstr )) goto decode_success;
11156          goto decode_failure;
11157          
11158       /* Branch Instructions */
11159       case 0x210: case 0x010: // bcctr, bclr
11160          if (dis_branch(theInstr, abiinfo, &dres, 
11161                                   resteerOkFn, callback_opaque)) 
11162             goto decode_success;
11163          goto decode_failure;
11164          
11165       /* Memory Synchronization Instructions */
11166       case 0x096: // isync
11167          if (dis_memsync( theInstr )) goto decode_success;
11168          goto decode_failure;
11169          
11170       default:
11171          goto decode_failure;
11172       }
11173       break;
11174
11175
11176    case 0x1F:
11177
11178       /* For arith instns, bit10 is the OE flag (overflow enable) */
11179
11180       opc2 = IFIELD(theInstr, 1, 9);
11181       switch (opc2) {
11182       /* Integer Arithmetic Instructions */
11183       case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
11184       case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
11185       case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
11186       case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
11187       case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
11188       case 0x0C8:                         // subfze
11189          if (dis_int_arith( theInstr )) goto decode_success;
11190          goto decode_failure;
11191
11192       /* 64bit Integer Arithmetic */
11193       case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
11194       case 0x1C9: case 0x1E9:             // divdu, divd
11195          if (!mode64) goto decode_failure;
11196          if (dis_int_arith( theInstr )) goto decode_success;
11197          goto decode_failure;
11198
11199       case 0x1FC:                         // cmpb
11200          if (dis_int_logic( theInstr )) goto decode_success;
11201          goto decode_failure;
11202
11203       default:
11204          break;  // Fall through...
11205       }
11206
11207       /* All remaining opcodes use full 10 bits. */
11208
11209       opc2 = IFIELD(theInstr, 1, 10);
11210       switch (opc2) {
11211       /* Integer Compare Instructions  */
11212       case 0x000: case 0x020: // cmp, cmpl
11213          if (dis_int_cmp( theInstr )) goto decode_success;
11214          goto decode_failure;
11215
11216       /* Integer Logical Instructions */
11217       case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
11218       case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
11219       case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
11220       case 0x19C: case 0x13C:             // orc,  xor
11221       case 0x2DF: case 0x25F:            // mftgpr, mffgpr
11222          if (dis_int_logic( theInstr )) goto decode_success;
11223          goto decode_failure;
11224
11225       /* 64bit Integer Logical Instructions */
11226       case 0x3DA: case 0x03A: // extsw, cntlzd
11227          if (!mode64) goto decode_failure;
11228          if (dis_int_logic( theInstr )) goto decode_success;
11229          goto decode_failure;
11230
11231          /* 64bit Integer Parity Instructions */
11232       case 0xba: case 0x9a: // prtyd, prtyw
11233          if (dis_int_parity( theInstr )) goto decode_success;
11234          goto decode_failure;
11235
11236       /* Integer Shift Instructions */
11237       case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
11238       case 0x218:                         // srw
11239          if (dis_int_shift( theInstr )) goto decode_success;
11240          goto decode_failure;
11241
11242       /* 64bit Integer Shift Instructions */
11243       case 0x01B: case 0x31A: // sld, srad
11244       case 0x33A: case 0x33B: // sradi
11245       case 0x21B:             // srd
11246          if (!mode64) goto decode_failure;
11247          if (dis_int_shift( theInstr )) goto decode_success;
11248          goto decode_failure;
11249
11250       /* Integer Load Instructions */
11251       case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
11252       case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
11253       case 0x017: case 0x037:             // lwzx,  lwzux
11254          if (dis_int_load( theInstr )) goto decode_success;
11255          goto decode_failure;
11256
11257       /* 64bit Integer Load Instructions */
11258       case 0x035: case 0x015:             // ldux,  ldx
11259       case 0x175: case 0x155:             // lwaux, lwax
11260          if (!mode64) goto decode_failure;
11261          if (dis_int_load( theInstr )) goto decode_success;
11262          goto decode_failure;
11263
11264       /* Integer Store Instructions */
11265       case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
11266       case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
11267          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
11268          goto decode_failure;
11269
11270       /* 64bit Integer Store Instructions */
11271       case 0x0B5: case 0x095: // stdux, stdx
11272          if (!mode64) goto decode_failure;
11273          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
11274          goto decode_failure;
11275
11276       /* Integer Load and Store with Byte Reverse Instructions */
11277       case 0x316: case 0x216: case 0x396: // lhbrx, lwbrx, sthbrx
11278       case 0x296: case 0x214:             // stwbrx, ldbrx
11279          if (dis_int_ldst_rev( theInstr )) goto decode_success;
11280          goto decode_failure;
11281          
11282       /* Integer Load and Store String Instructions */
11283       case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
11284       case 0x295: {                       // stswx
11285          Bool stopHere = False;
11286          Bool ok = dis_int_ldst_str( theInstr, &stopHere );
11287          if (!ok) goto decode_failure;
11288          if (stopHere) {
11289             irsb->next     = mkSzImm(ty, nextInsnAddr());
11290             irsb->jumpkind = Ijk_Boring;
11291             dres.whatNext  = Dis_StopHere;
11292          }
11293          goto decode_success;
11294       }
11295
11296       /* Memory Synchronization Instructions */
11297       case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
11298       case 0x256:                         // sync
11299          if (dis_memsync( theInstr )) goto decode_success;
11300          goto decode_failure;
11301          
11302       /* 64bit Memory Synchronization Instructions */
11303       case 0x054: case 0x0D6: // ldarx, stdcx.
11304          if (!mode64) goto decode_failure;
11305          if (dis_memsync( theInstr )) goto decode_success;
11306          goto decode_failure;
11307
11308       /* Processor Control Instructions */
11309       case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
11310       case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
11311          if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
11312          goto decode_failure;
11313
11314       /* Cache Management Instructions */
11315       case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
11316       case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
11317       case 0x3D6:                         // icbi
11318          if (dis_cache_manage( theInstr, &dres, archinfo )) 
11319             goto decode_success;
11320          goto decode_failure;
11321
11322 //zz       /* External Control Instructions */
11323 //zz       case 0x136: case 0x1B6: // eciwx, ecowx
11324 //zz          DIP("external control op => not implemented\n");
11325 //zz          goto decode_failure;
11326
11327       /* Trap Instructions */
11328       case 0x004: case 0x044:             // tw,   td
11329          if (dis_trap(theInstr, &dres)) goto decode_success;
11330          goto decode_failure;
11331
11332       /* Floating Point Load Instructions */
11333       case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
11334       case 0x277:                         // lfdux
11335          if (!allow_F) goto decode_noF;
11336          if (dis_fp_load( theInstr )) goto decode_success;
11337          goto decode_failure;
11338
11339       /* Floating Point Store Instructions */
11340       case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
11341       case 0x2F7:                         // stfdu, stfiwx
11342          if (!allow_F) goto decode_noF;
11343          if (dis_fp_store( theInstr )) goto decode_success;
11344          goto decode_failure;
11345       case 0x3D7:                         // stfiwx
11346          if (!allow_F) goto decode_noF;
11347          if (!allow_GX) goto decode_noGX;
11348          if (dis_fp_store( theInstr )) goto decode_success;
11349          goto decode_failure;
11350
11351          /* Floating Point Double Pair Indexed Instructions */
11352       case 0x317: // lfdpx (Power6)
11353       case 0x397: // stfdpx (Power6)
11354          if (!allow_F) goto decode_noF;
11355          if (dis_fp_pair(theInstr)) goto decode_success;
11356          goto decode_failure;
11357
11358       case 0x357:                         // lfiwax
11359          if (!allow_F) goto decode_noF;
11360          if (dis_fp_load( theInstr )) goto decode_success;
11361          goto decode_failure;
11362
11363       case 0x377:                         // lfiwzx
11364          if (!allow_F) goto decode_noF;
11365          if (dis_fp_load( theInstr )) goto decode_success;
11366          goto decode_failure;
11367
11368       /* AltiVec instructions */
11369
11370       /* AV Cache Control - Data streams */
11371       case 0x156: case 0x176: case 0x336: // dst, dstst, dss
11372          if (!allow_V) goto decode_noV;
11373          if (dis_av_datastream( theInstr )) goto decode_success;
11374          goto decode_failure;
11375
11376       /* AV Load */
11377       case 0x006: case 0x026:             // lvsl, lvsr
11378       case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
11379       case 0x067: case 0x167:             // lvx, lvxl
11380          if (!allow_V) goto decode_noV;
11381          if (dis_av_load( abiinfo, theInstr )) goto decode_success;
11382          goto decode_failure;
11383
11384       /* AV Store */
11385       case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
11386       case 0x0E7: case 0x1E7:             // stvx, stvxl
11387          if (!allow_V) goto decode_noV;
11388          if (dis_av_store( theInstr )) goto decode_success;
11389          goto decode_failure;
11390
11391       /* VSX Load */
11392       case 0x24C: // lxsdx
11393       case 0x34C: // lxvd2x
11394       case 0x14C: // lxvdsx
11395       case 0x30C: // lxvw4x
11396           if (dis_vx_load( theInstr )) goto decode_success;
11397           goto decode_failure;
11398
11399       /* VSX Store */
11400       case 0x2CC: // stxsdx
11401       case 0x3CC: // stxvd2x
11402       case 0x38C: // stxvw4x
11403           if (dis_vx_store( theInstr )) goto decode_success;
11404           goto decode_failure;
11405
11406       /* Miscellaneous ISA 2.06 instructions */
11407       case 0x1FA: // popcntd
11408           if (dis_int_logic( theInstr )) goto decode_success;
11409           goto decode_failure;
11410
11411       default:
11412          /* Deal with some other cases that we would otherwise have
11413             punted on. */
11414          /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
11415          /* only decode this insn when reserved bit 0 (31 in IBM's
11416             notation) is zero */
11417          if (IFIELD(theInstr, 0, 6) == (15<<1)) {
11418             UInt rT = ifieldRegDS( theInstr );
11419             UInt rA = ifieldRegA( theInstr );
11420             UInt rB = ifieldRegB( theInstr );
11421             UInt bi = ifieldRegC( theInstr );
11422             putIReg(
11423                rT,
11424                IRExpr_Mux0X( unop(Iop_32to8,getCRbit( bi )),
11425                              getIReg(rB),
11426                              rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
11427                                      : getIReg(rA) )
11428             );
11429             DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
11430             goto decode_success;
11431          }
11432          goto decode_failure;
11433       }
11434       break;
11435
11436
11437    case 0x04:
11438       /* AltiVec instructions */
11439
11440       opc2 = IFIELD(theInstr, 0, 6);
11441       switch (opc2) {
11442       /* AV Mult-Add, Mult-Sum */
11443       case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
11444       case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
11445       case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
11446          if (!allow_V) goto decode_noV;
11447          if (dis_av_multarith( theInstr )) goto decode_success;
11448          goto decode_failure;
11449
11450       /* AV Permutations */
11451       case 0x2A:                       // vsel
11452       case 0x2B:                       // vperm
11453       case 0x2C:                       // vsldoi
11454          if (!allow_V) goto decode_noV;
11455          if (dis_av_permute( theInstr )) goto decode_success;
11456          goto decode_failure;
11457
11458       /* AV Floating Point Mult-Add/Sub */
11459       case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
11460          if (!allow_V) goto decode_noV;
11461          if (dis_av_fp_arith( theInstr )) goto decode_success;
11462          goto decode_failure;
11463
11464       default:
11465          break;  // Fall through...
11466       }
11467
11468       opc2 = IFIELD(theInstr, 0, 11);
11469       switch (opc2) {
11470       /* AV Arithmetic */
11471       case 0x180:                         // vaddcuw
11472       case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
11473       case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
11474       case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
11475       case 0x580:                         // vsubcuw
11476       case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
11477       case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
11478       case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
11479       case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
11480       case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
11481       case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
11482       case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
11483       case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
11484       case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
11485       case 0x008: case 0x048:             // vmuloub, vmulouh
11486       case 0x108: case 0x148:             // vmulosb, vmulosh
11487       case 0x208: case 0x248:             // vmuleub, vmuleuh
11488       case 0x308: case 0x348:             // vmulesb, vmulesh
11489       case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
11490       case 0x688: case 0x788:             // vsum2sws, vsumsws
11491          if (!allow_V) goto decode_noV;
11492          if (dis_av_arith( theInstr )) goto decode_success;
11493          goto decode_failure;
11494
11495       /* AV Rotate, Shift */
11496       case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
11497       case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
11498       case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
11499       case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
11500       case 0x1C4: case 0x2C4:             // vsl, vsr
11501       case 0x40C: case 0x44C:             // vslo, vsro
11502          if (!allow_V) goto decode_noV;
11503          if (dis_av_shift( theInstr )) goto decode_success;
11504          goto decode_failure;
11505
11506       /* AV Logic */
11507       case 0x404: case 0x444: case 0x484: // vand, vandc, vor
11508       case 0x4C4: case 0x504:             // vxor, vnor
11509          if (!allow_V) goto decode_noV;
11510          if (dis_av_logic( theInstr )) goto decode_success;
11511          goto decode_failure;
11512
11513       /* AV Processor Control */
11514       case 0x604: case 0x644:             // mfvscr, mtvscr
11515          if (!allow_V) goto decode_noV;
11516          if (dis_av_procctl( theInstr )) goto decode_success;
11517          goto decode_failure;
11518
11519       /* AV Floating Point Arithmetic */
11520       case 0x00A: case 0x04A:             // vaddfp, vsubfp
11521       case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
11522       case 0x1CA:                         // vlogefp
11523       case 0x40A: case 0x44A:             // vmaxfp, vminfp
11524          if (!allow_V) goto decode_noV;
11525          if (dis_av_fp_arith( theInstr )) goto decode_success;
11526          goto decode_failure;
11527
11528       /* AV Floating Point Round/Convert */
11529       case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
11530       case 0x2CA:                         // vrfim
11531       case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
11532       case 0x3CA:                         // vctsxs
11533          if (!allow_V) goto decode_noV;
11534          if (dis_av_fp_convert( theInstr )) goto decode_success;
11535          goto decode_failure;
11536
11537       /* AV Merge, Splat */
11538       case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
11539       case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
11540       case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
11541       case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
11542          if (!allow_V) goto decode_noV;
11543          if (dis_av_permute( theInstr )) goto decode_success;
11544          goto decode_failure;
11545
11546       /* AV Pack, Unpack */
11547       case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
11548       case 0x0CE:                         // vpkuwus
11549       case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
11550       case 0x1CE:                         // vpkswss
11551       case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
11552       case 0x2CE:                         // vupklsh
11553       case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
11554          if (!allow_V) goto decode_noV;
11555          if (dis_av_pack( theInstr )) goto decode_success;
11556          goto decode_failure;
11557
11558       default:
11559          break;  // Fall through...
11560       }
11561
11562       opc2 = IFIELD(theInstr, 0, 10);
11563       switch (opc2) {
11564
11565       /* AV Compare */
11566       case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
11567       case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
11568       case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
11569          if (!allow_V) goto decode_noV;
11570          if (dis_av_cmp( theInstr )) goto decode_success;
11571          goto decode_failure;
11572
11573       /* AV Floating Point Compare */
11574       case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
11575       case 0x3C6:                         // vcmpbfp
11576          if (!allow_V) goto decode_noV;
11577          if (dis_av_fp_cmp( theInstr )) goto decode_success;
11578          goto decode_failure;
11579
11580       default:
11581          goto decode_failure;
11582       }
11583       break;
11584
11585    default:
11586       goto decode_failure;
11587
11588    decode_noF:
11589       vassert(!allow_F);
11590       vex_printf("disInstr(ppc): declined to decode an FP insn.\n");
11591       goto decode_failure;
11592    decode_noV:
11593       vassert(!allow_V);
11594       vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n");
11595       goto decode_failure;
11596    decode_noVX:
11597       vassert(!allow_VX);
11598       vex_printf("disInstr(ppc): declined to decode a VSX insn.\n");
11599       goto decode_failure;
11600    decode_noFX:
11601       vassert(!allow_FX);
11602       vex_printf("disInstr(ppc): "
11603                  "declined to decode a GeneralPurpose-Optional insn.\n");
11604       goto decode_failure;
11605    decode_noGX:
11606       vassert(!allow_GX);
11607       vex_printf("disInstr(ppc): "
11608                  "declined to decode a Graphics-Optional insn.\n");
11609       goto decode_failure;
11610
11611    decode_failure:
11612    /* All decode failures end up here. */
11613    opc2 = (theInstr) & 0x7FF;
11614    vex_printf("disInstr(ppc): unhandled instruction: "
11615               "0x%x\n", theInstr);
11616    vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n", 
11617               opc1, opc1, opc2, opc2);
11618
11619    /* Tell the dispatcher that this insn cannot be decoded, and so has
11620       not been executed, and (is currently) the next to be executed.
11621       CIA should be up-to-date since it made so at the start of each
11622       insn, but nevertheless be paranoid and update it again right
11623       now. */
11624    putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
11625    irsb->next     = mkSzImm(ty, guest_CIA_curr_instr);
11626    irsb->jumpkind = Ijk_NoDecode;
11627    dres.whatNext  = Dis_StopHere;
11628    dres.len       = 0;
11629    return dres;
11630
11631    } /* switch (opc) for the main (primary) opcode switch. */
11632
11633   decode_success:
11634    /* All decode successes end up here. */
11635    DIP("\n");
11636
11637    if (dres.len == 0) {
11638       dres.len = 4;
11639    } else {
11640       vassert(dres.len == 20);
11641    }
11642    return dres;
11643 }
11644
11645 #undef DIP
11646 #undef DIS
11647
11648
11649 /*------------------------------------------------------------*/
11650 /*--- Top-level fn                                         ---*/
11651 /*------------------------------------------------------------*/
11652
11653 /* Disassemble a single instruction into IR.  The instruction
11654    is located in host memory at &guest_code[delta]. */
11655
11656 DisResult disInstr_PPC ( IRSB*        irsb_IN,
11657                          Bool         put_IP,
11658                          Bool         (*resteerOkFn) ( void*, Addr64 ),
11659                          Bool         resteerCisOk,
11660                          void*        callback_opaque,
11661                          UChar*       guest_code_IN,
11662                          Long         delta,
11663                          Addr64       guest_IP,
11664                          VexArch      guest_arch,
11665                          VexArchInfo* archinfo,
11666                          VexAbiInfo*  abiinfo,
11667                          Bool         host_bigendian_IN )
11668 {
11669    IRType     ty;
11670    DisResult  dres;
11671    UInt       mask32, mask64;
11672    UInt hwcaps_guest = archinfo->hwcaps;
11673
11674    vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
11675
11676    /* global -- ick */
11677    mode64 = guest_arch == VexArchPPC64;
11678    ty = mode64 ? Ity_I64 : Ity_I32;
11679
11680    /* do some sanity checks */
11681    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
11682             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX;
11683
11684    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
11685                    | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX;
11686
11687    if (mode64) {
11688       vassert((hwcaps_guest & mask32) == 0);
11689    } else {
11690       vassert((hwcaps_guest & mask64) == 0);
11691    }
11692
11693    /* Set globals (see top of this file) */
11694    guest_code           = guest_code_IN;
11695    irsb                 = irsb_IN;
11696    host_is_bigendian    = host_bigendian_IN;
11697
11698    guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
11699    guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
11700
11701    dres = disInstr_PPC_WRK ( put_IP, 
11702                              resteerOkFn, resteerCisOk, callback_opaque,
11703                              delta, archinfo, abiinfo );
11704
11705    return dres;
11706 }
11707
11708
11709 /*------------------------------------------------------------*/
11710 /*--- Unused stuff                                         ---*/
11711 /*------------------------------------------------------------*/
11712
11713 ///* A potentially more memcheck-friendly implementation of Clz32, with
11714 //   the boundary case Clz32(0) = 32, which is what ppc requires. */
11715 //
11716 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
11717 //{
11718 //   /* Welcome ... to SSA R Us. */
11719 //   IRTemp n1  = newTemp(Ity_I32);
11720 //   IRTemp n2  = newTemp(Ity_I32);
11721 //   IRTemp n3  = newTemp(Ity_I32);
11722 //   IRTemp n4  = newTemp(Ity_I32);
11723 //   IRTemp n5  = newTemp(Ity_I32);
11724 //   IRTemp n6  = newTemp(Ity_I32);
11725 //   IRTemp n7  = newTemp(Ity_I32);
11726 //   IRTemp n8  = newTemp(Ity_I32);
11727 //   IRTemp n9  = newTemp(Ity_I32);
11728 //   IRTemp n10 = newTemp(Ity_I32);
11729 //   IRTemp n11 = newTemp(Ity_I32);
11730 //   IRTemp n12 = newTemp(Ity_I32);
11731 //
11732 //   /* First, propagate the most significant 1-bit into all lower
11733 //      positions in the word. */
11734 //   /* unsigned int clz ( unsigned int n )
11735 //      {
11736 //         n |= (n >> 1);
11737 //         n |= (n >> 2);
11738 //         n |= (n >> 4);
11739 //         n |= (n >> 8);
11740 //         n |= (n >> 16);
11741 //         return bitcount(~n);
11742 //      }
11743 //   */
11744 //   assign(n1, mkexpr(arg));
11745 //   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
11746 //   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
11747 //   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
11748 //   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
11749 //   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
11750 //   /* This gives a word of the form 0---01---1.  Now invert it, giving
11751 //      a word of the form 1---10---0, then do a population-count idiom
11752 //      (to count the 1s, which is the number of leading zeroes, or 32
11753 //      if the original word was 0. */
11754 //   assign(n7, unop(Iop_Not32, mkexpr(n6)));
11755 //
11756 //   /* unsigned int bitcount ( unsigned int n )
11757 //      {
11758 //         n = n - ((n >> 1) & 0x55555555);
11759 //         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
11760 //         n = (n + (n >> 4)) & 0x0F0F0F0F;
11761 //         n = n + (n >> 8);
11762 //         n = (n + (n >> 16)) & 0x3F;
11763 //         return n;
11764 //      }
11765 //   */
11766 //   assign(n8, 
11767 //          binop(Iop_Sub32, 
11768 //                mkexpr(n7),  
11769 //                binop(Iop_And32, 
11770 //                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
11771 //                      mkU32(0x55555555))));
11772 //   assign(n9,
11773 //          binop(Iop_Add32,
11774 //                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
11775 //                binop(Iop_And32,
11776 //                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
11777 //                      mkU32(0x33333333))));
11778 //   assign(n10,
11779 //          binop(Iop_And32,
11780 //                binop(Iop_Add32, 
11781 //                      mkexpr(n9), 
11782 //                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
11783 //                mkU32(0x0F0F0F0F)));
11784 //   assign(n11,
11785 //          binop(Iop_Add32,
11786 //                mkexpr(n10),
11787 //                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
11788 //   assign(n12,
11789 //          binop(Iop_Add32,
11790 //                mkexpr(n11),
11791 //                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
11792 //   return
11793 //      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
11794 //}
11795
11796 /*--------------------------------------------------------------------*/
11797 /*--- end                                         guest_ppc_toIR.c ---*/
11798 /*--------------------------------------------------------------------*/