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