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