3 /*--------------------------------------------------------------------*/
4 /*--- begin guest_ppc_toIR.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2004-2010 OpenWorks LLP
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29 The GNU General Public License is contained in the file COPYING.
31 Neither the names of the U.S. Department of Energy nor the
32 University of California nor the names of its contributors may be
33 used to endorse or promote products derived from this software
34 without prior written permission.
39 Spot rld... cases which are simply left/right shifts and emit
40 Shl64/Shr64 accordingly.
44 - lvxl,stvxl: load/store with 'least recently used' hint
51 - Some invalid forms of lswi and lswx are accepted when they should
55 - All exceptions disabled in FPSCR
56 - condition codes not set in FPSCR
58 - Altivec floating point:
60 Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
61 system default of Non-Java mode, we get some small errors
63 This is because Non-Java mode brutally hacks denormalised results
64 to zero, whereas we keep maximum accuracy. However, using
65 Non-Java mode would give us more inaccuracy, as our intermediate
66 results would then be zeroed, too.
68 - AbiHints for the stack red zone are only emitted for
69 unconditional calls and returns (bl, blr). They should also be
70 emitted for conditional calls and returns, but we don't have a
71 way to express that right now. Ah well.
74 /* "Special" instructions.
76 This instruction decoder can decode four special instructions
77 which mean nothing natively (are no-ops as far as regs/mem are
78 concerned) but have meaning for supporting Valgrind. A special
79 instruction is flagged by a 16-byte preamble:
81 32-bit mode: 54001800 54006800 5400E800 54009800
82 (rlwinm 0,0,3,0,0; rlwinm 0,0,13,0,0;
83 rlwinm 0,0,29,0,0; rlwinm 0,0,19,0,0)
85 64-bit mode: 78001800 78006800 7800E802 78009802
86 (rotldi 0,0,3; rotldi 0,0,13;
87 rotldi 0,0,61; rotldi 0,0,51)
89 Following that, one of the following 3 are allowed
90 (standard interpretation in parentheses):
92 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 )
93 7C421378 (or 2,2,2) %R3 = guest_NRADDR
94 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11
95 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2
97 Any other bytes following the 16-byte preamble are illegal and
98 constitute a failure in instruction decoding. This all assumes
99 that the preamble will never occur except in specific code
100 fragments designed for Valgrind to catch.
104 /* Translates PPC32/64 code to IR. */
109 "PowerPC Microprocessor Family:
110 The Programming Environments Manual for 32-Bit Microprocessors"
112 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
115 "PowerPC Microprocessor Family:
116 Programming Environments Manual for 64-Bit Microprocessors"
118 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
121 "PowerPC Microprocessor Family:
122 AltiVec(TM) Technology Programming Environments Manual"
124 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
127 #include "libvex_basictypes.h"
128 #include "libvex_ir.h"
130 #include "libvex_guest_ppc32.h"
131 #include "libvex_guest_ppc64.h"
133 #include "main_util.h"
134 #include "main_globals.h"
135 #include "guest_generic_bb_to_IR.h"
136 #include "guest_ppc_defs.h"
139 /*------------------------------------------------------------*/
141 /*------------------------------------------------------------*/
143 /* These are set at the start of the translation of an insn, right
144 down in disInstr_PPC, so that we don't have to pass them around
145 endlessly. They are all constant during the translation of any
148 /* We need to know this to do sub-register accesses correctly. */
149 static Bool host_is_bigendian;
151 /* Pointer to the guest code area. */
152 static UChar* guest_code;
154 /* The guest address corresponding to guest_code[0]. */
155 static Addr64 guest_CIA_bbstart;
157 /* The guest address for the instruction currently being
159 static Addr64 guest_CIA_curr_instr;
161 /* The IRSB* into which we're generating code. */
164 /* Is our guest binary 32 or 64bit? Set at each call to
165 disInstr_PPC below. */
166 static Bool mode64 = False;
168 // Given a pointer to a function as obtained by "& functionname" in C,
169 // produce a pointer to the actual entry point for the function. For
170 // most platforms it's the identity function. Unfortunately, on
171 // ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and
173 static void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f )
175 if (vbi->host_ppc_calls_use_fndescrs) {
176 /* f is a pointer to a 3-word function descriptor, of which the
177 first word is the entry address. */
178 /* note, this is correct even with cross-jitting, since this is
179 purely a host issue, not a guest one. */
180 HWord* fdescr = (HWord*)f;
181 return (void*)(fdescr[0]);
183 /* Simple; "& f" points directly at the code for f. */
189 /*------------------------------------------------------------*/
190 /*--- Debugging output ---*/
191 /*------------------------------------------------------------*/
193 #define DIP(format, args...) \
194 if (vex_traceflags & VEX_TRACE_FE) \
195 vex_printf(format, ## args)
197 #define DIS(buf, format, args...) \
198 if (vex_traceflags & VEX_TRACE_FE) \
199 vex_sprintf(buf, format, ## args)
202 /*------------------------------------------------------------*/
203 /*--- Offsets of various parts of the ppc32/64 guest state ---*/
204 /*------------------------------------------------------------*/
206 #define offsetofPPCGuestState(_x) \
207 (mode64 ? offsetof(VexGuestPPC64State, _x) : \
208 offsetof(VexGuestPPC32State, _x))
210 #define OFFB_CIA offsetofPPCGuestState(guest_CIA)
211 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
212 #define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO)
213 #define OFFB_LR offsetofPPCGuestState(guest_LR)
214 #define OFFB_CTR offsetofPPCGuestState(guest_CTR)
215 #define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO)
216 #define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV)
217 #define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA)
218 #define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC)
219 #define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND)
220 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE)
221 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR)
222 #define OFFB_EMWARN offsetofPPCGuestState(guest_EMWARN)
223 #define OFFB_TISTART offsetofPPCGuestState(guest_TISTART)
224 #define OFFB_TILEN offsetofPPCGuestState(guest_TILEN)
225 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR)
226 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
229 /*------------------------------------------------------------*/
230 /*--- Extract instruction fields --- */
231 /*------------------------------------------------------------*/
233 /* Extract field from insn, given idx (zero = lsb) and field length */
234 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
236 /* Extract primary opcode, instr[31:26] */
237 static UChar ifieldOPC( UInt instr ) {
238 return toUChar( IFIELD( instr, 26, 6 ) );
241 /* Extract 10-bit secondary opcode, instr[10:1] */
242 static UInt ifieldOPClo10 ( UInt instr) {
243 return IFIELD( instr, 1, 10 );
246 /* Extract 9-bit secondary opcode, instr[9:1] */
247 static UInt ifieldOPClo9 ( UInt instr) {
248 return IFIELD( instr, 1, 9 );
251 /* Extract 5-bit secondary opcode, instr[5:1] */
252 static UInt ifieldOPClo5 ( UInt instr) {
253 return IFIELD( instr, 1, 5 );
256 /* Extract RD (destination register) field, instr[25:21] */
257 static UChar ifieldRegDS( UInt instr ) {
258 return toUChar( IFIELD( instr, 21, 5 ) );
261 /* Extract XT (destination register) field, instr[0,25:21] */
262 static UChar ifieldRegXT ( UInt instr )
264 UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
265 UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
266 return (upper_bit << 5) | lower_bits;
269 /* Extract XS (store source register) field, instr[0,25:21] */
270 static inline UChar ifieldRegXS ( UInt instr )
272 return ifieldRegXT ( instr );
275 /* Extract RA (1st source register) field, instr[20:16] */
276 static UChar ifieldRegA ( UInt instr ) {
277 return toUChar( IFIELD( instr, 16, 5 ) );
280 /* Extract XA (1st source register) field, instr[2,20:16] */
281 static UChar ifieldRegXA ( UInt instr )
283 UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
284 UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
285 return (upper_bit << 5) | lower_bits;
288 /* Extract RB (2nd source register) field, instr[15:11] */
289 static UChar ifieldRegB ( UInt instr ) {
290 return toUChar( IFIELD( instr, 11, 5 ) );
293 /* Extract XB (2nd source register) field, instr[1,15:11] */
294 static UChar ifieldRegXB ( UInt instr )
296 UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
297 UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
298 return (upper_bit << 5) | lower_bits;
301 /* Extract RC (3rd source register) field, instr[10:6] */
302 static UChar ifieldRegC ( UInt instr ) {
303 return toUChar( IFIELD( instr, 6, 5 ) );
306 /* Extract bit 10, instr[10] */
307 static UChar ifieldBIT10 ( UInt instr ) {
308 return toUChar( IFIELD( instr, 10, 1 ) );
311 /* Extract 2nd lowest bit, instr[1] */
312 static UChar ifieldBIT1 ( UInt instr ) {
313 return toUChar( IFIELD( instr, 1, 1 ) );
316 /* Extract lowest bit, instr[0] */
317 static UChar ifieldBIT0 ( UInt instr ) {
318 return toUChar( instr & 0x1 );
321 /* Extract unsigned bottom half, instr[15:0] */
322 static UInt ifieldUIMM16 ( UInt instr ) {
323 return instr & 0xFFFF;
326 /* Extract unsigned bottom 26 bits, instr[25:0] */
327 static UInt ifieldUIMM26 ( UInt instr ) {
328 return instr & 0x3FFFFFF;
331 /* Extract DM field, instr[9:8] */
332 static UChar ifieldDM ( UInt instr ) {
333 return toUChar( IFIELD( instr, 8, 2 ) );
336 /* Extract SHW field, instr[9:8] */
337 static inline UChar ifieldSHW ( UInt instr )
339 return ifieldDM ( instr );
342 /*------------------------------------------------------------*/
343 /*--- Guest-state identifiers ---*/
344 /*------------------------------------------------------------*/
347 PPC_GST_CIA, // Current Instruction Address
348 PPC_GST_LR, // Link Register
349 PPC_GST_CTR, // Count Register
350 PPC_GST_XER, // Overflow, carry flags, byte count
351 PPC_GST_CR, // Condition Register
352 PPC_GST_FPSCR, // Floating Point Status/Control Register
353 PPC_GST_VRSAVE, // Vector Save/Restore Register
354 PPC_GST_VSCR, // Vector Status and Control Register
355 PPC_GST_EMWARN, // Emulation warnings
356 PPC_GST_TISTART,// For icbi: start of area to invalidate
357 PPC_GST_TILEN, // For icbi: length of area to invalidate
358 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
359 PPC_GST_SPRG3_RO, // SPRG3
363 #define MASK_FPSCR_RN 0x3
364 #define MASK_FPSCR_FPRF 0x1F000
365 #define MASK_VSCR_VALID 0x00010001
368 /*------------------------------------------------------------*/
369 /*--- FP Helpers ---*/
370 /*------------------------------------------------------------*/
372 /* Produce the 32-bit pattern corresponding to the supplied
374 static UInt float_to_bits ( Float f )
376 union { UInt i; Float f; } u;
377 vassert(4 == sizeof(UInt));
378 vassert(4 == sizeof(Float));
379 vassert(4 == sizeof(u));
385 /*------------------------------------------------------------*/
386 /*--- Misc Helpers ---*/
387 /*------------------------------------------------------------*/
389 /* Generate mask with 1's from 'begin' through 'end',
390 wrapping if begin > end.
391 begin->end works from right to left, 0=lsb
393 static UInt MASK32( UInt begin, UInt end )
398 m1 = ((UInt)(-1)) << begin;
399 m2 = ((UInt)(-1)) << end << 1;
401 if (begin > end) mask = ~mask; // wrap mask
405 /* ditto for 64bit mask */
406 static ULong MASK64( UInt begin, UInt end )
411 m1 = ((ULong)(-1)) << begin;
412 m2 = ((ULong)(-1)) << end << 1;
414 if (begin > end) mask = ~mask; // wrap mask
418 static Addr64 nextInsnAddr( void )
420 return guest_CIA_curr_instr + 4;
424 /*------------------------------------------------------------*/
425 /*--- Helper bits and pieces for deconstructing the ---*/
426 /*--- ppc32/64 insn stream. ---*/
427 /*------------------------------------------------------------*/
429 /* Add a statement to the list held by "irsb". */
430 static void stmt ( IRStmt* st )
432 addStmtToIRSB( irsb, st );
435 /* Generate a new temporary of the given type. */
436 static IRTemp newTemp ( IRType ty )
438 vassert(isPlausibleIRType(ty));
439 return newIRTemp( irsb->tyenv, ty );
442 /* Various simple conversions */
444 static UChar extend_s_5to8 ( UChar x )
446 return toUChar((((Int)x) << 27) >> 27);
449 static UInt extend_s_8to32( UChar x )
451 return (UInt)((((Int)x) << 24) >> 24);
454 static UInt extend_s_16to32 ( UInt x )
456 return (UInt)((((Int)x) << 16) >> 16);
459 static ULong extend_s_16to64 ( UInt x )
461 return (ULong)((((Long)x) << 48) >> 48);
464 static ULong extend_s_26to64 ( UInt x )
466 return (ULong)((((Long)x) << 38) >> 38);
469 static ULong extend_s_32to64 ( UInt x )
471 return (ULong)((((Long)x) << 32) >> 32);
474 /* Do a big-endian load of a 32-bit word, regardless of the endianness
475 of the underlying host. */
476 static UInt getUIntBigendianly ( UChar* p )
487 /*------------------------------------------------------------*/
488 /*--- Helpers for constructing IR. ---*/
489 /*------------------------------------------------------------*/
491 static void assign ( IRTemp dst, IRExpr* e )
493 stmt( IRStmt_WrTmp(dst, e) );
496 /* This generates a normal (non store-conditional) store. */
497 static void storeBE ( IRExpr* addr, IRExpr* data )
499 IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
500 vassert(tyA == Ity_I32 || tyA == Ity_I64);
501 stmt( IRStmt_Store(Iend_BE, addr, data) );
504 static IRExpr* unop ( IROp op, IRExpr* a )
506 return IRExpr_Unop(op, a);
509 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
511 return IRExpr_Binop(op, a1, a2);
514 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
516 return IRExpr_Triop(op, a1, a2, a3);
519 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
520 IRExpr* a3, IRExpr* a4 )
522 return IRExpr_Qop(op, a1, a2, a3, a4);
525 static IRExpr* mkexpr ( IRTemp tmp )
527 return IRExpr_RdTmp(tmp);
530 static IRExpr* mkU8 ( UChar i )
532 return IRExpr_Const(IRConst_U8(i));
535 static IRExpr* mkU16 ( UInt i )
537 return IRExpr_Const(IRConst_U16(i));
540 static IRExpr* mkU32 ( UInt i )
542 return IRExpr_Const(IRConst_U32(i));
545 static IRExpr* mkU64 ( ULong i )
547 return IRExpr_Const(IRConst_U64(i));
550 static IRExpr* mkV128 ( UShort i )
552 vassert(i == 0 || i == 0xffff);
553 return IRExpr_Const(IRConst_V128(i));
556 /* This generates a normal (non load-linked) load. */
557 static IRExpr* loadBE ( IRType ty, IRExpr* addr )
559 return IRExpr_Load(Iend_BE, ty, addr);
562 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
564 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
565 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
566 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
567 unop(Iop_1Uto32, arg2)));
570 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
572 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
573 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
574 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
575 unop(Iop_1Uto32, arg2)));
578 /* expand V128_8Ux16 to 2x V128_16Ux8's */
579 static void expand8Ux16( IRExpr* vIn,
580 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
582 IRTemp ones8x16 = newTemp(Ity_V128);
584 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
585 vassert(vEvn && *vEvn == IRTemp_INVALID);
586 vassert(vOdd && *vOdd == IRTemp_INVALID);
587 *vEvn = newTemp(Ity_V128);
588 *vOdd = newTemp(Ity_V128);
590 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
591 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
592 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
593 binop(Iop_ShrV128, vIn, mkU8(8))) );
596 /* expand V128_8Sx16 to 2x V128_16Sx8's */
597 static void expand8Sx16( IRExpr* vIn,
598 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
600 IRTemp ones8x16 = newTemp(Ity_V128);
602 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
603 vassert(vEvn && *vEvn == IRTemp_INVALID);
604 vassert(vOdd && *vOdd == IRTemp_INVALID);
605 *vEvn = newTemp(Ity_V128);
606 *vOdd = newTemp(Ity_V128);
608 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
609 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
610 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
611 binop(Iop_ShrV128, vIn, mkU8(8))) );
614 /* expand V128_16Uto8 to 2x V128_32Ux4's */
615 static void expand16Ux8( IRExpr* vIn,
616 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
618 IRTemp ones16x8 = newTemp(Ity_V128);
620 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
621 vassert(vEvn && *vEvn == IRTemp_INVALID);
622 vassert(vOdd && *vOdd == IRTemp_INVALID);
623 *vEvn = newTemp(Ity_V128);
624 *vOdd = newTemp(Ity_V128);
626 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
627 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
628 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
629 binop(Iop_ShrV128, vIn, mkU8(16))) );
632 /* expand V128_16Sto8 to 2x V128_32Sx4's */
633 static void expand16Sx8( IRExpr* vIn,
634 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
636 IRTemp ones16x8 = newTemp(Ity_V128);
638 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
639 vassert(vEvn && *vEvn == IRTemp_INVALID);
640 vassert(vOdd && *vOdd == IRTemp_INVALID);
641 *vEvn = newTemp(Ity_V128);
642 *vOdd = newTemp(Ity_V128);
644 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
645 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
646 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
647 binop(Iop_ShrV128, vIn, mkU8(16))) );
650 /* break V128 to 4xI32's, then sign-extend to I64's */
651 static void breakV128to4x64S( IRExpr* t128,
653 IRTemp* t3, IRTemp* t2,
654 IRTemp* t1, IRTemp* t0 )
656 IRTemp hi64 = newTemp(Ity_I64);
657 IRTemp lo64 = newTemp(Ity_I64);
659 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
660 vassert(t0 && *t0 == IRTemp_INVALID);
661 vassert(t1 && *t1 == IRTemp_INVALID);
662 vassert(t2 && *t2 == IRTemp_INVALID);
663 vassert(t3 && *t3 == IRTemp_INVALID);
664 *t0 = newTemp(Ity_I64);
665 *t1 = newTemp(Ity_I64);
666 *t2 = newTemp(Ity_I64);
667 *t3 = newTemp(Ity_I64);
669 assign( hi64, unop(Iop_V128HIto64, t128) );
670 assign( lo64, unop(Iop_V128to64, t128) );
671 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
672 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) );
673 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
674 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) );
677 /* break V128 to 4xI32's, then zero-extend to I64's */
678 static void breakV128to4x64U ( IRExpr* t128,
680 IRTemp* t3, IRTemp* t2,
681 IRTemp* t1, IRTemp* t0 )
683 IRTemp hi64 = newTemp(Ity_I64);
684 IRTemp lo64 = newTemp(Ity_I64);
686 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
687 vassert(t0 && *t0 == IRTemp_INVALID);
688 vassert(t1 && *t1 == IRTemp_INVALID);
689 vassert(t2 && *t2 == IRTemp_INVALID);
690 vassert(t3 && *t3 == IRTemp_INVALID);
691 *t0 = newTemp(Ity_I64);
692 *t1 = newTemp(Ity_I64);
693 *t2 = newTemp(Ity_I64);
694 *t3 = newTemp(Ity_I64);
696 assign( hi64, unop(Iop_V128HIto64, t128) );
697 assign( lo64, unop(Iop_V128to64, t128) );
698 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
699 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) );
700 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
701 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) );
704 /* Signed saturating narrow 64S to 32 */
705 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
707 IRTemp hi32 = newTemp(Ity_I32);
708 IRTemp lo32 = newTemp(Ity_I32);
710 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
712 assign( hi32, unop(Iop_64HIto32, t64));
713 assign( lo32, unop(Iop_64to32, t64));
716 /* if (hi32 == (lo32 >>s 31)) */
718 binop(Iop_CmpEQ32, mkexpr(hi32),
719 binop( Iop_Sar32, mkexpr(lo32), mkU8(31)))),
720 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
721 binop(Iop_Add32, mkU32(0x7FFFFFFF),
722 binop(Iop_Shr32, mkexpr(hi32), mkU8(31))),
723 /* then: within signed-32 range: lo half good enough */
727 /* Unsigned saturating narrow 64S to 32 */
728 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
730 IRTemp hi32 = newTemp(Ity_I32);
731 IRTemp lo32 = newTemp(Ity_I32);
733 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
735 assign( hi32, unop(Iop_64HIto32, t64));
736 assign( lo32, unop(Iop_64to32, t64));
739 /* if (top 32 bits of t64 are 0) */
740 unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0))),
741 /* else: positive saturate -> 0xFFFFFFFF */
743 /* then: within unsigned-32 range: lo half good enough */
747 /* Signed saturate narrow 64->32, combining to V128 */
748 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
749 IRExpr* t1, IRExpr* t0 )
751 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
752 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
753 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
754 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
755 return binop(Iop_64HLtoV128,
757 mkQNarrow64Sto32( t3 ),
758 mkQNarrow64Sto32( t2 )),
760 mkQNarrow64Sto32( t1 ),
761 mkQNarrow64Sto32( t0 )));
764 /* Unsigned saturate narrow 64->32, combining to V128 */
765 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
766 IRExpr* t1, IRExpr* t0 )
768 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
769 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
770 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
771 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
772 return binop(Iop_64HLtoV128,
774 mkQNarrow64Uto32( t3 ),
775 mkQNarrow64Uto32( t2 )),
777 mkQNarrow64Uto32( t1 ),
778 mkQNarrow64Uto32( t0 )));
781 /* Simulate irops Iop_MullOdd*, since we don't have them */
782 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
783 binop(Iop_MullEven8Ux16, \
784 binop(Iop_ShrV128, expr_vA, mkU8(8)), \
785 binop(Iop_ShrV128, expr_vB, mkU8(8)))
787 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
788 binop(Iop_MullEven8Sx16, \
789 binop(Iop_ShrV128, expr_vA, mkU8(8)), \
790 binop(Iop_ShrV128, expr_vB, mkU8(8)))
792 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
793 binop(Iop_MullEven16Ux8, \
794 binop(Iop_ShrV128, expr_vA, mkU8(16)), \
795 binop(Iop_ShrV128, expr_vB, mkU8(16)))
797 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
798 binop(Iop_MullEven16Sx8, \
799 binop(Iop_ShrV128, expr_vA, mkU8(16)), \
800 binop(Iop_ShrV128, expr_vB, mkU8(16)))
802 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
804 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
805 return unop(Iop_32Sto64, unop(Iop_64to32, src));
808 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
810 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
811 return unop(Iop_32Uto64, unop(Iop_64to32, src));
814 static IROp mkSzOp ( IRType ty, IROp op8 )
817 vassert(ty == Ity_I8 || ty == Ity_I16 ||
818 ty == Ity_I32 || ty == Ity_I64);
819 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 ||
820 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 ||
821 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 ||
822 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
824 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
828 /* Make sure we get valid 32 and 64bit addresses */
829 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
831 vassert(ty == Ity_I32 || ty == Ity_I64);
832 return ( ty == Ity_I64 ?
834 (Addr64)extend_s_32to64( toUInt(addr) ) );
837 /* sz, ULong -> IRExpr */
838 static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
840 vassert(ty == Ity_I32 || ty == Ity_I64);
841 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
844 /* sz, ULong -> IRConst */
845 static IRConst* mkSzConst ( IRType ty, ULong imm64 )
847 vassert(ty == Ity_I32 || ty == Ity_I64);
848 return ( ty == Ity_I64 ?
850 IRConst_U32((UInt)imm64) );
853 /* Sign extend imm16 -> IRExpr* */
854 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
856 vassert(ty == Ity_I32 || ty == Ity_I64);
857 return ( ty == Ity_I64 ?
858 mkU64(extend_s_16to64(imm16)) :
859 mkU32(extend_s_16to32(imm16)) );
862 /* Sign extend imm32 -> IRExpr* */
863 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
865 vassert(ty == Ity_I32 || ty == Ity_I64);
866 return ( ty == Ity_I64 ?
867 mkU64(extend_s_32to64(imm32)) :
871 /* IR narrows I32/I64 -> I8/I16/I32 */
872 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
874 vassert(ty == Ity_I32 || ty == Ity_I64);
875 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
878 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
880 vassert(ty == Ity_I32 || ty == Ity_I64);
881 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
884 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
886 vassert(ty == Ity_I32 || ty == Ity_I64);
887 return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
890 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
891 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
894 vassert(ty == Ity_I32 || ty == Ity_I64);
895 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
896 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
897 return unop(op, src);
900 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
903 vassert(ty == Ity_I32 || ty == Ity_I64);
904 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
905 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
906 return unop(op, src);
909 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
911 vassert(ty == Ity_I32 || ty == Ity_I64);
914 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
918 static Int integerGuestRegOffset ( UInt archreg )
920 vassert(archreg < 32);
922 // jrs: probably not necessary; only matters if we reference sub-parts
923 // of the ppc registers, but that isn't the case
924 // later: this might affect Altivec though?
925 vassert(host_is_bigendian);
928 case 0: return offsetofPPCGuestState(guest_GPR0);
929 case 1: return offsetofPPCGuestState(guest_GPR1);
930 case 2: return offsetofPPCGuestState(guest_GPR2);
931 case 3: return offsetofPPCGuestState(guest_GPR3);
932 case 4: return offsetofPPCGuestState(guest_GPR4);
933 case 5: return offsetofPPCGuestState(guest_GPR5);
934 case 6: return offsetofPPCGuestState(guest_GPR6);
935 case 7: return offsetofPPCGuestState(guest_GPR7);
936 case 8: return offsetofPPCGuestState(guest_GPR8);
937 case 9: return offsetofPPCGuestState(guest_GPR9);
938 case 10: return offsetofPPCGuestState(guest_GPR10);
939 case 11: return offsetofPPCGuestState(guest_GPR11);
940 case 12: return offsetofPPCGuestState(guest_GPR12);
941 case 13: return offsetofPPCGuestState(guest_GPR13);
942 case 14: return offsetofPPCGuestState(guest_GPR14);
943 case 15: return offsetofPPCGuestState(guest_GPR15);
944 case 16: return offsetofPPCGuestState(guest_GPR16);
945 case 17: return offsetofPPCGuestState(guest_GPR17);
946 case 18: return offsetofPPCGuestState(guest_GPR18);
947 case 19: return offsetofPPCGuestState(guest_GPR19);
948 case 20: return offsetofPPCGuestState(guest_GPR20);
949 case 21: return offsetofPPCGuestState(guest_GPR21);
950 case 22: return offsetofPPCGuestState(guest_GPR22);
951 case 23: return offsetofPPCGuestState(guest_GPR23);
952 case 24: return offsetofPPCGuestState(guest_GPR24);
953 case 25: return offsetofPPCGuestState(guest_GPR25);
954 case 26: return offsetofPPCGuestState(guest_GPR26);
955 case 27: return offsetofPPCGuestState(guest_GPR27);
956 case 28: return offsetofPPCGuestState(guest_GPR28);
957 case 29: return offsetofPPCGuestState(guest_GPR29);
958 case 30: return offsetofPPCGuestState(guest_GPR30);
959 case 31: return offsetofPPCGuestState(guest_GPR31);
962 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
965 static IRExpr* getIReg ( UInt archreg )
967 IRType ty = mode64 ? Ity_I64 : Ity_I32;
968 vassert(archreg < 32);
969 return IRExpr_Get( integerGuestRegOffset(archreg), ty );
972 /* Ditto, but write to a reg instead. */
973 static void putIReg ( UInt archreg, IRExpr* e )
975 IRType ty = mode64 ? Ity_I64 : Ity_I32;
976 vassert(archreg < 32);
977 vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
978 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
982 /* Floating point egisters are mapped to VSX registers[0..31]. */
983 static Int floatGuestRegOffset ( UInt archreg )
985 vassert(archreg < 32);
988 case 0: return offsetofPPCGuestState(guest_VSR0);
989 case 1: return offsetofPPCGuestState(guest_VSR1);
990 case 2: return offsetofPPCGuestState(guest_VSR2);
991 case 3: return offsetofPPCGuestState(guest_VSR3);
992 case 4: return offsetofPPCGuestState(guest_VSR4);
993 case 5: return offsetofPPCGuestState(guest_VSR5);
994 case 6: return offsetofPPCGuestState(guest_VSR6);
995 case 7: return offsetofPPCGuestState(guest_VSR7);
996 case 8: return offsetofPPCGuestState(guest_VSR8);
997 case 9: return offsetofPPCGuestState(guest_VSR9);
998 case 10: return offsetofPPCGuestState(guest_VSR10);
999 case 11: return offsetofPPCGuestState(guest_VSR11);
1000 case 12: return offsetofPPCGuestState(guest_VSR12);
1001 case 13: return offsetofPPCGuestState(guest_VSR13);
1002 case 14: return offsetofPPCGuestState(guest_VSR14);
1003 case 15: return offsetofPPCGuestState(guest_VSR15);
1004 case 16: return offsetofPPCGuestState(guest_VSR16);
1005 case 17: return offsetofPPCGuestState(guest_VSR17);
1006 case 18: return offsetofPPCGuestState(guest_VSR18);
1007 case 19: return offsetofPPCGuestState(guest_VSR19);
1008 case 20: return offsetofPPCGuestState(guest_VSR20);
1009 case 21: return offsetofPPCGuestState(guest_VSR21);
1010 case 22: return offsetofPPCGuestState(guest_VSR22);
1011 case 23: return offsetofPPCGuestState(guest_VSR23);
1012 case 24: return offsetofPPCGuestState(guest_VSR24);
1013 case 25: return offsetofPPCGuestState(guest_VSR25);
1014 case 26: return offsetofPPCGuestState(guest_VSR26);
1015 case 27: return offsetofPPCGuestState(guest_VSR27);
1016 case 28: return offsetofPPCGuestState(guest_VSR28);
1017 case 29: return offsetofPPCGuestState(guest_VSR29);
1018 case 30: return offsetofPPCGuestState(guest_VSR30);
1019 case 31: return offsetofPPCGuestState(guest_VSR31);
1022 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1025 static IRExpr* getFReg ( UInt archreg )
1027 vassert(archreg < 32);
1028 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1031 /* Ditto, but write to a reg instead. */
1032 static void putFReg ( UInt archreg, IRExpr* e )
1034 vassert(archreg < 32);
1035 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1036 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1039 static Int vsxGuestRegOffset ( UInt archreg )
1041 vassert(archreg < 64);
1043 case 0: return offsetofPPCGuestState(guest_VSR0);
1044 case 1: return offsetofPPCGuestState(guest_VSR1);
1045 case 2: return offsetofPPCGuestState(guest_VSR2);
1046 case 3: return offsetofPPCGuestState(guest_VSR3);
1047 case 4: return offsetofPPCGuestState(guest_VSR4);
1048 case 5: return offsetofPPCGuestState(guest_VSR5);
1049 case 6: return offsetofPPCGuestState(guest_VSR6);
1050 case 7: return offsetofPPCGuestState(guest_VSR7);
1051 case 8: return offsetofPPCGuestState(guest_VSR8);
1052 case 9: return offsetofPPCGuestState(guest_VSR9);
1053 case 10: return offsetofPPCGuestState(guest_VSR10);
1054 case 11: return offsetofPPCGuestState(guest_VSR11);
1055 case 12: return offsetofPPCGuestState(guest_VSR12);
1056 case 13: return offsetofPPCGuestState(guest_VSR13);
1057 case 14: return offsetofPPCGuestState(guest_VSR14);
1058 case 15: return offsetofPPCGuestState(guest_VSR15);
1059 case 16: return offsetofPPCGuestState(guest_VSR16);
1060 case 17: return offsetofPPCGuestState(guest_VSR17);
1061 case 18: return offsetofPPCGuestState(guest_VSR18);
1062 case 19: return offsetofPPCGuestState(guest_VSR19);
1063 case 20: return offsetofPPCGuestState(guest_VSR20);
1064 case 21: return offsetofPPCGuestState(guest_VSR21);
1065 case 22: return offsetofPPCGuestState(guest_VSR22);
1066 case 23: return offsetofPPCGuestState(guest_VSR23);
1067 case 24: return offsetofPPCGuestState(guest_VSR24);
1068 case 25: return offsetofPPCGuestState(guest_VSR25);
1069 case 26: return offsetofPPCGuestState(guest_VSR26);
1070 case 27: return offsetofPPCGuestState(guest_VSR27);
1071 case 28: return offsetofPPCGuestState(guest_VSR28);
1072 case 29: return offsetofPPCGuestState(guest_VSR29);
1073 case 30: return offsetofPPCGuestState(guest_VSR30);
1074 case 31: return offsetofPPCGuestState(guest_VSR31);
1075 case 32: return offsetofPPCGuestState(guest_VSR32);
1076 case 33: return offsetofPPCGuestState(guest_VSR33);
1077 case 34: return offsetofPPCGuestState(guest_VSR34);
1078 case 35: return offsetofPPCGuestState(guest_VSR35);
1079 case 36: return offsetofPPCGuestState(guest_VSR36);
1080 case 37: return offsetofPPCGuestState(guest_VSR37);
1081 case 38: return offsetofPPCGuestState(guest_VSR38);
1082 case 39: return offsetofPPCGuestState(guest_VSR39);
1083 case 40: return offsetofPPCGuestState(guest_VSR40);
1084 case 41: return offsetofPPCGuestState(guest_VSR41);
1085 case 42: return offsetofPPCGuestState(guest_VSR42);
1086 case 43: return offsetofPPCGuestState(guest_VSR43);
1087 case 44: return offsetofPPCGuestState(guest_VSR44);
1088 case 45: return offsetofPPCGuestState(guest_VSR45);
1089 case 46: return offsetofPPCGuestState(guest_VSR46);
1090 case 47: return offsetofPPCGuestState(guest_VSR47);
1091 case 48: return offsetofPPCGuestState(guest_VSR48);
1092 case 49: return offsetofPPCGuestState(guest_VSR49);
1093 case 50: return offsetofPPCGuestState(guest_VSR50);
1094 case 51: return offsetofPPCGuestState(guest_VSR51);
1095 case 52: return offsetofPPCGuestState(guest_VSR52);
1096 case 53: return offsetofPPCGuestState(guest_VSR53);
1097 case 54: return offsetofPPCGuestState(guest_VSR54);
1098 case 55: return offsetofPPCGuestState(guest_VSR55);
1099 case 56: return offsetofPPCGuestState(guest_VSR56);
1100 case 57: return offsetofPPCGuestState(guest_VSR57);
1101 case 58: return offsetofPPCGuestState(guest_VSR58);
1102 case 59: return offsetofPPCGuestState(guest_VSR59);
1103 case 60: return offsetofPPCGuestState(guest_VSR60);
1104 case 61: return offsetofPPCGuestState(guest_VSR61);
1105 case 62: return offsetofPPCGuestState(guest_VSR62);
1106 case 63: return offsetofPPCGuestState(guest_VSR63);
1109 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1112 /* Vector registers are mapped to VSX registers[32..63]. */
1113 static Int vectorGuestRegOffset ( UInt archreg )
1115 vassert(archreg < 32);
1118 case 0: return offsetofPPCGuestState(guest_VSR32);
1119 case 1: return offsetofPPCGuestState(guest_VSR33);
1120 case 2: return offsetofPPCGuestState(guest_VSR34);
1121 case 3: return offsetofPPCGuestState(guest_VSR35);
1122 case 4: return offsetofPPCGuestState(guest_VSR36);
1123 case 5: return offsetofPPCGuestState(guest_VSR37);
1124 case 6: return offsetofPPCGuestState(guest_VSR38);
1125 case 7: return offsetofPPCGuestState(guest_VSR39);
1126 case 8: return offsetofPPCGuestState(guest_VSR40);
1127 case 9: return offsetofPPCGuestState(guest_VSR41);
1128 case 10: return offsetofPPCGuestState(guest_VSR42);
1129 case 11: return offsetofPPCGuestState(guest_VSR43);
1130 case 12: return offsetofPPCGuestState(guest_VSR44);
1131 case 13: return offsetofPPCGuestState(guest_VSR45);
1132 case 14: return offsetofPPCGuestState(guest_VSR46);
1133 case 15: return offsetofPPCGuestState(guest_VSR47);
1134 case 16: return offsetofPPCGuestState(guest_VSR48);
1135 case 17: return offsetofPPCGuestState(guest_VSR49);
1136 case 18: return offsetofPPCGuestState(guest_VSR50);
1137 case 19: return offsetofPPCGuestState(guest_VSR51);
1138 case 20: return offsetofPPCGuestState(guest_VSR52);
1139 case 21: return offsetofPPCGuestState(guest_VSR53);
1140 case 22: return offsetofPPCGuestState(guest_VSR54);
1141 case 23: return offsetofPPCGuestState(guest_VSR55);
1142 case 24: return offsetofPPCGuestState(guest_VSR56);
1143 case 25: return offsetofPPCGuestState(guest_VSR57);
1144 case 26: return offsetofPPCGuestState(guest_VSR58);
1145 case 27: return offsetofPPCGuestState(guest_VSR59);
1146 case 28: return offsetofPPCGuestState(guest_VSR60);
1147 case 29: return offsetofPPCGuestState(guest_VSR61);
1148 case 30: return offsetofPPCGuestState(guest_VSR62);
1149 case 31: return offsetofPPCGuestState(guest_VSR63);
1152 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1155 static IRExpr* getVReg ( UInt archreg )
1157 vassert(archreg < 32);
1158 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1161 /* Ditto, but write to a reg instead. */
1162 static void putVReg ( UInt archreg, IRExpr* e )
1164 vassert(archreg < 32);
1165 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1166 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1169 /* Get contents of VSX guest register */
1170 static IRExpr* getVSReg ( UInt archreg )
1172 vassert(archreg < 64);
1173 return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
1176 /* Ditto, but write to a VSX reg instead. */
1177 static void putVSReg ( UInt archreg, IRExpr* e )
1179 vassert(archreg < 64);
1180 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1181 stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
1185 static Int guestCR321offset ( UInt cr )
1188 case 0: return offsetofPPCGuestState(guest_CR0_321 );
1189 case 1: return offsetofPPCGuestState(guest_CR1_321 );
1190 case 2: return offsetofPPCGuestState(guest_CR2_321 );
1191 case 3: return offsetofPPCGuestState(guest_CR3_321 );
1192 case 4: return offsetofPPCGuestState(guest_CR4_321 );
1193 case 5: return offsetofPPCGuestState(guest_CR5_321 );
1194 case 6: return offsetofPPCGuestState(guest_CR6_321 );
1195 case 7: return offsetofPPCGuestState(guest_CR7_321 );
1196 default: vpanic("guestCR321offset(ppc)");
1200 static Int guestCR0offset ( UInt cr )
1203 case 0: return offsetofPPCGuestState(guest_CR0_0 );
1204 case 1: return offsetofPPCGuestState(guest_CR1_0 );
1205 case 2: return offsetofPPCGuestState(guest_CR2_0 );
1206 case 3: return offsetofPPCGuestState(guest_CR3_0 );
1207 case 4: return offsetofPPCGuestState(guest_CR4_0 );
1208 case 5: return offsetofPPCGuestState(guest_CR5_0 );
1209 case 6: return offsetofPPCGuestState(guest_CR6_0 );
1210 case 7: return offsetofPPCGuestState(guest_CR7_0 );
1211 default: vpanic("guestCR3offset(ppc)");
1215 /* Generate an IR sequence to do a popcount operation on the supplied
1216 * IRTemp, and return an IRTemp holding the result.
1218 static IRTemp gen_POPCOUNT ( IRTemp src )
1221 IRTemp old = IRTemp_INVALID;
1222 IRTemp nyu = IRTemp_INVALID;
1225 vassert(typeOfIRExpr(irsb->tyenv,mkexpr(src)) == Ity_I64);
1226 for (i = 0; i < 6; i++) {
1227 mask[i] = newTemp( Ity_I64 );
1230 assign( mask[0], mkU64( 0x5555555555555555ULL ) );
1231 assign( mask[1], mkU64( 0x3333333333333333ULL ) );
1232 assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
1233 assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
1234 assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
1235 assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
1237 for (i = 0; i < 6; i++) {
1238 nyu = newTemp( Ity_I64 );
1241 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
1243 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
1244 mkexpr( mask[i] ) ) ) );
1251 // ROTL(src32/64, rot_amt5/6)
1252 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1256 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1258 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1259 // rot = (src << rot_amt) | (src >> (64-rot_amt))
1260 mask = binop(Iop_And8, rot_amt, mkU8(63));
1261 rot = binop(Iop_Or64,
1262 binop(Iop_Shl64, src, mask),
1263 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1265 // rot = (src << rot_amt) | (src >> (32-rot_amt))
1266 mask = binop(Iop_And8, rot_amt, mkU8(31));
1267 rot = binop(Iop_Or32,
1268 binop(Iop_Shl32, src, mask),
1269 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
1271 /* Note: the MuxOX is not merely an optimisation; it's needed
1272 because otherwise the Shr is a shift by the word size when
1273 mask denotes zero. For rotates by immediates, a lot of
1274 this junk gets folded out. */
1275 return IRExpr_Mux0X( mask, /* zero rotate */ src,
1276 /* non-zero rotate */ rot );
1279 /* Standard effective address calc: (rA + rB) */
1280 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1282 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1285 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1288 /* Standard effective address calc: (rA + simm) */
1289 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1291 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1293 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
1294 mkSzExtendS16(ty, simm16));
1297 /* Standard effective address calc: (rA|0) */
1298 static IRExpr* ea_rAor0 ( UInt rA )
1300 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1303 return mkSzImm(ty, 0);
1309 /* Standard effective address calc: (rA|0) + rB */
1310 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1314 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1317 /* Standard effective address calc: (rA|0) + simm16 */
1318 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
1320 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1323 return mkSzExtendS16(ty, simm16);
1325 return ea_rA_simm( rA, simm16 );
1330 /* Align effective address */
1331 static IRExpr* addr_align( IRExpr* addr, UChar align )
1333 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1336 case 1: return addr; // byte aligned
1337 case 2: mask = ((Long)-1) << 1; break; // half-word aligned
1338 case 4: mask = ((Long)-1) << 2; break; // word aligned
1339 case 16: mask = ((Long)-1) << 4; break; // quad-word aligned
1341 vex_printf("addr_align: align = %u\n", align);
1342 vpanic("addr_align(ppc)");
1345 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1346 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
1350 /* Exit the trace if ADDR (intended to be a guest memory address) is
1351 not ALIGN-aligned, generating a request for a SIGBUS followed by a
1352 restart of the current insn. */
1353 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1355 vassert(align == 4 || align == 8);
1357 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1361 binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1364 IRConst_U64( guest_CIA_curr_instr )
1368 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1372 binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1375 IRConst_U32( guest_CIA_curr_instr )
1382 /* Generate AbiHints which mark points at which the ELF or PowerOpen
1383 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1384 N) becomes undefined. That is at function calls and returns. ELF
1385 ppc32 doesn't have this "feature" (how fortunate for it). nia is
1386 the address of the next instruction to be executed.
1388 static void make_redzone_AbiHint ( VexAbiInfo* vbi,
1389 IRTemp nia, HChar* who )
1391 Int szB = vbi->guest_stack_redzone_size;
1392 if (0) vex_printf("AbiHint: %s\n", who);
1396 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1397 stmt( IRStmt_AbiHint(
1398 binop(Iop_Sub64, getIReg(1), mkU64(szB)),
1403 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1404 stmt( IRStmt_AbiHint(
1405 binop(Iop_Sub32, getIReg(1), mkU32(szB)),
1414 /*------------------------------------------------------------*/
1415 /*--- Helpers for condition codes. ---*/
1416 /*------------------------------------------------------------*/
1418 /* Condition register layout.
1420 In the hardware, CR is laid out like this. The leftmost end is the
1421 most significant bit in the register; however the IBM documentation
1422 numbers the bits backwards for some reason.
1424 CR0 CR1 .......... CR6 CR7
1425 0 .. 3 ....................... 28 .. 31 (IBM bit numbering)
1426 31 28 3 0 (normal bit numbering)
1428 Each CR field is 4 bits: [<,>,==,SO]
1430 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1432 Indexing from BI to guest state:
1436 this references CR n:
1438 off==0 -> guest_CRn_321 >> 3
1439 off==1 -> guest_CRn_321 >> 2
1440 off==2 -> guest_CRn_321 >> 1
1441 off==3 -> guest_CRn_SO
1443 Bear in mind the only significant bit in guest_CRn_SO is bit 0
1444 (normal notation) and in guest_CRn_321 the significant bits are
1445 3, 2 and 1 (normal notation).
1448 static void putCR321 ( UInt cr, IRExpr* e )
1451 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1452 stmt( IRStmt_Put(guestCR321offset(cr), e) );
1455 static void putCR0 ( UInt cr, IRExpr* e )
1458 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1459 stmt( IRStmt_Put(guestCR0offset(cr), e) );
1462 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1465 return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1468 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1471 return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1474 /* Fetch the specified CR bit (as per IBM/hardware notation) and
1475 return it at the bottom of an I32; the top 31 bits are guaranteed
1477 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1483 /* Fetch the SO bit for this CR field */
1484 /* Note: And32 is redundant paranoia iff guest state only has 0
1485 or 1 in that slot. */
1486 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1488 /* Fetch the <, > or == bit for this CR field */
1489 return binop( Iop_And32,
1491 unop(Iop_8Uto32, getCR321(n)),
1492 mkU8(toUChar(3-off)) ),
1497 /* Dually, write the least significant bit of BIT to the specified CR
1498 bit. Indexing as per getCRbit. */
1499 static void putCRbit ( UInt bi, IRExpr* bit )
1503 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
1504 safe = binop(Iop_And32, bit, mkU32(1));
1509 /* This is the SO bit for this CR field */
1510 putCR0(n, unop(Iop_32to8, safe));
1513 vassert(off == 1 || off == 2 || off == 3);
1518 /* old value with field masked out */
1519 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
1520 mkU32(~(1 << off))),
1521 /* new value in the right place */
1522 binop(Iop_Shl32, safe, mkU8(toUChar(off)))
1529 /* Fetch the specified CR bit (as per IBM/hardware notation) and
1530 return it somewhere in an I32; it does not matter where, but
1531 whichever bit it is, all other bits are guaranteed to be zero. In
1532 other words, the I32-typed expression will be zero if the bit is
1533 zero and nonzero if the bit is 1. Write into *where the index
1534 of where the bit will be. */
1537 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
1543 /* Fetch the SO bit for this CR field */
1544 /* Note: And32 is redundant paranoia iff guest state only has 0
1545 or 1 in that slot. */
1547 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1549 /* Fetch the <, > or == bit for this CR field */
1551 return binop( Iop_And32,
1552 unop(Iop_8Uto32, getCR321(n)),
1553 mkU32(1 << (3-off)) );
1557 /* Set the CR0 flags following an arithmetic operation.
1558 (Condition Register CR0 Field Definition, PPC32 p60)
1560 static IRExpr* getXER_SO ( void );
1561 static void set_CR0 ( IRExpr* result )
1563 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
1564 typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
1566 putCR321( 0, unop(Iop_64to8,
1567 binop(Iop_CmpORD64S, result, mkU64(0))) );
1569 putCR321( 0, unop(Iop_32to8,
1570 binop(Iop_CmpORD32S, result, mkU32(0))) );
1572 putCR0( 0, getXER_SO() );
1576 /* Set the CR6 flags following an AltiVec compare operation. */
1577 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
1579 /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
1580 all_ones = (v[0] && v[1] && v[2] && v[3])
1581 all_zeros = ~(v[0] || v[1] || v[2] || v[3])
1583 IRTemp v0 = newTemp(Ity_V128);
1584 IRTemp v1 = newTemp(Ity_V128);
1585 IRTemp v2 = newTemp(Ity_V128);
1586 IRTemp v3 = newTemp(Ity_V128);
1587 IRTemp rOnes = newTemp(Ity_I8);
1588 IRTemp rZeros = newTemp(Ity_I8);
1590 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
1592 assign( v0, result );
1593 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
1594 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
1595 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
1597 assign( rZeros, unop(Iop_1Uto8,
1598 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1602 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
1603 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
1606 if (test_all_ones) {
1607 assign( rOnes, unop(Iop_1Uto8,
1608 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1611 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
1612 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
1614 putCR321( 6, binop(Iop_Or8,
1615 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)),
1616 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
1618 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
1620 putCR0( 6, mkU8(0) );
1625 /*------------------------------------------------------------*/
1626 /*--- Helpers for XER flags. ---*/
1627 /*------------------------------------------------------------*/
1629 static void putXER_SO ( IRExpr* e )
1632 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1633 so = binop(Iop_And8, e, mkU8(1));
1634 stmt( IRStmt_Put( OFFB_XER_SO, so ) );
1637 static void putXER_OV ( IRExpr* e )
1640 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1641 ov = binop(Iop_And8, e, mkU8(1));
1642 stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
1645 static void putXER_CA ( IRExpr* e )
1648 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1649 ca = binop(Iop_And8, e, mkU8(1));
1650 stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
1653 static void putXER_BC ( IRExpr* e )
1656 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1657 bc = binop(Iop_And8, e, mkU8(0x7F));
1658 stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
1661 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
1663 return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
1666 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
1668 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
1671 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
1673 return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
1676 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
1678 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
1681 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
1683 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
1684 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
1687 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
1689 return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
1692 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
1694 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
1695 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
1699 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and
1700 %XER.SO accordingly. */
1702 static void set_XER_OV_32( UInt op, IRExpr* res,
1703 IRExpr* argL, IRExpr* argR )
1707 vassert(op < PPCG_FLAG_OP_NUMBER);
1708 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32);
1709 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
1710 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
1712 # define INT32_MIN 0x80000000
1714 # define XOR2(_aa,_bb) \
1715 binop(Iop_Xor32,(_aa),(_bb))
1717 # define XOR3(_cc,_dd,_ee) \
1718 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
1720 # define AND3(_ff,_gg,_hh) \
1721 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
1724 unop(Iop_Not32, (_jj))
1727 case /* 0 */ PPCG_FLAG_OP_ADD:
1728 case /* 1 */ PPCG_FLAG_OP_ADDE:
1729 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */
1730 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
1732 = AND3( XOR3(argL,argR,mkU32(-1)),
1735 /* xer_ov can only be 0 or 1<<31 */
1737 = binop(Iop_Shr32, xer_ov, mkU8(31) );
1740 case /* 2 */ PPCG_FLAG_OP_DIVW:
1741 /* (argL == INT32_MIN && argR == -1) || argR == 0 */
1745 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
1746 binop(Iop_CmpEQ32, argR, mkU32(-1))
1748 binop(Iop_CmpEQ32, argR, mkU32(0) )
1751 = unop(Iop_1Uto32, xer_ov);
1754 case /* 3 */ PPCG_FLAG_OP_DIVWU:
1757 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
1760 case /* 4 */ PPCG_FLAG_OP_MULLW:
1761 /* OV true if result can't be represented in 32 bits
1762 i.e sHi != sign extension of sLo */
1763 t64 = newTemp(Ity_I64);
1764 assign( t64, binop(Iop_MullS32, argL, argR) );
1766 = binop( Iop_CmpNE32,
1767 unop(Iop_64HIto32, mkexpr(t64)),
1769 unop(Iop_64to32, mkexpr(t64)),
1773 = unop(Iop_1Uto32, xer_ov);
1776 case /* 5 */ PPCG_FLAG_OP_NEG:
1777 /* argL == INT32_MIN */
1780 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
1783 case /* 6 */ PPCG_FLAG_OP_SUBF:
1784 case /* 7 */ PPCG_FLAG_OP_SUBFC:
1785 case /* 8 */ PPCG_FLAG_OP_SUBFE:
1786 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
1788 = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
1789 XOR2(NOT(argL),res),
1791 /* xer_ov can only be 0 or 1<<31 */
1793 = binop(Iop_Shr32, xer_ov, mkU8(31) );
1797 vex_printf("set_XER_OV: op = %u\n", op);
1798 vpanic("set_XER_OV(ppc)");
1801 /* xer_ov MUST denote either 0 or 1, no other value allowed */
1802 putXER_OV( unop(Iop_32to8, xer_ov) );
1804 /* Update the summary overflow */
1805 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
1814 static void set_XER_OV_64( UInt op, IRExpr* res,
1815 IRExpr* argL, IRExpr* argR )
1818 vassert(op < PPCG_FLAG_OP_NUMBER);
1819 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64);
1820 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
1821 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
1823 # define INT64_MIN 0x8000000000000000ULL
1825 # define XOR2(_aa,_bb) \
1826 binop(Iop_Xor64,(_aa),(_bb))
1828 # define XOR3(_cc,_dd,_ee) \
1829 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
1831 # define AND3(_ff,_gg,_hh) \
1832 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
1835 unop(Iop_Not64, (_jj))
1838 case /* 0 */ PPCG_FLAG_OP_ADD:
1839 case /* 1 */ PPCG_FLAG_OP_ADDE:
1840 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */
1841 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
1843 = AND3( XOR3(argL,argR,mkU64(-1)),
1846 /* xer_ov can only be 0 or 1<<63 */
1848 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
1851 case /* 2 */ PPCG_FLAG_OP_DIVW:
1852 /* (argL == INT64_MIN && argR == -1) || argR == 0 */
1856 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
1857 binop(Iop_CmpEQ64, argR, mkU64(-1))
1859 binop(Iop_CmpEQ64, argR, mkU64(0) )
1863 case /* 3 */ PPCG_FLAG_OP_DIVWU:
1866 = binop(Iop_CmpEQ64, argR, mkU64(0));
1869 case /* 4 */ PPCG_FLAG_OP_MULLW: {
1870 /* OV true if result can't be represented in 64 bits
1871 i.e sHi != sign extension of sLo */
1873 = binop( Iop_CmpNE32,
1874 unop(Iop_64HIto32, res),
1876 unop(Iop_64to32, res),
1882 case /* 5 */ PPCG_FLAG_OP_NEG:
1883 /* argL == INT64_MIN */
1885 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
1888 case /* 6 */ PPCG_FLAG_OP_SUBF:
1889 case /* 7 */ PPCG_FLAG_OP_SUBFC:
1890 case /* 8 */ PPCG_FLAG_OP_SUBFE:
1891 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
1893 = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
1894 XOR2(NOT(argL),res),
1896 /* xer_ov can only be 0 or 1<<63 */
1898 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
1902 vex_printf("set_XER_OV: op = %u\n", op);
1903 vpanic("set_XER_OV(ppc64)");
1906 /* xer_ov MUST denote either 0 or 1, no other value allowed */
1907 putXER_OV( unop(Iop_1Uto8, xer_ov) );
1909 /* Update the summary overflow */
1910 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
1919 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
1920 IRExpr* argL, IRExpr* argR )
1923 set_XER_OV_32( op, res, argL, argR );
1925 set_XER_OV_64( op, res, argL, argR );
1930 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
1931 value being OLDCA. Set %XER.CA accordingly. */
1933 static void set_XER_CA_32 ( UInt op, IRExpr* res,
1934 IRExpr* argL, IRExpr* argR, IRExpr* oldca )
1937 vassert(op < PPCG_FLAG_OP_NUMBER);
1938 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32);
1939 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
1940 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
1941 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
1943 /* Incoming oldca is assumed to hold the values 0 or 1 only. This
1944 seems reasonable given that it's always generated by
1945 getXER_CA32(), which masks it accordingly. In any case it being
1946 0 or 1 is an invariant of the ppc guest state representation;
1947 if it has any other value, that invariant has been violated. */
1950 case /* 0 */ PPCG_FLAG_OP_ADD:
1953 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
1956 case /* 1 */ PPCG_FLAG_OP_ADDE:
1957 /* res <u argL || (old_ca==1 && res==argL) */
1960 binop(Iop_CmpLT32U, res, argL),
1962 binop(Iop_CmpEQ32, oldca, mkU32(1)),
1963 binop(Iop_CmpEQ32, res, argL)
1967 = unop(Iop_1Uto32, xer_ca);
1970 case /* 8 */ PPCG_FLAG_OP_SUBFE:
1971 /* res <u argR || (old_ca==1 && res==argR) */
1974 binop(Iop_CmpLT32U, res, argR),
1976 binop(Iop_CmpEQ32, oldca, mkU32(1)),
1977 binop(Iop_CmpEQ32, res, argR)
1981 = unop(Iop_1Uto32, xer_ca);
1984 case /* 7 */ PPCG_FLAG_OP_SUBFC:
1985 case /* 9 */ PPCG_FLAG_OP_SUBFI:
1988 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
1991 case /* 10 */ PPCG_FLAG_OP_SRAW:
1992 /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
1993 If it is <= 31, behave like SRAWI; else XER.CA is the sign
1995 /* This term valid for shift amount < 32 only */
1999 binop(Iop_Sar32, argL, mkU8(31)),
2003 binop(Iop_Shl32, mkU32(1),
2004 unop(Iop_32to8,argR)),
2010 /* shift amt > 31 ? */
2011 unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)),
2012 /* no -- be like srawi */
2013 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))),
2014 /* yes -- get sign bit of argL */
2015 binop(Iop_Shr32, argL, mkU8(31))
2019 case /* 11 */ PPCG_FLAG_OP_SRAWI:
2020 /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2021 0. Since the shift amount is known to be in the range
2022 0 .. 31 inclusive the following seems viable:
2023 xer.ca == 1 iff the following is nonzero:
2024 (argL >>s 31) -- either all 0s or all 1s
2025 & (argL & (1<<argR)-1) -- the stuff shifted out */
2029 binop(Iop_Sar32, argL, mkU8(31)),
2033 binop(Iop_Shl32, mkU32(1),
2034 unop(Iop_32to8,argR)),
2039 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2043 vex_printf("set_XER_CA: op = %u\n", op);
2044 vpanic("set_XER_CA(ppc)");
2047 /* xer_ca MUST denote either 0 or 1, no other value allowed */
2048 putXER_CA( unop(Iop_32to8, xer_ca) );
2051 static void set_XER_CA_64 ( UInt op, IRExpr* res,
2052 IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2055 vassert(op < PPCG_FLAG_OP_NUMBER);
2056 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64);
2057 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
2058 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
2059 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
2061 /* Incoming oldca is assumed to hold the values 0 or 1 only. This
2062 seems reasonable given that it's always generated by
2063 getXER_CA32(), which masks it accordingly. In any case it being
2064 0 or 1 is an invariant of the ppc guest state representation;
2065 if it has any other value, that invariant has been violated. */
2068 case /* 0 */ PPCG_FLAG_OP_ADD:
2071 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2074 case /* 1 */ PPCG_FLAG_OP_ADDE:
2075 /* res <u argL || (old_ca==1 && res==argL) */
2078 binop(Iop_CmpLT64U, res, argL),
2080 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2081 binop(Iop_CmpEQ64, res, argL)
2085 = unop(Iop_1Uto32, xer_ca);
2088 case /* 8 */ PPCG_FLAG_OP_SUBFE:
2089 /* res <u argR || (old_ca==1 && res==argR) */
2092 binop(Iop_CmpLT64U, res, argR),
2094 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2095 binop(Iop_CmpEQ64, res, argR)
2099 = unop(Iop_1Uto32, xer_ca);
2102 case /* 7 */ PPCG_FLAG_OP_SUBFC:
2103 case /* 9 */ PPCG_FLAG_OP_SUBFI:
2106 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2110 case /* 10 */ PPCG_FLAG_OP_SRAW:
2111 /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2112 If it is <= 31, behave like SRAWI; else XER.CA is the sign
2114 /* This term valid for shift amount < 31 only */
2119 binop(Iop_Sar64, argL, mkU8(31)),
2123 binop(Iop_Shl64, mkU64(1),
2124 unop(Iop_64to8,argR)),
2130 /* shift amt > 31 ? */
2131 unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(31), argR)),
2132 /* no -- be like srawi */
2133 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
2134 /* yes -- get sign bit of argL */
2135 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
2139 case /* 11 */ PPCG_FLAG_OP_SRAWI:
2140 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2141 Since the shift amount is known to be in the range 0 .. 31
2142 inclusive the following seems viable:
2143 xer.ca == 1 iff the following is nonzero:
2144 (argL >>s 31) -- either all 0s or all 1s
2145 & (argL & (1<<argR)-1) -- the stuff shifted out */
2150 binop(Iop_Sar64, argL, mkU8(31)),
2154 binop(Iop_Shl64, mkU64(1),
2155 unop(Iop_64to8,argR)),
2160 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2164 case /* 12 */ PPCG_FLAG_OP_SRAD:
2165 /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2166 If it is <= 63, behave like SRADI; else XER.CA is the sign
2168 /* This term valid for shift amount < 63 only */
2173 binop(Iop_Sar64, argL, mkU8(63)),
2177 binop(Iop_Shl64, mkU64(1),
2178 unop(Iop_64to8,argR)),
2184 /* shift amt > 63 ? */
2185 unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)),
2186 /* no -- be like sradi */
2187 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
2188 /* yes -- get sign bit of argL */
2189 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
2194 case /* 13 */ PPCG_FLAG_OP_SRADI:
2195 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2196 Since the shift amount is known to be in the range 0 .. 63
2197 inclusive, the following seems viable:
2198 xer.ca == 1 iff the following is nonzero:
2199 (argL >>s 63) -- either all 0s or all 1s
2200 & (argL & (1<<argR)-1) -- the stuff shifted out */
2205 binop(Iop_Sar64, argL, mkU8(63)),
2209 binop(Iop_Shl64, mkU64(1),
2210 unop(Iop_64to8,argR)),
2215 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2219 vex_printf("set_XER_CA: op = %u\n", op);
2220 vpanic("set_XER_CA(ppc64)");
2223 /* xer_ca MUST denote either 0 or 1, no other value allowed */
2224 putXER_CA( unop(Iop_32to8, xer_ca) );
2227 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
2228 IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2231 set_XER_CA_32( op, res, argL, argR, oldca );
2233 set_XER_CA_64( op, res, argL, argR, oldca );
2238 /*------------------------------------------------------------*/
2239 /*--- Read/write to guest-state --- */
2240 /*------------------------------------------------------------*/
2242 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
2244 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2246 case PPC_GST_SPRG3_RO:
2247 return IRExpr_Get( OFFB_SPRG3_RO, ty );
2250 return IRExpr_Get( OFFB_CIA, ty );
2253 return IRExpr_Get( OFFB_LR, ty );
2256 return IRExpr_Get( OFFB_CTR, ty );
2258 case PPC_GST_VRSAVE:
2259 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
2262 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
2263 mkU32(MASK_VSCR_VALID));
2266 /* Synthesise the entire CR into a single word. Expensive. */
2267 # define FIELD(_n) \
2271 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
2272 binop(Iop_And8, getCR0(_n), mkU8(1)) \
2275 mkU8(4 * (7-(_n))) \
2277 return binop(Iop_Or32,
2279 binop(Iop_Or32, FIELD(0), FIELD(1)),
2280 binop(Iop_Or32, FIELD(2), FIELD(3))
2283 binop(Iop_Or32, FIELD(4), FIELD(5)),
2284 binop(Iop_Or32, FIELD(6), FIELD(7))
2291 return binop(Iop_Or32,
2293 binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
2294 binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
2296 binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
2300 vex_printf("getGST(ppc): reg = %u", reg);
2301 vpanic("getGST(ppc)");
2305 /* Get a masked word from the given reg */
2306 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
2308 IRTemp val = newTemp(Ity_I32);
2309 vassert( reg < PPC_GST_MAX );
2313 case PPC_GST_FPSCR: {
2314 /* Vex-generated code expects the FPSCR to be set as follows:
2315 all exceptions masked, round-to-nearest.
2316 This corresponds to a FPSCR value of 0x0. */
2318 /* We're only keeping track of the rounding mode,
2319 so if the mask isn't asking for this, just return 0x0 */
2320 if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
2321 assign( val, IRExpr_Get( OFFB_FPROUND, Ity_I32 ) );
2323 assign( val, mkU32(0x0) );
2329 vex_printf("getGST_masked(ppc): reg = %u", reg);
2330 vpanic("getGST_masked(ppc)");
2333 if (mask != 0xFFFFFFFF) {
2334 return binop(Iop_And32, mkexpr(val), mkU32(mask));
2340 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
2341 and return it at the bottom of an I32; the top 27 bits are
2342 guaranteed to be zero. */
2343 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
2348 vassert( reg < PPC_GST_MAX );
2356 return binop(Iop_Or32,
2358 binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
2359 binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
2360 binop( Iop_Shl32, getXER_CA32(), mkU8(1)));
2365 return getGST_masked( reg, mask );
2367 return binop(Iop_Shr32,
2368 getGST_masked( reg, mask ),
2369 mkU8(toUChar( shft )));
2373 static void putGST ( PPC_GST reg, IRExpr* src )
2375 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2376 IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
2377 vassert( reg < PPC_GST_MAX );
2379 case PPC_GST_IP_AT_SYSCALL:
2380 vassert( ty_src == ty );
2381 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
2384 vassert( ty_src == ty );
2385 stmt( IRStmt_Put( OFFB_CIA, src ) );
2388 vassert( ty_src == ty );
2389 stmt( IRStmt_Put( OFFB_LR, src ) );
2392 vassert( ty_src == ty );
2393 stmt( IRStmt_Put( OFFB_CTR, src ) );
2395 case PPC_GST_VRSAVE:
2396 vassert( ty_src == Ity_I32 );
2397 stmt( IRStmt_Put( OFFB_VRSAVE,src));
2400 vassert( ty_src == Ity_I32 );
2401 stmt( IRStmt_Put( OFFB_VSCR,
2402 binop(Iop_And32, src,
2403 mkU32(MASK_VSCR_VALID)) ) );
2406 vassert( ty_src == Ity_I32 );
2407 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
2408 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
2409 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
2410 putXER_BC( unop(Iop_32to8, src) );
2413 case PPC_GST_EMWARN:
2414 vassert( ty_src == Ity_I32 );
2415 stmt( IRStmt_Put( OFFB_EMWARN,src) );
2418 case PPC_GST_TISTART:
2419 vassert( ty_src == ty );
2420 stmt( IRStmt_Put( OFFB_TISTART, src) );
2424 vassert( ty_src == ty );
2425 stmt( IRStmt_Put( OFFB_TILEN, src) );
2429 vex_printf("putGST(ppc): reg = %u", reg);
2430 vpanic("putGST(ppc)");
2434 /* Write masked src to the given reg */
2435 static void putGST_masked ( PPC_GST reg, IRExpr* src, UInt mask )
2437 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2438 vassert( reg < PPC_GST_MAX );
2439 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
2442 case PPC_GST_FPSCR: {
2443 /* Allow writes to Rounding Mode */
2444 if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
2445 /* construct new fpround from new and old values as per mask:
2446 new fpround = (src & (3 & mask)) | (fpround & (3 & ~mask)) */
2452 binop(Iop_And32, src, mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & mask)),
2455 IRExpr_Get(OFFB_FPROUND,Ity_I32),
2456 mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & ~mask)
2463 /* Give EmWarn for attempted writes to:
2464 - Exception Controls
2467 if (mask & 0xFC) { // Exception Control, Non-IEE mode
2468 VexEmWarn ew = EmWarn_PPCexns;
2470 /* If any of the src::exception_control bits are actually set,
2471 side-exit to the next insn, reporting the warning,
2472 so that Valgrind's dispatcher sees the warning. */
2473 putGST( PPC_GST_EMWARN, mkU32(ew) );
2476 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)),
2478 mkSzConst( ty, nextInsnAddr()) ));
2481 /* Ignore all other writes */
2486 vex_printf("putGST_masked(ppc): reg = %u", reg);
2487 vpanic("putGST_masked(ppc)");
2491 /* Write the least significant nibble of src to the specified
2492 REG[FLD] (as per IBM/hardware notation). */
2493 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
2497 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
2499 vassert( reg < PPC_GST_MAX );
2506 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src)));
2507 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
2512 putGST_masked( reg, src, mask );
2515 binop(Iop_Shl32, src, mkU8(toUChar(shft))),
2521 /*------------------------------------------------------------*/
2522 /* Helpers for VSX instructions that do floating point
2523 * operations and need to determine if a src contains a
2526 *------------------------------------------------------------*/
2528 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
2529 #define FP_FRAC_PART(x) binop( Iop_And64, \
2531 mkU64( NONZERO_FRAC_MASK ) )
2533 // Returns exponent part of floating point as I32
2534 static IRExpr * fp_exp_part(IRTemp src)
2538 exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
2540 mkU8( 20 ) ), mkU32( 0x7ff ) );
2542 exp = unop( Iop_64to32,
2544 binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
2550 // Infinity: exp = 7ff and fraction is zero; s = 0/1
2551 static IRExpr * is_Inf(IRTemp src)
2553 IRExpr * Inf_exp, * hi32, * low32;
2554 IRTemp frac_part = newTemp(Ity_I64);
2556 assign( frac_part, FP_FRAC_PART(src) );
2557 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src ), mkU32( 0x7ff ) );
2558 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
2559 low32 = unop( Iop_64to32, mkexpr( frac_part ) );
2560 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
2564 // Zero: exp is zero and fraction is zero; s = 0/1
2565 static IRExpr * is_Zero(IRTemp src)
2567 #define SIGN_MASK 0x7fffffffffffffffULL
2568 IRExpr * hi32, * low32;
2569 IRTemp sign_less_part = newTemp(Ity_I64);
2571 assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
2572 hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
2573 low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
2574 return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
2578 /* SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
2579 * QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
2580 * This function returns an IRExpr value of '1' for any type of NaN.
2582 static IRExpr * is_NaN(IRTemp src)
2584 IRExpr * NaN_exp, * hi32, * low32;
2585 IRTemp frac_part = newTemp(Ity_I64);
2587 assign( frac_part, FP_FRAC_PART(src) );
2588 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
2589 low32 = unop( Iop_64to32, mkexpr( frac_part ) );
2590 NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src ), mkU32( 0x7ffULL ) );
2592 return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
2597 /*------------------------------------------------------------*/
2598 /*--- Integer Instruction Translation --- */
2599 /*------------------------------------------------------------*/
2602 Integer Arithmetic Instructions
2604 static Bool dis_int_arith ( UInt theInstr )
2606 /* D-Form, XO-Form */
2607 UChar opc1 = ifieldOPC(theInstr);
2608 UChar rD_addr = ifieldRegDS(theInstr);
2609 UChar rA_addr = ifieldRegA(theInstr);
2610 UInt uimm16 = ifieldUIMM16(theInstr);
2611 UChar rB_addr = ifieldRegB(theInstr);
2612 UChar flag_OE = ifieldBIT10(theInstr);
2613 UInt opc2 = ifieldOPClo9(theInstr);
2614 UChar flag_rC = ifieldBIT0(theInstr);
2616 Long simm16 = extend_s_16to64(uimm16);
2617 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2618 IRTemp rA = newTemp(ty);
2619 IRTemp rB = newTemp(ty);
2620 IRTemp rD = newTemp(ty);
2624 assign( rA, getIReg(rA_addr) );
2625 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB
2629 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351
2630 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2631 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2632 mkSzExtendS16(ty, uimm16) ) );
2633 set_XER_CA( ty, PPCG_FLAG_OP_ADD,
2634 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2635 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2638 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
2639 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2640 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2641 mkSzExtendS16(ty, uimm16) ) );
2642 set_XER_CA( ty, PPCG_FLAG_OP_ADD,
2643 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2644 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2645 do_rc = True; // Always record to CR
2649 case 0x0E: // addi (Add Immediate, PPC32 p350)
2650 // li rD,val == addi rD,0,val
2651 // la disp(rA) == addi rD,rA,disp
2652 if ( rA_addr == 0 ) {
2653 DIP("li r%u,%d\n", rD_addr, (Int)simm16);
2654 assign( rD, mkSzExtendS16(ty, uimm16) );
2656 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2657 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2658 mkSzExtendS16(ty, uimm16) ) );
2662 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353)
2663 // lis rD,val == addis rD,0,val
2664 if ( rA_addr == 0 ) {
2665 DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
2666 assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
2668 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
2669 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2670 mkSzExtendS32(ty, uimm16 << 16) ) );
2674 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490)
2675 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2677 assign( rD, unop(Iop_128to64,
2678 binop(Iop_MullS64, mkexpr(rA),
2679 mkSzExtendS16(ty, uimm16))) );
2681 assign( rD, unop(Iop_64to32,
2682 binop(Iop_MullS32, mkexpr(rA),
2683 mkSzExtendS16(ty, uimm16))) );
2686 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540)
2687 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2689 assign( rD, binop( mkSzOp(ty, Iop_Sub8),
2690 mkSzExtendS16(ty, uimm16),
2692 set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
2693 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2694 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2699 do_rc = True; // All below record to CR
2702 case 0x10A: // add (Add, PPC32 p347)
2703 DIP("add%s%s r%u,r%u,r%u\n",
2704 flag_OE ? "o" : "", flag_rC ? ".":"",
2705 rD_addr, rA_addr, rB_addr);
2706 assign( rD, binop( mkSzOp(ty, Iop_Add8),
2707 mkexpr(rA), mkexpr(rB) ) );
2709 set_XER_OV( ty, PPCG_FLAG_OP_ADD,
2710 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2714 case 0x00A: // addc (Add Carrying, PPC32 p348)
2715 DIP("addc%s%s r%u,r%u,r%u\n",
2716 flag_OE ? "o" : "", flag_rC ? ".":"",
2717 rD_addr, rA_addr, rB_addr);
2718 assign( rD, binop( mkSzOp(ty, Iop_Add8),
2719 mkexpr(rA), mkexpr(rB)) );
2720 set_XER_CA( ty, PPCG_FLAG_OP_ADD,
2721 mkexpr(rD), mkexpr(rA), mkexpr(rB),
2722 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2724 set_XER_OV( ty, PPCG_FLAG_OP_ADD,
2725 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2729 case 0x08A: { // adde (Add Extended, PPC32 p349)
2730 IRTemp old_xer_ca = newTemp(ty);
2731 DIP("adde%s%s r%u,r%u,r%u\n",
2732 flag_OE ? "o" : "", flag_rC ? ".":"",
2733 rD_addr, rA_addr, rB_addr);
2734 // rD = rA + rB + XER[CA]
2735 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
2736 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2737 binop( mkSzOp(ty, Iop_Add8),
2738 mkexpr(rB), mkexpr(old_xer_ca))) );
2739 set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
2740 mkexpr(rD), mkexpr(rA), mkexpr(rB),
2741 mkexpr(old_xer_ca) );
2743 set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
2744 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2749 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354)
2750 IRTemp old_xer_ca = newTemp(ty);
2753 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
2756 DIP("addme%s%s r%u,r%u,r%u\n",
2757 flag_OE ? "o" : "", flag_rC ? ".":"",
2758 rD_addr, rA_addr, rB_addr);
2759 // rD = rA + (-1) + XER[CA]
2760 // => Just another form of adde
2761 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
2762 min_one = mkSzImm(ty, (Long)-1);
2763 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2764 binop( mkSzOp(ty, Iop_Add8),
2765 min_one, mkexpr(old_xer_ca)) ));
2766 set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
2767 mkexpr(rD), mkexpr(rA), min_one,
2768 mkexpr(old_xer_ca) );
2770 set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
2771 mkexpr(rD), mkexpr(rA), min_one );
2776 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355)
2777 IRTemp old_xer_ca = newTemp(ty);
2779 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
2782 DIP("addze%s%s r%u,r%u,r%u\n",
2783 flag_OE ? "o" : "", flag_rC ? ".":"",
2784 rD_addr, rA_addr, rB_addr);
2785 // rD = rA + (0) + XER[CA]
2786 // => Just another form of adde
2787 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
2788 assign( rD, binop( mkSzOp(ty, Iop_Add8),
2789 mkexpr(rA), mkexpr(old_xer_ca)) );
2790 set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
2791 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
2792 mkexpr(old_xer_ca) );
2794 set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
2795 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
2800 case 0x1EB: // divw (Divide Word, PPC32 p388)
2801 DIP("divw%s%s r%u,r%u,r%u\n",
2802 flag_OE ? "o" : "", flag_rC ? ".":"",
2803 rD_addr, rA_addr, rB_addr);
2806 XER settings are mode independent, and reflect the
2807 overflow of the low-order 32bit result
2808 CR0[LT|GT|EQ] are undefined if flag_rC && mode64
2810 /* rD[hi32] are undefined: setting them to sign of lo32
2811 - makes set_CR0 happy */
2812 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
2813 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) );
2814 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
2817 set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
2818 mkexpr(rD), dividend, divisor );
2821 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
2823 set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
2824 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2828 if (0x8000_0000 / -1) or (x / 0)
2829 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
2830 => But _no_ exception raised. */
2833 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389)
2834 DIP("divwu%s%s r%u,r%u,r%u\n",
2835 flag_OE ? "o" : "", flag_rC ? ".":"",
2836 rD_addr, rA_addr, rB_addr);
2839 XER settings are mode independent, and reflect the
2840 overflow of the low-order 32bit result
2841 CR0[LT|GT|EQ] are undefined if flag_rC && mode64
2843 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
2844 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) );
2845 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
2848 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
2849 mkexpr(rD), dividend, divisor );
2852 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
2854 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
2855 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2858 /* Note: ditto comment divw, for (x / 0) */
2861 case 0x04B: // mulhw (Multiply High Word, PPC32 p488)
2863 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
2866 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
2867 rD_addr, rA_addr, rB_addr);
2869 /* rD[hi32] are undefined: setting them to sign of lo32
2870 - makes set_CR0 happy */
2871 assign( rD, binop(Iop_Sar64,
2873 mk64lo32Sto64( mkexpr(rA) ),
2874 mk64lo32Sto64( mkexpr(rB) )),
2877 assign( rD, unop(Iop_64HIto32,
2879 mkexpr(rA), mkexpr(rB))) );
2883 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489)
2885 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
2888 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
2889 rD_addr, rA_addr, rB_addr);
2891 /* rD[hi32] are undefined: setting them to sign of lo32
2892 - makes set_CR0 happy */
2893 assign( rD, binop(Iop_Sar64,
2895 mk64lo32Uto64( mkexpr(rA) ),
2896 mk64lo32Uto64( mkexpr(rB) ) ),
2899 assign( rD, unop(Iop_64HIto32,
2901 mkexpr(rA), mkexpr(rB))) );
2905 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491)
2906 DIP("mullw%s%s r%u,r%u,r%u\n",
2907 flag_OE ? "o" : "", flag_rC ? ".":"",
2908 rD_addr, rA_addr, rB_addr);
2910 /* rD[hi32] are undefined: setting them to sign of lo32
2911 - set_XER_OV() and set_CR0() depend on this */
2912 IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
2913 IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
2914 assign( rD, binop(Iop_MullS32, a, b) );
2916 set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
2918 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
2921 assign( rD, unop(Iop_64to32,
2923 mkexpr(rA), mkexpr(rB))) );
2925 set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
2926 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2931 case 0x068: // neg (Negate, PPC32 p493)
2933 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
2936 DIP("neg%s%s r%u,r%u\n",
2937 flag_OE ? "o" : "", flag_rC ? ".":"",
2940 assign( rD, binop( mkSzOp(ty, Iop_Add8),
2941 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
2944 set_XER_OV( ty, PPCG_FLAG_OP_NEG,
2945 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2949 case 0x028: // subf (Subtract From, PPC32 p537)
2950 DIP("subf%s%s r%u,r%u,r%u\n",
2951 flag_OE ? "o" : "", flag_rC ? ".":"",
2952 rD_addr, rA_addr, rB_addr);
2954 assign( rD, binop( mkSzOp(ty, Iop_Sub8),
2955 mkexpr(rB), mkexpr(rA)) );
2957 set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
2958 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2962 case 0x008: // subfc (Subtract from Carrying, PPC32 p538)
2963 DIP("subfc%s%s r%u,r%u,r%u\n",
2964 flag_OE ? "o" : "", flag_rC ? ".":"",
2965 rD_addr, rA_addr, rB_addr);
2967 assign( rD, binop( mkSzOp(ty, Iop_Sub8),
2968 mkexpr(rB), mkexpr(rA)) );
2969 set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
2970 mkexpr(rD), mkexpr(rA), mkexpr(rB),
2971 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2973 set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
2974 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2978 case 0x088: {// subfe (Subtract from Extended, PPC32 p539)
2979 IRTemp old_xer_ca = newTemp(ty);
2980 DIP("subfe%s%s r%u,r%u,r%u\n",
2981 flag_OE ? "o" : "", flag_rC ? ".":"",
2982 rD_addr, rA_addr, rB_addr);
2983 // rD = (log not)rA + rB + XER[CA]
2984 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
2985 assign( rD, binop( mkSzOp(ty, Iop_Add8),
2986 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
2987 binop( mkSzOp(ty, Iop_Add8),
2988 mkexpr(rB), mkexpr(old_xer_ca))) );
2989 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
2990 mkexpr(rD), mkexpr(rA), mkexpr(rB),
2991 mkexpr(old_xer_ca) );
2993 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
2994 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2999 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541)
3000 IRTemp old_xer_ca = newTemp(ty);
3003 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
3006 DIP("subfme%s%s r%u,r%u\n",
3007 flag_OE ? "o" : "", flag_rC ? ".":"",
3009 // rD = (log not)rA + (-1) + XER[CA]
3010 // => Just another form of subfe
3011 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3012 min_one = mkSzImm(ty, (Long)-1);
3013 assign( rD, binop( mkSzOp(ty, Iop_Add8),
3014 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3015 binop( mkSzOp(ty, Iop_Add8),
3016 min_one, mkexpr(old_xer_ca))) );
3017 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3018 mkexpr(rD), mkexpr(rA), min_one,
3019 mkexpr(old_xer_ca) );
3021 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3022 mkexpr(rD), mkexpr(rA), min_one );
3027 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542)
3028 IRTemp old_xer_ca = newTemp(ty);
3030 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
3033 DIP("subfze%s%s r%u,r%u\n",
3034 flag_OE ? "o" : "", flag_rC ? ".":"",
3036 // rD = (log not)rA + (0) + XER[CA]
3037 // => Just another form of subfe
3038 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3039 assign( rD, binop( mkSzOp(ty, Iop_Add8),
3040 unop( mkSzOp(ty, Iop_Not8),
3041 mkexpr(rA)), mkexpr(old_xer_ca)) );
3042 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3043 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3044 mkexpr(old_xer_ca) );
3046 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3047 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3053 /* 64bit Arithmetic */
3054 case 0x49: // mulhd (Multiply High DWord, PPC64 p539)
3056 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
3059 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3060 rD_addr, rA_addr, rB_addr);
3061 assign( rD, unop(Iop_128HIto64,
3063 mkexpr(rA), mkexpr(rB))) );
3067 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540)
3069 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
3072 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3073 rD_addr, rA_addr, rB_addr);
3074 assign( rD, unop(Iop_128HIto64,
3076 mkexpr(rA), mkexpr(rB))) );
3079 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543)
3080 DIP("mulld%s%s r%u,r%u,r%u\n",
3081 flag_OE ? "o" : "", flag_rC ? ".":"",
3082 rD_addr, rA_addr, rB_addr);
3083 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
3085 set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3086 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3090 case 0x1E9: // divd (Divide DWord, PPC64 p419)
3091 DIP("divd%s%s r%u,r%u,r%u\n",
3092 flag_OE ? "o" : "", flag_rC ? ".":"",
3093 rD_addr, rA_addr, rB_addr);
3094 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
3096 set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3097 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3101 if (0x8000_0000_0000_0000 / -1) or (x / 0)
3102 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3103 => But _no_ exception raised. */
3105 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
3106 DIP("divdu%s%s r%u,r%u,r%u\n",
3107 flag_OE ? "o" : "", flag_rC ? ".":"",
3108 rD_addr, rA_addr, rB_addr);
3109 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
3111 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3112 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3115 /* Note: ditto comment divd, for (x / 0) */
3118 vex_printf("dis_int_arith(ppc)(opc2)\n");
3124 vex_printf("dis_int_arith(ppc)(opc1)\n");
3128 putIReg( rD_addr, mkexpr(rD) );
3130 if (do_rc && flag_rC) {
3131 set_CR0( mkexpr(rD) );
3139 Integer Compare Instructions
3141 static Bool dis_int_cmp ( UInt theInstr )
3143 /* D-Form, X-Form */
3144 UChar opc1 = ifieldOPC(theInstr);
3145 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
3146 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) );
3147 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) );
3148 UChar rA_addr = ifieldRegA(theInstr);
3149 UInt uimm16 = ifieldUIMM16(theInstr);
3150 UChar rB_addr = ifieldRegB(theInstr);
3151 UInt opc2 = ifieldOPClo10(theInstr);
3152 UChar b0 = ifieldBIT0(theInstr);
3154 IRType ty = mode64 ? Ity_I64 : Ity_I32;
3155 IRExpr *a = getIReg(rA_addr);
3158 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit.
3159 vex_printf("dis_int_cmp(ppc)(flag_L)\n");
3164 vex_printf("dis_int_cmp(ppc)(b22)\n");
3169 case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
3170 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
3171 (Int)extend_s_16to32(uimm16));
3172 b = mkSzExtendS16( ty, uimm16 );
3174 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
3176 a = mkNarrowTo32( ty, a );
3177 b = mkNarrowTo32( ty, b );
3178 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
3180 putCR0( crfD, getXER_SO() );
3183 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
3184 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
3185 b = mkSzImm( ty, uimm16 );
3187 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
3189 a = mkNarrowTo32( ty, a );
3190 b = mkNarrowTo32( ty, b );
3191 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
3193 putCR0( crfD, getXER_SO() );
3199 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
3202 b = getIReg(rB_addr);
3205 case 0x000: // cmp (Compare, PPC32 p367)
3206 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
3207 /* Comparing a reg with itself produces a result which
3208 doesn't depend on the contents of the reg. Therefore
3209 remove the false dependency, which has been known to cause
3210 memcheck to produce false errors. */
3211 if (rA_addr == rB_addr)
3212 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
3213 ? mkU64(0) : mkU32(0);
3215 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
3217 a = mkNarrowTo32( ty, a );
3218 b = mkNarrowTo32( ty, b );
3219 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
3221 putCR0( crfD, getXER_SO() );
3224 case 0x020: // cmpl (Compare Logical, PPC32 p369)
3225 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
3226 /* Comparing a reg with itself produces a result which
3227 doesn't depend on the contents of the reg. Therefore
3228 remove the false dependency, which has been known to cause
3229 memcheck to produce false errors. */
3230 if (rA_addr == rB_addr)
3231 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
3232 ? mkU64(0) : mkU32(0);
3234 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
3236 a = mkNarrowTo32( ty, a );
3237 b = mkNarrowTo32( ty, b );
3238 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
3240 putCR0( crfD, getXER_SO() );
3244 vex_printf("dis_int_cmp(ppc)(opc2)\n");
3250 vex_printf("dis_int_cmp(ppc)(opc1)\n");
3259 Integer Logical Instructions
3261 static Bool dis_int_logic ( UInt theInstr )
3263 /* D-Form, X-Form */
3264 UChar opc1 = ifieldOPC(theInstr);
3265 UChar rS_addr = ifieldRegDS(theInstr);
3266 UChar rA_addr = ifieldRegA(theInstr);
3267 UInt uimm16 = ifieldUIMM16(theInstr);
3268 UChar rB_addr = ifieldRegB(theInstr);
3269 UInt opc2 = ifieldOPClo10(theInstr);
3270 UChar flag_rC = ifieldBIT0(theInstr);
3272 IRType ty = mode64 ? Ity_I64 : Ity_I32;
3273 IRTemp rS = newTemp(ty);
3274 IRTemp rA = newTemp(ty);
3275 IRTemp rB = newTemp(ty);
3279 assign( rS, getIReg(rS_addr) );
3280 assign( rB, getIReg(rB_addr) );
3283 case 0x1C: // andi. (AND Immediate, PPC32 p358)
3284 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3285 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3286 mkSzImm(ty, uimm16)) );
3287 do_rc = True; // Always record to CR
3291 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
3292 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3293 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3294 mkSzImm(ty, uimm16 << 16)) );
3295 do_rc = True; // Always record to CR
3299 case 0x18: // ori (OR Immediate, PPC32 p497)
3300 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3301 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3302 mkSzImm(ty, uimm16)) );
3305 case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
3306 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3307 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3308 mkSzImm(ty, uimm16 << 16)) );
3311 case 0x1A: // xori (XOR Immediate, PPC32 p550)
3312 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3313 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
3314 mkSzImm(ty, uimm16)) );
3317 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
3318 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3319 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
3320 mkSzImm(ty, uimm16 << 16)) );
3325 do_rc = True; // All below record to CR
3328 case 0x01C: // and (AND, PPC32 p356)
3329 DIP("and%s r%u,r%u,r%u\n",
3330 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3331 assign(rA, binop( mkSzOp(ty, Iop_And8),
3332 mkexpr(rS), mkexpr(rB)));
3335 case 0x03C: // andc (AND with Complement, PPC32 p357)
3336 DIP("andc%s r%u,r%u,r%u\n",
3337 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3338 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3339 unop( mkSzOp(ty, Iop_Not8),
3343 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
3346 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
3349 DIP("cntlzw%s r%u,r%u\n",
3350 flag_rC ? ".":"", rA_addr, rS_addr);
3352 // mode64: count in low word only
3353 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
3355 // Iop_Clz32 undefined for arg==0, so deal with that case:
3356 irx = binop(Iop_CmpNE32, lo32, mkU32(0));
3357 assign(rA, mkWidenFrom32(ty,
3358 IRExpr_Mux0X( unop(Iop_1Uto8, irx),
3360 unop(Iop_Clz32, lo32)),
3363 // TODO: alternatively: assign(rA, verbose_Clz32(rS));
3367 case 0x11C: // eqv (Equivalent, PPC32 p396)
3368 DIP("eqv%s r%u,r%u,r%u\n",
3369 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3370 assign( rA, unop( mkSzOp(ty, Iop_Not8),
3371 binop( mkSzOp(ty, Iop_Xor8),
3372 mkexpr(rS), mkexpr(rB))) );
3375 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
3377 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
3380 DIP("extsb%s r%u,r%u\n",
3381 flag_rC ? ".":"", rA_addr, rS_addr);
3383 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
3385 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
3388 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
3390 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
3393 DIP("extsh%s r%u,r%u\n",
3394 flag_rC ? ".":"", rA_addr, rS_addr);
3396 assign( rA, unop(Iop_16Sto64,
3397 unop(Iop_64to16, mkexpr(rS))) );
3399 assign( rA, unop(Iop_16Sto32,
3400 unop(Iop_32to16, mkexpr(rS))) );
3403 case 0x1DC: // nand (NAND, PPC32 p492)
3404 DIP("nand%s r%u,r%u,r%u\n",
3405 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3406 assign( rA, unop( mkSzOp(ty, Iop_Not8),
3407 binop( mkSzOp(ty, Iop_And8),
3408 mkexpr(rS), mkexpr(rB))) );
3411 case 0x07C: // nor (NOR, PPC32 p494)
3412 DIP("nor%s r%u,r%u,r%u\n",
3413 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3414 assign( rA, unop( mkSzOp(ty, Iop_Not8),
3415 binop( mkSzOp(ty, Iop_Or8),
3416 mkexpr(rS), mkexpr(rB))) );
3419 case 0x1BC: // or (OR, PPC32 p495)
3420 if ((!flag_rC) && rS_addr == rB_addr) {
3421 DIP("mr r%u,r%u\n", rA_addr, rS_addr);
3422 assign( rA, mkexpr(rS) );
3424 DIP("or%s r%u,r%u,r%u\n",
3425 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3426 assign( rA, binop( mkSzOp(ty, Iop_Or8),
3427 mkexpr(rS), mkexpr(rB)) );
3431 case 0x19C: // orc (OR with Complement, PPC32 p496)
3432 DIP("orc%s r%u,r%u,r%u\n",
3433 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3434 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3435 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
3438 case 0x13C: // xor (XOR, PPC32 p549)
3439 DIP("xor%s r%u,r%u,r%u\n",
3440 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3441 assign( rA, binop( mkSzOp(ty, Iop_Xor8),
3442 mkexpr(rS), mkexpr(rB)) );
3446 /* 64bit Integer Logical Instructions */
3447 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
3449 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
3452 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
3453 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
3456 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
3458 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
3461 DIP("cntlzd%s r%u,r%u\n",
3462 flag_rC ? ".":"", rA_addr, rS_addr);
3463 // Iop_Clz64 undefined for arg==0, so deal with that case:
3464 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
3465 assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx),
3467 unop(Iop_Clz64, mkexpr(rS)) ));
3468 // TODO: alternatively: assign(rA, verbose_Clz64(rS));
3471 case 0x1FC: // cmpb (Power6: compare bytes)
3472 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
3475 assign( rA, unop( Iop_V128to64,
3476 binop( Iop_CmpEQ8x16,
3477 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
3478 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
3481 assign( rA, unop( Iop_V128to32,
3482 binop( Iop_CmpEQ8x16,
3483 unop( Iop_32UtoV128, mkexpr(rS) ),
3484 unop( Iop_32UtoV128, mkexpr(rB) )
3488 case 0x2DF: { // mftgpr (move floating-point to general purpose register)
3489 IRTemp frB = newTemp(Ity_F64);
3490 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
3492 assign( frB, getFReg(rB_addr)); // always F64
3494 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
3496 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
3498 putIReg( rS_addr, mkexpr(rA));
3502 case 0x25F: { // mffgpr (move floating-point from general purpose register)
3503 IRTemp frA = newTemp(Ity_F64);
3504 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
3507 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
3509 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
3511 putFReg( rS_addr, mkexpr(frA));
3514 case 0x1FA: // popcntd (population count doubleword
3516 DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
3517 IRTemp result = gen_POPCOUNT(rS);
3518 putIReg( rA_addr, mkexpr(result) );
3523 vex_printf("dis_int_logic(ppc)(opc2)\n");
3529 vex_printf("dis_int_logic(ppc)(opc1)\n");
3533 putIReg( rA_addr, mkexpr(rA) );
3535 if (do_rc && flag_rC) {
3536 set_CR0( mkexpr(rA) );
3542 Integer Parity Instructions
3544 static Bool dis_int_parity ( UInt theInstr )
3547 UChar opc1 = ifieldOPC(theInstr);
3548 UChar rS_addr = ifieldRegDS(theInstr);
3549 UChar rA_addr = ifieldRegA(theInstr);
3550 UChar rB_addr = ifieldRegB(theInstr);
3551 UInt opc2 = ifieldOPClo10(theInstr);
3552 UChar b0 = ifieldBIT0(theInstr);
3553 IRType ty = mode64 ? Ity_I64 : Ity_I32;
3555 IRTemp rS = newTemp(ty);
3556 IRTemp rA = newTemp(ty);
3557 IRTemp iTot1 = newTemp(Ity_I32);
3558 IRTemp iTot2 = newTemp(Ity_I32);
3559 IRTemp iTot3 = newTemp(Ity_I32);
3560 IRTemp iTot4 = newTemp(Ity_I32);
3561 IRTemp iTot5 = newTemp(Ity_I32);
3562 IRTemp iTot6 = newTemp(Ity_I32);
3563 IRTemp iTot7 = newTemp(Ity_I32);
3564 IRTemp iTot8 = newTemp(Ity_I32);
3565 IRTemp rS1 = newTemp(ty);
3566 IRTemp rS2 = newTemp(ty);
3567 IRTemp rS3 = newTemp(ty);
3568 IRTemp rS4 = newTemp(ty);
3569 IRTemp rS5 = newTemp(ty);
3570 IRTemp rS6 = newTemp(ty);
3571 IRTemp rS7 = newTemp(ty);
3572 IRTemp iHi = newTemp(Ity_I32);
3573 IRTemp iLo = newTemp(Ity_I32);
3574 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1);
3575 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32);
3577 if (opc1 != 0x1f || rB_addr || b0) {
3578 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
3582 assign( rS, getIReg(rS_addr) );
3585 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320)
3586 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
3587 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
3588 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
3589 assign( iTot2, binop(Iop_Add32,
3590 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
3592 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
3593 assign( iTot3, binop(Iop_Add32,
3594 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
3596 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
3597 assign( iTot4, binop(Iop_Add32,
3598 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
3601 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
3602 assign( iTot5, binop(Iop_Add32,
3603 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
3605 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
3606 assign( iTot6, binop(Iop_Add32,
3607 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
3609 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
3610 assign( iTot7, binop(Iop_Add32,
3611 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
3613 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
3614 assign( iTot8, binop(Iop_Add32,
3615 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
3617 assign( rA, unop(Iop_32Uto64,
3618 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
3620 assign( rA, mkexpr(iTot4) );
3623 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320)
3624 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
3625 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
3626 assign( iTot2, binop(Iop_Add32,
3627 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
3629 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
3630 assign( iTot3, binop(Iop_Add32,
3631 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
3633 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
3634 assign( iTot4, binop(Iop_Add32,
3635 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
3637 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
3640 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
3641 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
3642 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
3643 assign( iTot6, binop(Iop_Add32,
3644 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
3646 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
3647 assign( iTot7, binop(Iop_Add32,
3648 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
3650 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
3651 assign( iTot8, binop(Iop_Add32,
3652 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
3654 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
3655 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
3657 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
3660 vex_printf("dis_int_parity(ppc)(opc2)\n");
3664 putIReg( rA_addr, mkexpr(rA) );
3671 Integer Rotate Instructions
3673 static Bool dis_int_rot ( UInt theInstr )
3675 /* M-Form, MDS-Form */
3676 UChar opc1 = ifieldOPC(theInstr);
3677 UChar rS_addr = ifieldRegDS(theInstr);
3678 UChar rA_addr = ifieldRegA(theInstr);
3679 UChar rB_addr = ifieldRegB(theInstr);
3680 UChar sh_imm = rB_addr;
3681 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
3682 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
3683 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
3684 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) );
3685 UChar b1 = ifieldBIT1(theInstr);
3686 UChar flag_rC = ifieldBIT0(theInstr);
3688 IRType ty = mode64 ? Ity_I64 : Ity_I32;
3689 IRTemp rS = newTemp(ty);
3690 IRTemp rA = newTemp(ty);
3691 IRTemp rB = newTemp(ty);
3692 IRTemp rot = newTemp(ty);
3697 assign( rS, getIReg(rS_addr) );
3698 assign( rB, getIReg(rB_addr) );
3702 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
3703 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
3704 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
3706 // tmp32 = (ROTL(rS_Lo32, Imm)
3707 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
3708 mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
3709 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
3710 r = unop(Iop_32Uto64, r);
3711 assign( rot, binop(Iop_Or64, r,
3712 binop(Iop_Shl64, r, mkU8(32))) );
3715 binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
3716 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
3719 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
3720 mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
3721 r = ROTL(mkexpr(rS), mkU8(sh_imm));
3724 binop(Iop_And32, mkU32(mask32), r),
3725 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
3731 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
3732 vassert(MaskBeg < 32);
3733 vassert(MaskEnd < 32);
3734 vassert(sh_imm < 32);
3737 IRTemp rTmp = newTemp(Ity_I64);
3738 mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
3739 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
3740 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
3741 // tmp32 = (ROTL(rS_Lo32, Imm)
3742 // rA = ((tmp32 || tmp32) & mask64)
3743 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
3744 r = unop(Iop_32Uto64, r);
3747 assign( rot, binop(Iop_Or64, mkexpr(rTmp),
3748 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
3749 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
3752 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
3753 /* Special-case the ,n,0,31-n form as that is just n-bit
3754 shift left, PPC32 p501 */
3755 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
3756 rA_addr, rS_addr, sh_imm);
3757 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
3759 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
3760 /* Special-case the ,32-n,n,31 form as that is just n-bit
3761 unsigned shift right, PPC32 p501 */
3762 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
3763 rA_addr, rS_addr, MaskBeg);
3764 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
3768 mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
3769 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
3770 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
3771 // rA = ROTL(rS, Imm) & mask
3772 assign( rA, binop(Iop_And32,
3773 ROTL(mkexpr(rS), mkU8(sh_imm)),
3781 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
3782 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
3783 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
3785 mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
3786 /* weird insn alert!
3787 tmp32 = (ROTL(rS_Lo32, rB[0-4])
3788 rA = ((tmp32 || tmp32) & mask64)
3790 // note, ROTL does the masking, so we don't do it here
3791 r = ROTL( unop(Iop_64to32, mkexpr(rS)),
3792 unop(Iop_64to8, mkexpr(rB)) );
3793 r = unop(Iop_32Uto64, r);
3794 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
3795 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
3797 mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
3798 // rA = ROTL(rS, rB[0-4]) & mask
3799 // note, ROTL does the masking, so we don't do it here
3800 assign( rA, binop(Iop_And32,
3802 unop(Iop_32to8, mkexpr(rB))),
3808 /* 64bit Integer Rotates */
3810 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
3813 vassert( msk_imm < 64 );
3814 vassert( sh_imm < 64 );
3818 /* r = ROTL64( rS, rB_lo6) */
3819 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
3821 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
3822 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
3823 rA_addr, rS_addr, rB_addr, msk_imm);
3824 // note, ROTL does the masking, so we don't do it here
3825 mask64 = MASK64(0, 63-msk_imm);
3826 assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
3828 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556)
3829 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
3830 rA_addr, rS_addr, rB_addr, msk_imm);
3831 mask64 = MASK64(63-msk_imm, 63);
3832 assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
3837 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
3838 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
3839 rA_addr, rS_addr, sh_imm, msk_imm);
3840 r = ROTL(mkexpr(rS), mkU8(sh_imm));
3841 mask64 = MASK64(sh_imm, 63-msk_imm);
3842 assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
3844 // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
3846 Hmm... looks like this'll do the job more simply:
3848 m = ~(1 << (63-msk_imm))
3852 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
3854 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
3855 /* special-case the ,64-n,n form as that is just
3856 unsigned shift-right by n */
3857 DIP("srdi%s r%u,r%u,%u\n",
3858 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
3859 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
3861 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
3862 rA_addr, rS_addr, sh_imm, msk_imm);
3863 r = ROTL(mkexpr(rS), mkU8(sh_imm));
3864 mask64 = MASK64(0, 63-msk_imm);
3865 assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
3869 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
3871 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
3872 /* special-case the ,n,63-n form as that is just
3874 DIP("sldi%s r%u,r%u,%u\n",
3875 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
3876 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
3878 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
3879 rA_addr, rS_addr, sh_imm, msk_imm);
3880 r = ROTL(mkexpr(rS), mkU8(sh_imm));
3881 mask64 = MASK64(63-msk_imm, 63);
3882 assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
3886 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
3887 IRTemp rA_orig = newTemp(ty);
3888 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
3889 rA_addr, rS_addr, sh_imm, msk_imm);
3890 r = ROTL(mkexpr(rS), mkU8(sh_imm));
3891 mask64 = MASK64(sh_imm, 63-msk_imm);
3892 assign( rA_orig, getIReg(rA_addr) );
3893 assign( rA, binop(Iop_Or64,
3894 binop(Iop_And64, mkU64(mask64), r),
3895 binop(Iop_And64, mkU64(~mask64),
3896 mkexpr(rA_orig))) );
3900 vex_printf("dis_int_rot(ppc)(opc2)\n");
3907 vex_printf("dis_int_rot(ppc)(opc1)\n");
3911 putIReg( rA_addr, mkexpr(rA) );
3914 set_CR0( mkexpr(rA) );
3921 Integer Load Instructions
3923 static Bool dis_int_load ( UInt theInstr )
3925 /* D-Form, X-Form, DS-Form */
3926 UChar opc1 = ifieldOPC(theInstr);
3927 UChar rD_addr = ifieldRegDS(theInstr);
3928 UChar rA_addr = ifieldRegA(theInstr);
3929 UInt uimm16 = ifieldUIMM16(theInstr);
3930 UChar rB_addr = ifieldRegB(theInstr);
3931 UInt opc2 = ifieldOPClo10(theInstr);
3932 UChar b1 = ifieldBIT1(theInstr);
3933 UChar b0 = ifieldBIT0(theInstr);
3935 Int simm16 = extend_s_16to32(uimm16);
3936 IRType ty = mode64 ? Ity_I64 : Ity_I32;
3937 IRTemp EA = newTemp(ty);
3941 case 0x1F: // register offset
3942 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
3944 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
3945 // lowest 2 bits of immediate before forming EA
3946 simm16 = simm16 & 0xFFFFFFFC;
3947 default: // immediate offset
3948 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
3953 case 0x22: // lbz (Load B & Zero, PPC32 p433)
3954 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3955 val = loadBE(Ity_I8, mkexpr(EA));
3956 putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
3959 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
3960 if (rA_addr == 0 || rA_addr == rD_addr) {
3961 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
3964 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3965 val = loadBE(Ity_I8, mkexpr(EA));
3966 putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
3967 putIReg( rA_addr, mkexpr(EA) );
3970 case 0x2A: // lha (Load HW Alg, PPC32 p445)
3971 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3972 val = loadBE(Ity_I16, mkexpr(EA));
3973 putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
3976 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
3977 if (rA_addr == 0 || rA_addr == rD_addr) {
3978 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
3981 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3982 val = loadBE(Ity_I16, mkexpr(EA));
3983 putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
3984 putIReg( rA_addr, mkexpr(EA) );
3987 case 0x28: // lhz (Load HW & Zero, PPC32 p450)
3988 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3989 val = loadBE(Ity_I16, mkexpr(EA));
3990 putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
3993 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
3994 if (rA_addr == 0 || rA_addr == rD_addr) {
3995 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
3998 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
3999 val = loadBE(Ity_I16, mkexpr(EA));
4000 putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4001 putIReg( rA_addr, mkexpr(EA) );
4004 case 0x20: // lwz (Load W & Zero, PPC32 p460)
4005 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4006 val = loadBE(Ity_I32, mkexpr(EA));
4007 putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4010 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
4011 if (rA_addr == 0 || rA_addr == rD_addr) {
4012 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
4015 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4016 val = loadBE(Ity_I32, mkexpr(EA));
4017 putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4018 putIReg( rA_addr, mkexpr(EA) );
4024 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
4029 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
4030 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4031 if (rA_addr == 0 || rA_addr == rD_addr) {
4032 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
4035 val = loadBE(Ity_I8, mkexpr(EA));
4036 putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4037 putIReg( rA_addr, mkexpr(EA) );
4040 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
4041 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4042 val = loadBE(Ity_I8, mkexpr(EA));
4043 putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4046 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
4047 if (rA_addr == 0 || rA_addr == rD_addr) {
4048 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
4051 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4052 val = loadBE(Ity_I16, mkexpr(EA));
4053 putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4054 putIReg( rA_addr, mkexpr(EA) );
4057 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
4058 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4059 val = loadBE(Ity_I16, mkexpr(EA));
4060 putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4063 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
4064 if (rA_addr == 0 || rA_addr == rD_addr) {
4065 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
4068 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4069 val = loadBE(Ity_I16, mkexpr(EA));
4070 putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4071 putIReg( rA_addr, mkexpr(EA) );
4074 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
4075 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4076 val = loadBE(Ity_I16, mkexpr(EA));
4077 putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4080 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
4081 if (rA_addr == 0 || rA_addr == rD_addr) {
4082 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
4085 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4086 val = loadBE(Ity_I32, mkexpr(EA));
4087 putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4088 putIReg( rA_addr, mkexpr(EA) );
4091 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
4092 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4093 val = loadBE(Ity_I32, mkexpr(EA));
4094 putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4099 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
4100 if (rA_addr == 0 || rA_addr == rD_addr) {
4101 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
4104 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4105 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4106 putIReg( rA_addr, mkexpr(EA) );
4109 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
4110 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4111 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4114 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
4115 if (rA_addr == 0 || rA_addr == rD_addr) {
4116 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
4119 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4121 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4122 putIReg( rA_addr, mkexpr(EA) );
4125 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
4126 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4128 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4132 vex_printf("dis_int_load(ppc)(opc2)\n");
4137 /* DS Form - 64bit Loads. In each case EA will have been formed
4138 with the lowest 2 bits masked off the immediate offset. */
4140 switch ((b1<<1) | b0) {
4141 case 0x0: // ld (Load DWord, PPC64 p472)
4142 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4143 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4146 case 0x1: // ldu (Load DWord, Update, PPC64 p474)
4147 if (rA_addr == 0 || rA_addr == rD_addr) {
4148 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
4151 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4152 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4153 putIReg( rA_addr, mkexpr(EA) );
4156 case 0x2: // lwa (Load Word Alg, PPC64 p499)
4157 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4159 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4163 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
4169 vex_printf("dis_int_load(ppc)(opc1)\n");
4178 Integer Store Instructions
4180 static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi )
4182 /* D-Form, X-Form, DS-Form */
4183 UChar opc1 = ifieldOPC(theInstr);
4184 UInt rS_addr = ifieldRegDS(theInstr);
4185 UInt rA_addr = ifieldRegA(theInstr);
4186 UInt uimm16 = ifieldUIMM16(theInstr);
4187 UInt rB_addr = ifieldRegB(theInstr);
4188 UInt opc2 = ifieldOPClo10(theInstr);
4189 UChar b1 = ifieldBIT1(theInstr);
4190 UChar b0 = ifieldBIT0(theInstr);
4192 Int simm16 = extend_s_16to32(uimm16);
4193 IRType ty = mode64 ? Ity_I64 : Ity_I32;
4194 IRTemp rS = newTemp(ty);
4195 IRTemp rB = newTemp(ty);
4196 IRTemp EA = newTemp(ty);
4198 assign( rB, getIReg(rB_addr) );
4199 assign( rS, getIReg(rS_addr) );
4202 case 0x1F: // register offset
4203 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
4205 case 0x3E: // immediate offset: 64bit: std/stdu: mask off
4206 // lowest 2 bits of immediate before forming EA
4207 simm16 = simm16 & 0xFFFFFFFC;
4208 default: // immediate offset
4209 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
4214 case 0x26: // stb (Store B, PPC32 p509)
4215 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4216 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4219 case 0x27: // stbu (Store B, Update, PPC32 p510)
4220 if (rA_addr == 0 ) {
4221 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
4224 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4225 putIReg( rA_addr, mkexpr(EA) );
4226 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4229 case 0x2C: // sth (Store HW, PPC32 p522)
4230 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4231 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4234 case 0x2D: // sthu (Store HW, Update, PPC32 p524)
4236 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
4239 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4240 putIReg( rA_addr, mkexpr(EA) );
4241 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4244 case 0x24: // stw (Store W, PPC32 p530)
4245 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4246 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4249 case 0x25: // stwu (Store W, Update, PPC32 p534)
4251 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
4254 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4255 putIReg( rA_addr, mkexpr(EA) );
4256 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4259 /* X Form : all these use EA_indexed */
4262 vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
4267 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
4269 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
4272 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4273 putIReg( rA_addr, mkexpr(EA) );
4274 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4277 case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
4278 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4279 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4282 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
4284 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
4287 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4288 putIReg( rA_addr, mkexpr(EA) );
4289 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4292 case 0x197: // sthx (Store HW Indexed, PPC32 p526)
4293 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4294 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4297 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
4299 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
4302 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4303 putIReg( rA_addr, mkexpr(EA) );
4304 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4307 case 0x097: // stwx (Store W Indexed, PPC32 p536)
4308 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4309 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4314 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
4316 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
4319 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4320 putIReg( rA_addr, mkexpr(EA) );
4321 storeBE( mkexpr(EA), mkexpr(rS) );
4324 case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
4325 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4326 storeBE( mkexpr(EA), mkexpr(rS) );
4330 vex_printf("dis_int_store(ppc)(opc2)\n");
4335 /* DS Form - 64bit Stores. In each case EA will have been formed
4336 with the lowest 2 bits masked off the immediate offset. */
4338 switch ((b1<<1) | b0) {
4339 case 0x0: // std (Store DWord, PPC64 p580)
4340 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4341 storeBE( mkexpr(EA), mkexpr(rS) );
4344 case 0x1: // stdu (Store DWord, Update, PPC64 p583)
4345 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4346 putIReg( rA_addr, mkexpr(EA) );
4347 storeBE( mkexpr(EA), mkexpr(rS) );
4351 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
4357 vex_printf("dis_int_store(ppc)(opc1)\n");
4366 Integer Load/Store Multiple Instructions
4368 static Bool dis_int_ldst_mult ( UInt theInstr )
4371 UChar opc1 = ifieldOPC(theInstr);
4372 UChar rD_addr = ifieldRegDS(theInstr);
4373 UChar rS_addr = rD_addr;
4374 UChar rA_addr = ifieldRegA(theInstr);
4375 UInt uimm16 = ifieldUIMM16(theInstr);
4377 Int simm16 = extend_s_16to32(uimm16);
4378 IRType ty = mode64 ? Ity_I64 : Ity_I32;
4379 IRTemp EA = newTemp(ty);
4384 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
4387 case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
4388 if (rA_addr >= rD_addr) {
4389 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
4392 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4393 for (r = rD_addr; r <= 31; r++) {
4394 irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
4395 putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ),
4401 case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
4402 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4403 for (r = rS_addr; r <= 31; r++) {
4404 irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
4405 storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
4411 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
4420 Integer Load/Store String Instructions
4423 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32
4425 Int rD, // first dst register
4426 Int maxBytes ) // 32 or 128
4429 IRExpr* e_nbytes = mkexpr(tNBytes);
4430 IRExpr* e_EA = mkexpr(EA);
4431 IRType ty = mode64 ? Ity_I64 : Ity_I32;
4433 vassert(rD >= 0 && rD < 32);
4434 rD--; if (rD < 0) rD = 31;
4436 for (i = 0; i < maxBytes; i++) {
4437 /* if (nBytes < (i+1)) goto NIA; */
4438 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
4440 mkSzConst( ty, nextInsnAddr()) ));
4441 /* when crossing into a new dest register, set it to zero. */
4443 rD++; if (rD == 32) rD = 0;
4444 putIReg(rD, mkSzImm(ty, 0));
4447 /* rD |= (8Uto32(*(EA+i))) << shift */
4448 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
4455 mkNarrowTo32(ty, getIReg(rD)),
4461 binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)))
4463 mkU8(toUChar(shift))
4474 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32
4476 Int rS, // first src register
4477 Int maxBytes ) // 32 or 128
4480 IRExpr* e_nbytes = mkexpr(tNBytes);
4481 IRExpr* e_EA = mkexpr(EA);
4482 IRType ty = mode64 ? Ity_I64 : Ity_I32;
4484 vassert(rS >= 0 && rS < 32);
4485 rS--; if (rS < 0) rS = 31;
4487 for (i = 0; i < maxBytes; i++) {
4488 /* if (nBytes < (i+1)) goto NIA; */
4489 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
4491 mkSzConst( ty, nextInsnAddr() ) ));
4492 /* check for crossing into a new src register. */
4494 rS++; if (rS == 32) rS = 0;
4497 /* *(EA+i) = 32to8(rS >> shift) */
4498 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
4500 binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
4503 mkNarrowTo32(ty, getIReg(rS)),
4504 mkU8(toUChar(shift))))
4510 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
4513 UChar opc1 = ifieldOPC(theInstr);
4514 UChar rD_addr = ifieldRegDS(theInstr);
4515 UChar rS_addr = rD_addr;
4516 UChar rA_addr = ifieldRegA(theInstr);
4517 UChar rB_addr = ifieldRegB(theInstr);
4518 UChar NumBytes = rB_addr;
4519 UInt opc2 = ifieldOPClo10(theInstr);
4520 UChar b0 = ifieldBIT0(theInstr);
4522 IRType ty = mode64 ? Ity_I64 : Ity_I32;
4523 IRTemp t_EA = newTemp(ty);
4524 IRTemp t_nbytes = IRTemp_INVALID;
4528 if (opc1 != 0x1F || b0 != 0) {
4529 vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
4534 case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
4535 /* NB: does not reject the case where RA is in the range of
4536 registers to be loaded. It should. */
4537 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
4538 assign( t_EA, ea_rAor0(rA_addr) );
4539 if (NumBytes == 8 && !mode64) {
4540 /* Special case hack */
4541 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
4543 loadBE(Ity_I32, mkexpr(t_EA)) );
4544 putIReg( (rD_addr+1) % 32,
4546 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
4548 t_nbytes = newTemp(Ity_I32);
4549 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
4550 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
4555 case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
4556 /* NB: does not reject the case where RA is in the range of
4557 registers to be loaded. It should. Although considering
4558 that that can only be detected at run time, it's not easy to
4560 if (rD_addr == rA_addr || rD_addr == rB_addr)
4562 if (rD_addr == 0 && rA_addr == 0)
4564 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4565 t_nbytes = newTemp(Ity_I32);
4566 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
4567 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
4568 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
4572 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
4573 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
4574 assign( t_EA, ea_rAor0(rA_addr) );
4575 if (NumBytes == 8 && !mode64) {
4576 /* Special case hack */
4577 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
4578 storeBE( mkexpr(t_EA),
4580 storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
4581 getIReg((rD_addr+1) % 32) );
4583 t_nbytes = newTemp(Ity_I32);
4584 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
4585 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
4590 case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
4591 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4592 t_nbytes = newTemp(Ity_I32);
4593 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
4594 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
4595 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
4600 vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
4607 /* ------------------------------------------------------------------
4608 Integer Branch Instructions
4609 ------------------------------------------------------------------ */
4612 Branch helper function
4613 ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
4614 Returns an I32 which is 0x00000000 if the ctr condition failed
4615 and 0xFFFFFFFF otherwise.
4617 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
4619 IRType ty = mode64 ? Ity_I64 : Ity_I32;
4620 IRTemp ok = newTemp(Ity_I32);
4622 if ((BO >> 2) & 1) { // independent of ctr
4623 assign( ok, mkU32(0xFFFFFFFF) );
4625 if ((BO >> 1) & 1) { // ctr == 0 ?
4626 assign( ok, unop( Iop_1Sto32,
4627 binop( mkSzOp(ty, Iop_CmpEQ8),
4628 getGST( PPC_GST_CTR ),
4630 } else { // ctr != 0 ?
4631 assign( ok, unop( Iop_1Sto32,
4632 binop( mkSzOp(ty, Iop_CmpNE8),
4633 getGST( PPC_GST_CTR ),
4642 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
4643 Returns an I32 which is either 0 if the condition failed or
4644 some arbitrary nonzero value otherwise. */
4646 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
4649 IRTemp res = newTemp(Ity_I32);
4650 IRTemp cr_bi = newTemp(Ity_I32);
4652 if ((BO >> 4) & 1) {
4653 assign( res, mkU32(1) );
4655 // ok = (CR[BI] == BO[3]) Note, the following relies on
4656 // getCRbit_anywhere returning a value which
4657 // is either zero or has exactly 1 bit set.
4658 assign( cr_bi, getCRbit_anywhere( BI, &where ) );
4660 if ((BO >> 3) & 1) {
4661 /* We can use cr_bi as-is. */
4662 assign( res, mkexpr(cr_bi) );
4664 /* We have to invert the sense of the information held in
4665 cr_bi. For that we need to know which bit
4666 getCRbit_anywhere regards as significant. */
4667 assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
4676 Integer Branch Instructions
4678 static Bool dis_branch ( UInt theInstr,
4680 /*OUT*/DisResult* dres,
4681 Bool (*resteerOkFn)(void*,Addr64),
4682 void* callback_opaque )
4684 UChar opc1 = ifieldOPC(theInstr);
4685 UChar BO = ifieldRegDS(theInstr);
4686 UChar BI = ifieldRegA(theInstr);
4687 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
4688 UChar b11to15 = ifieldRegB(theInstr);
4689 UInt opc2 = ifieldOPClo10(theInstr);
4690 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
4691 UChar flag_AA = ifieldBIT1(theInstr);
4692 UChar flag_LK = ifieldBIT0(theInstr);
4694 IRType ty = mode64 ? Ity_I64 : Ity_I32;
4696 Int BD = extend_s_16to32(BD_u16);
4697 IRTemp do_branch = newTemp(Ity_I32);
4698 IRTemp ctr_ok = newTemp(Ity_I32);
4699 IRTemp cond_ok = newTemp(Ity_I32);
4700 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr());
4701 IRConst* c_nia = mkSzConst(ty, nextInsnAddr());
4702 IRTemp lr_old = newTemp(ty);
4704 /* Hack to pass through code that just wants to read the PC */
4705 if (theInstr == 0x429F0005) {
4706 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
4707 putGST( PPC_GST_LR, e_nia );
4711 /* The default what-next. Individual cases can override it. */
4712 dres->whatNext = Dis_StopHere;
4715 case 0x12: // b (Branch, PPC32 p360)
4717 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
4719 tgt = mkSzAddr( ty, guest_CIA_curr_instr +
4720 (Long)extend_s_26to64(LI_u26) );
4723 DIP("b%s%s 0x%llx\n",
4724 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
4727 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
4731 putGST( PPC_GST_LR, e_nia );
4732 if (vbi->guest_ppc_zap_RZ_at_bl
4733 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
4734 IRTemp t_tgt = newTemp(ty);
4735 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
4736 make_redzone_AbiHint( vbi, t_tgt,
4737 "branch-and-link (unconditional call)" );
4741 if (resteerOkFn( callback_opaque, tgt )) {
4742 dres->whatNext = Dis_ResteerU;
4743 dres->continueAt = tgt;
4745 irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
4746 irsb->next = mkSzImm(ty, tgt);
4750 case 0x10: // bc (Branch Conditional, PPC32 p361)
4751 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
4752 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
4755 putGST( PPC_GST_CTR,
4756 binop(mkSzOp(ty, Iop_Sub8),
4757 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
4760 /* This is a bit subtle. ctr_ok is either all 0s or all 1s.
4761 cond_ok is either zero or nonzero, since that's the cheapest
4762 way to compute it. Anding them together gives a value which
4763 is either zero or non zero and so that's what we must test
4764 for in the IRStmt_Exit. */
4765 assign( ctr_ok, branch_ctr_ok( BO ) );
4766 assign( cond_ok, branch_cond_ok( BO, BI ) );
4768 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
4771 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
4773 tgt = mkSzAddr(ty, guest_CIA_curr_instr +
4774 (Long)extend_s_16to64(BD_u16));
4777 putGST( PPC_GST_LR, e_nia );
4780 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
4781 flag_LK ? Ijk_Call : Ijk_Boring,
4782 mkSzConst(ty, tgt) ) );
4784 irsb->jumpkind = Ijk_Boring;
4789 /* For bclr and bcctr, it appears that the lowest two bits of
4790 b11to15 are a branch hint, and so we only need to ensure it's
4791 of the form 000XX. */
4792 if ((b11to15 & ~3) != 0) {
4793 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15);
4798 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
4799 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
4800 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
4803 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
4805 assign( cond_ok, branch_cond_ok( BO, BI ) );
4807 /* FIXME: this is confusing. lr_old holds the old value
4808 of ctr, not lr :-) */
4809 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
4812 putGST( PPC_GST_LR, e_nia );
4815 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
4819 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
4820 make_redzone_AbiHint( vbi, lr_old,
4821 "b-ctr-l (indirect call)" );
4824 irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
4825 irsb->next = mkexpr(lr_old);
4828 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
4829 Bool vanilla_return = False;
4830 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
4832 vanilla_return = True;
4834 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
4838 putGST( PPC_GST_CTR,
4839 binop(mkSzOp(ty, Iop_Sub8),
4840 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
4843 /* See comments above for 'bc' about this */
4844 assign( ctr_ok, branch_ctr_ok( BO ) );
4845 assign( cond_ok, branch_cond_ok( BO, BI ) );
4847 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
4849 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
4852 putGST( PPC_GST_LR, e_nia );
4855 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
4859 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
4860 make_redzone_AbiHint( vbi, lr_old,
4861 "branch-to-lr (unconditional return)" );
4864 /* blrl is pretty strange; it's like a return that sets the
4865 return address of its caller to the insn following this
4866 one. Mark it as a return. */
4867 irsb->jumpkind = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */
4868 irsb->next = mkexpr(lr_old);
4872 vex_printf("dis_int_branch(ppc)(opc2)\n");
4878 vex_printf("dis_int_branch(ppc)(opc1)\n");
4888 Condition Register Logical Instructions
4890 static Bool dis_cond_logic ( UInt theInstr )
4893 UChar opc1 = ifieldOPC(theInstr);
4894 UChar crbD_addr = ifieldRegDS(theInstr);
4895 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
4896 UChar crbA_addr = ifieldRegA(theInstr);
4897 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
4898 UChar crbB_addr = ifieldRegB(theInstr);
4899 UInt opc2 = ifieldOPClo10(theInstr);
4900 UChar b0 = ifieldBIT0(theInstr);
4902 IRTemp crbD = newTemp(Ity_I32);
4903 IRTemp crbA = newTemp(Ity_I32);
4904 IRTemp crbB = newTemp(Ity_I32);
4906 if (opc1 != 19 || b0 != 0) {
4907 vex_printf("dis_cond_logic(ppc)(opc1)\n");
4911 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464)
4912 if (((crbD_addr & 0x3) != 0) ||
4913 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
4914 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
4917 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
4918 putCR0( crfD_addr, getCR0( crfS_addr) );
4919 putCR321( crfD_addr, getCR321(crfS_addr) );
4921 assign( crbA, getCRbit(crbA_addr) );
4922 if (crbA_addr == crbB_addr)
4925 assign( crbB, getCRbit(crbB_addr) );
4928 case 0x101: // crand (Cond Reg AND, PPC32 p372)
4929 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4930 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
4932 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373)
4933 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4934 assign( crbD, binop(Iop_And32,
4936 unop(Iop_Not32, mkexpr(crbB))) );
4938 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374)
4939 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4940 assign( crbD, unop(Iop_Not32,
4941 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
4943 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375)
4944 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4945 assign( crbD, unop(Iop_Not32,
4946 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
4948 case 0x021: // crnor (Cond Reg NOR, PPC32 p376)
4949 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4950 assign( crbD, unop(Iop_Not32,
4951 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
4953 case 0x1C1: // cror (Cond Reg OR, PPC32 p377)
4954 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4955 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
4957 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378)
4958 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4959 assign( crbD, binop(Iop_Or32,
4961 unop(Iop_Not32, mkexpr(crbB))) );
4963 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379)
4964 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
4965 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
4968 vex_printf("dis_cond_logic(ppc)(opc2)\n");
4972 putCRbit( crbD_addr, mkexpr(crbD) );
4982 /* Do the code generation for a trap. Returned Bool is true iff
4983 this is an unconditional trap. If the two arg IRExpr*s are
4984 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s
4985 then they are 64-bit, and we must be disassembling 64-bit
4987 static Bool do_trap ( UChar TO,
4988 IRExpr* argL0, IRExpr* argR0, Addr64 cia )
4991 IRExpr *argLe, *argRe, *cond, *tmp;
4993 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
4995 IROp opAND = is32bit ? Iop_And32 : Iop_And64;
4996 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64;
4997 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
4998 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
4999 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64;
5000 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64;
5001 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0);
5002 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2);
5003 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4);
5004 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8);
5006 const UChar b11100 = 0x1C;
5007 const UChar b00111 = 0x07;
5010 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
5011 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
5013 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
5014 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
5018 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
5019 /* Unconditional trap. Just do the exit without
5020 testing the arguments. */
5022 binop(opCMPEQ, const0, const0),
5024 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia)
5026 return True; /* unconditional trap */
5030 argL = newTemp(Ity_I32);
5031 argR = newTemp(Ity_I32);
5033 argL = newTemp(Ity_I64);
5034 argR = newTemp(Ity_I64);
5037 assign( argL, argL0 );
5038 assign( argR, argR0 );
5040 argLe = mkexpr(argL);
5041 argRe = mkexpr(argR);
5044 if (TO & 16) { // L <s R
5045 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
5046 cond = binop(opOR, tmp, cond);
5048 if (TO & 8) { // L >s R
5049 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
5050 cond = binop(opOR, tmp, cond);
5052 if (TO & 4) { // L == R
5053 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
5054 cond = binop(opOR, tmp, cond);
5056 if (TO & 2) { // L <u R
5057 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
5058 cond = binop(opOR, tmp, cond);
5060 if (TO & 1) { // L >u R
5061 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
5062 cond = binop(opOR, tmp, cond);
5065 binop(opCMPNE, cond, const0),
5067 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia)
5069 return False; /* not an unconditional trap */
5072 static Bool dis_trapi ( UInt theInstr,
5073 /*OUT*/DisResult* dres )
5076 UChar opc1 = ifieldOPC(theInstr);
5077 UChar TO = ifieldRegDS(theInstr);
5078 UChar rA_addr = ifieldRegA(theInstr);
5079 UInt uimm16 = ifieldUIMM16(theInstr);
5080 ULong simm16 = extend_s_16to64(uimm16);
5081 Addr64 cia = guest_CIA_curr_instr;
5082 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5083 Bool uncond = False;
5086 case 0x03: // twi (Trap Word Immediate, PPC32 p548)
5087 uncond = do_trap( TO,
5088 mode64 ? unop(Iop_64to32, getIReg(rA_addr))
5090 mkU32( (UInt)simm16 ),
5093 DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
5095 DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
5101 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
5103 DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
5105 DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
5113 /* If the trap shows signs of being unconditional, don't
5114 continue decoding past it. */
5115 irsb->next = mkSzImm( ty, nextInsnAddr() );
5116 irsb->jumpkind = Ijk_Boring;
5117 dres->whatNext = Dis_StopHere;
5123 static Bool dis_trap ( UInt theInstr,
5124 /*OUT*/DisResult* dres )
5127 UInt opc2 = ifieldOPClo10(theInstr);
5128 UChar TO = ifieldRegDS(theInstr);
5129 UChar rA_addr = ifieldRegA(theInstr);
5130 UChar rB_addr = ifieldRegB(theInstr);
5131 Addr64 cia = guest_CIA_curr_instr;
5132 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5133 Bool uncond = False;
5135 if (ifieldBIT0(theInstr) != 0)
5139 case 0x004: // tw (Trap Word, PPC64 p540)
5140 uncond = do_trap( TO,
5141 mode64 ? unop(Iop_64to32, getIReg(rA_addr))
5143 mode64 ? unop(Iop_64to32, getIReg(rB_addr))
5147 DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
5149 DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
5152 case 0x044: // td (Trap Doubleword, PPC64 p534)
5155 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
5157 DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
5159 DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
5167 /* If the trap shows signs of being unconditional, don't
5168 continue decoding past it. */
5169 irsb->next = mkSzImm( ty, nextInsnAddr() );
5170 irsb->jumpkind = Ijk_Boring;
5171 dres->whatNext = Dis_StopHere;
5179 System Linkage Instructions
5181 static Bool dis_syslink ( UInt theInstr,
5182 VexAbiInfo* abiinfo, DisResult* dres )
5184 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5186 if (theInstr != 0x44000002) {
5187 vex_printf("dis_syslink(ppc)(theInstr)\n");
5191 // sc (System Call, PPC32 p504)
5194 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX
5195 Valgrind can back the guest up to this instruction if it needs
5196 to restart the syscall. */
5197 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
5199 /* It's important that all ArchRegs carry their up-to-date value
5200 at this point. So we declare an end-of-block here, which
5201 forces any TempRegs caching ArchRegs to be flushed. */
5202 irsb->next = abiinfo->guest_ppc_sc_continues_at_LR
5203 ? getGST( PPC_GST_LR )
5204 : mkSzImm( ty, nextInsnAddr() );
5205 irsb->jumpkind = Ijk_Sys_syscall;
5207 dres->whatNext = Dis_StopHere;
5213 Memory Synchronization Instructions
5215 Note on Reservations:
5216 We rely on the assumption that V will in fact only allow one thread at
5217 once to run. In effect, a thread can make a reservation, but we don't
5218 check any stores it does. Instead, the reservation is cancelled when
5219 the scheduler switches to another thread (run_thread_for_a_while()).
5221 static Bool dis_memsync ( UInt theInstr )
5223 /* X-Form, XL-Form */
5224 UChar opc1 = ifieldOPC(theInstr);
5225 UInt b11to25 = IFIELD(theInstr, 11, 15);
5226 UChar flag_L = ifieldRegDS(theInstr);
5227 UInt b11to20 = IFIELD(theInstr, 11, 10);
5228 UChar rD_addr = ifieldRegDS(theInstr);
5229 UChar rS_addr = rD_addr;
5230 UChar rA_addr = ifieldRegA(theInstr);
5231 UChar rB_addr = ifieldRegB(theInstr);
5232 UInt opc2 = ifieldOPClo10(theInstr);
5233 UChar b0 = ifieldBIT0(theInstr);
5235 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5236 IRTemp EA = newTemp(ty);
5238 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5242 case 0x13: // isync (Instruction Synchronize, PPC32 p432)
5243 if (opc2 != 0x096) {
5244 vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
5247 if (b11to25 != 0 || b0 != 0) {
5248 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
5252 stmt( IRStmt_MBE(Imbe_Fence) );
5258 case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394)
5259 if (b11to25 != 0 || b0 != 0) {
5260 vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n");
5264 /* Insert a memory fence, just to be on the safe side. */
5265 stmt( IRStmt_MBE(Imbe_Fence) );
5268 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
5270 /* According to the PowerPC ISA version 2.05, b0 (called EH
5271 in the documentation) is merely a hint bit to the
5272 hardware, I think as to whether or not contention is
5273 likely. So we can just ignore it. */
5274 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
5276 // trap if misaligned
5277 gen_SIGBUS_if_misaligned( EA, 4 );
5279 // and actually do the load
5280 res = newTemp(Ity_I32);
5281 stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
5283 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
5288 // stwcx. (Store Word Conditional Indexed, PPC32 p532)
5289 // Note this has to handle stwcx. in both 32- and 64-bit modes,
5290 // so isn't quite as straightforward as it might otherwise be.
5291 IRTemp rS = newTemp(Ity_I32);
5294 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
5297 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5299 // trap if misaligned
5300 gen_SIGBUS_if_misaligned( EA, 4 );
5302 // Get the data to be stored, and narrow to 32 bits if necessary
5303 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
5305 // Do the store, and get success/failure bit into resSC
5306 resSC = newTemp(Ity_I1);
5307 stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
5309 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
5310 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
5311 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
5312 putCR0(0, getXER_SO());
5315 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
5316 whether rS is stored is dependent on that value. */
5317 /* So I guess we can just ignore this case? */
5321 case 0x256: // sync (Synchronize, PPC32 p543),
5322 // also lwsync (L==1), ptesync (L==2)
5323 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
5325 The PowerPC architecture used in IBM chips has expanded
5326 the sync instruction into two variants: lightweight sync
5327 and heavyweight sync. The original sync instruction is
5328 the new heavyweight sync and lightweight sync is a strict
5329 subset of the heavyweight sync functionality. This allows
5330 the programmer to specify a less expensive operation on
5331 high-end systems when the full sync functionality is not
5334 The basic "sync" mnemonic now utilizes an operand. "sync"
5335 without an operand now becomes a extended mnemonic for
5336 heavyweight sync. Processors without the lwsync
5337 instruction will not decode the L field and will perform a
5338 heavyweight sync. Everything is backward compatible.
5342 ptesync = sync 2 *** TODO - not implemented ***
5344 if (b11to20 != 0 || b0 != 0) {
5345 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
5348 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
5349 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
5352 DIP("%ssync\n", flag_L == 1 ? "lw" : "");
5353 /* Insert a memory fence. It's sometimes important that these
5354 are carried through to the generated code. */
5355 stmt( IRStmt_MBE(Imbe_Fence) );
5359 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
5361 /* According to the PowerPC ISA version 2.05, b0 (called EH
5362 in the documentation) is merely a hint bit to the
5363 hardware, I think as to whether or not contention is
5364 likely. So we can just ignore it. */
5367 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
5369 // trap if misaligned
5370 gen_SIGBUS_if_misaligned( EA, 8 );
5372 // and actually do the load
5373 res = newTemp(Ity_I64);
5374 stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
5376 putIReg( rD_addr, mkexpr(res) );
5380 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
5381 // A marginally simplified version of the stwcx. case
5382 IRTemp rS = newTemp(Ity_I64);
5385 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
5390 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5392 // trap if misaligned
5393 gen_SIGBUS_if_misaligned( EA, 8 );
5395 // Get the data to be stored
5396 assign( rS, getIReg(rS_addr) );
5398 // Do the store, and get success/failure bit into resSC
5399 resSC = newTemp(Ity_I1);
5400 stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
5402 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
5403 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
5404 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
5405 putCR0(0, getXER_SO());
5408 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
5409 whether rS is stored is dependent on that value. */
5410 /* So I guess we can just ignore this case? */
5415 vex_printf("dis_memsync(ppc)(opc2)\n");
5421 vex_printf("dis_memsync(ppc)(opc1)\n");
5430 Integer Shift Instructions
5432 static Bool dis_int_shift ( UInt theInstr )
5434 /* X-Form, XS-Form */
5435 UChar opc1 = ifieldOPC(theInstr);
5436 UChar rS_addr = ifieldRegDS(theInstr);
5437 UChar rA_addr = ifieldRegA(theInstr);
5438 UChar rB_addr = ifieldRegB(theInstr);
5439 UChar sh_imm = rB_addr;
5440 UInt opc2 = ifieldOPClo10(theInstr);
5441 UChar b1 = ifieldBIT1(theInstr);
5442 UChar flag_rC = ifieldBIT0(theInstr);
5444 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5445 IRTemp rA = newTemp(ty);
5446 IRTemp rS = newTemp(ty);
5447 IRTemp rB = newTemp(ty);
5448 IRTemp outofrange = newTemp(Ity_I8);
5449 IRTemp rS_lo32 = newTemp(Ity_I32);
5450 IRTemp rB_lo32 = newTemp(Ity_I32);
5453 assign( rS, getIReg(rS_addr) );
5454 assign( rB, getIReg(rB_addr) );
5455 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
5456 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
5460 case 0x018: { // slw (Shift Left Word, PPC32 p505)
5461 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5462 rA_addr, rS_addr, rB_addr);
5464 /* ppc32 semantics are:
5465 slw(x,y) = (x << (y & 31)) -- primary result
5466 & ~((y << 26) >>s 31) -- make result 0
5475 mkexpr(rB_lo32), mkU32(31)))),
5478 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
5480 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
5484 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
5485 IRTemp sh_amt = newTemp(Ity_I32);
5486 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5487 rA_addr, rS_addr, rB_addr);
5488 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
5490 rA = Sar32( rS, amt > 31 ? 31 : amt )
5491 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
5493 assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
5497 binop(Iop_CmpLT32U, mkU32(31),
5499 e_tmp = binop( Iop_Sar32,
5502 IRExpr_Mux0X( mkexpr(outofrange),
5505 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
5507 set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
5509 mkWidenFrom32(ty, mkexpr(rS_lo32), True),
5510 mkWidenFrom32(ty, mkexpr(sh_amt), True ),
5511 mkWidenFrom32(ty, getXER_CA32(), True) );
5515 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
5516 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
5517 rA_addr, rS_addr, sh_imm);
5518 vassert(sh_imm < 32);
5520 assign( rA, binop(Iop_Sar64,
5521 binop(Iop_Shl64, getIReg(rS_addr),
5523 mkU8(32 + sh_imm)) );
5525 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
5529 set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
5531 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
5532 mkSzImm(ty, sh_imm),
5533 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
5536 case 0x218: // srw (Shift Right Word, PPC32 p508)
5537 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5538 rA_addr, rS_addr, rB_addr);
5539 /* rA = rS >>u rB */
5540 /* ppc32 semantics are:
5541 srw(x,y) = (x >>u (y & 31)) -- primary result
5542 & ~((y << 26) >>s 31) -- make result 0
5551 binop(Iop_And32, mkexpr(rB_lo32),
5555 binop(Iop_Shl32, mkexpr(rB_lo32),
5558 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
5563 case 0x01B: // sld (Shift Left DWord, PPC64 p568)
5564 DIP("sld%s r%u,r%u,r%u\n",
5565 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
5567 /* ppc64 semantics are:
5568 slw(x,y) = (x << (y & 63)) -- primary result
5569 & ~((y << 57) >>s 63) -- make result 0
5578 binop(Iop_And64, mkexpr(rB), mkU64(63)))),
5581 binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
5585 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
5586 IRTemp sh_amt = newTemp(Ity_I64);
5587 DIP("srad%s r%u,r%u,r%u\n",
5588 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
5590 rA = Sar64( rS, amt > 63 ? 63 : amt )
5591 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
5593 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
5596 binop(Iop_CmpLT64U, mkU64(63),
5602 IRExpr_Mux0X( mkexpr(outofrange),
5606 set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
5607 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
5608 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
5612 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
5614 vassert(sh_imm < 64);
5615 DIP("sradi%s r%u,r%u,%u\n",
5616 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
5617 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
5619 set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
5623 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
5626 case 0x21B: // srd (Shift Right DWord, PPC64 p574)
5627 DIP("srd%s r%u,r%u,r%u\n",
5628 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
5629 /* rA = rS >>u rB */
5630 /* ppc semantics are:
5631 srw(x,y) = (x >>u (y & 63)) -- primary result
5632 & ~((y << 57) >>s 63) -- make result 0
5641 binop(Iop_And64, mkexpr(rB), mkU64(63)))),
5644 binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
5649 vex_printf("dis_int_shift(ppc)(opc2)\n");
5653 vex_printf("dis_int_shift(ppc)(opc1)\n");
5657 putIReg( rA_addr, mkexpr(rA) );
5660 set_CR0( mkexpr(rA) );
5668 Integer Load/Store Reverse Instructions
5670 /* Generates code to swap the byte order in an Ity_I32. */
5671 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
5673 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
5676 binop(Iop_Shl32, mkexpr(t), mkU8(24)),
5678 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
5681 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
5683 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
5688 /* Generates code to swap the byte order in the lower half of an Ity_I32,
5689 and zeroes the upper half. */
5690 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
5692 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
5695 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
5697 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
5702 static Bool dis_int_ldst_rev ( UInt theInstr )
5705 UChar opc1 = ifieldOPC(theInstr);
5706 UChar rD_addr = ifieldRegDS(theInstr);
5707 UChar rS_addr = rD_addr;
5708 UChar rA_addr = ifieldRegA(theInstr);
5709 UChar rB_addr = ifieldRegB(theInstr);
5710 UInt opc2 = ifieldOPClo10(theInstr);
5711 UChar b0 = ifieldBIT0(theInstr);
5713 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5714 IRTemp EA = newTemp(ty);
5715 IRTemp w1 = newTemp(Ity_I32);
5716 IRTemp w2 = newTemp(Ity_I32);
5718 if (opc1 != 0x1F || b0 != 0) {
5719 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
5723 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5727 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
5728 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5729 assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) );
5730 assign( w2, gen_byterev16(w1) );
5731 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
5732 /* Signed */False) );
5735 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
5736 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5737 assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
5738 assign( w2, gen_byterev32(w1) );
5739 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
5740 /* Signed */False) );
5743 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
5746 IRTemp w3 = newTemp( Ity_I32 );
5747 IRTemp w4 = newTemp( Ity_I32 );
5748 DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5749 assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) );
5750 assign( w2, gen_byterev32( w1 ) );
5751 nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
5752 ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
5753 assign( w3, loadBE( Ity_I32, nextAddr ) );
5754 assign( w4, gen_byterev32( w3 ) );
5755 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
5759 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
5760 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5761 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
5762 storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
5765 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
5766 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5767 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
5768 storeBE( mkexpr(EA), gen_byterev32(w1) );
5772 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
5781 Processor Control Instructions
5783 static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr )
5785 UChar opc1 = ifieldOPC(theInstr);
5788 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
5789 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
5790 UChar rD_addr = ifieldRegDS(theInstr);
5791 UInt b11to20 = IFIELD( theInstr, 11, 10 );
5794 UChar rS_addr = rD_addr;
5797 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) );
5798 UInt CRM = IFIELD( theInstr, 12, 8 );
5799 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) );
5801 UInt opc2 = ifieldOPClo10(theInstr);
5802 UChar b0 = ifieldBIT0(theInstr);
5804 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5805 IRTemp rS = newTemp(ty);
5806 assign( rS, getIReg(rS_addr) );
5808 /* Reorder SPR field as per PPC32 p470 */
5809 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
5810 /* Reorder TBR field as per PPC32 p475 */
5811 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
5813 if (opc1 != 0x1F || b0 != 0) {
5814 vex_printf("dis_proc_ctl(ppc)(opc1|b0)\n");
5820 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
5821 if (b21to22 != 0 || b11to20 != 0) {
5822 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
5825 DIP("mcrxr crf%d\n", crfD);
5826 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
5827 putGST_field( PPC_GST_CR,
5828 getGST_field( PPC_GST_XER, 7 ),
5832 putXER_SO( mkU8(0) );
5833 putXER_OV( mkU8(0) );
5834 putXER_CA( mkU8(0) );
5839 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467)
5840 // b20==1 & b11==0: mfocrf (Move from One CR Field)
5841 // However it seems that the 'mfcr' behaviour is an acceptable
5842 // implementation of mfocr (from the 2.02 arch spec)
5844 DIP("mfcr r%u\n", rD_addr);
5845 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
5846 /* Signed */False) );
5849 if (b20 == 1 && b11 == 0) {
5850 DIP("mfocrf r%u,%u\n", rD_addr, CRM);
5851 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
5852 /* Signed */False) );
5859 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
5861 switch (SPR) { // Choose a register...
5863 DIP("mfxer r%u\n", rD_addr);
5864 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
5865 /* Signed */False) );
5868 DIP("mflr r%u\n", rD_addr);
5869 putIReg( rD_addr, getGST( PPC_GST_LR ) );
5872 DIP("mfctr r%u\n", rD_addr);
5873 putIReg( rD_addr, getGST( PPC_GST_CTR ) );
5876 DIP("mfvrsave r%u\n", rD_addr);
5877 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
5878 /* Signed */False) );
5882 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
5883 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
5886 /* Even a lowly PPC7400 can run the associated helper, so no
5887 obvious need for feature testing at this point. */
5888 case 268 /* 0x10C */:
5889 case 269 /* 0x10D */: {
5890 UInt arg = SPR==268 ? 0 : 1;
5891 IRTemp val = newTemp(Ity_I32);
5892 IRExpr** args = mkIRExprVec_1( mkU32(arg) );
5893 IRDirty* d = unsafeIRDirty_1_N(
5896 "ppc32g_dirtyhelper_MFSPR_268_269",
5898 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
5901 /* execute the dirty call, dumping the result in val. */
5902 stmt( IRStmt_Dirty(d) );
5904 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
5905 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
5909 /* Again, runs natively on PPC7400 (7447, really). Not
5910 bothering with a feature test. */
5911 case 287: /* 0x11F */ {
5912 IRTemp val = newTemp(Ity_I32);
5913 IRExpr** args = mkIRExprVec_0();
5914 IRDirty* d = unsafeIRDirty_1_N(
5917 "ppc32g_dirtyhelper_MFSPR_287",
5919 (vbi, &ppc32g_dirtyhelper_MFSPR_287),
5922 /* execute the dirty call, dumping the result in val. */
5923 stmt( IRStmt_Dirty(d) );
5925 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
5926 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
5931 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
5936 case 0x173: { // mftb (Move from Time Base, PPC32 p475)
5937 IRTemp val = newTemp(Ity_I64);
5938 IRExpr** args = mkIRExprVec_0();
5939 IRDirty* d = unsafeIRDirty_1_N(
5942 "ppcg_dirtyhelper_MFTB",
5943 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
5945 /* execute the dirty call, dumping the result in val. */
5946 stmt( IRStmt_Dirty(d) );
5950 DIP("mftbu r%u", rD_addr);
5952 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
5953 /* Signed */False) );
5956 DIP("mftb r%u", rD_addr);
5957 putIReg( rD_addr, (mode64) ? mkexpr(val) :
5958 unop(Iop_64to32, mkexpr(val)) );
5961 return False; /* illegal instruction */
5967 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
5968 // b20==1: mtocrf (Move to One Cond Reg Field)
5974 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
5975 1 field is written. It seems more robust to decline to
5976 decode the insn if so. */
5978 case 0x01: case 0x02: case 0x04: case 0x08:
5979 case 0x10: case 0x20: case 0x40: case 0x80:
5985 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
5987 /* Write to each field specified by CRM */
5988 for (cr = 0; cr < 8; cr++) {
5989 if ((CRM & (1 << (7-cr))) == 0)
5992 putGST_field( PPC_GST_CR,
5994 mkNarrowTo32(ty, mkexpr(rS)),
6000 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
6002 switch (SPR) { // Choose a register...
6004 DIP("mtxer r%u\n", rS_addr);
6005 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
6008 DIP("mtlr r%u\n", rS_addr);
6009 putGST( PPC_GST_LR, mkexpr(rS) );
6012 DIP("mtctr r%u\n", rS_addr);
6013 putGST( PPC_GST_CTR, mkexpr(rS) );
6016 DIP("mtvrsave r%u\n", rS_addr);
6017 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
6021 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
6027 vex_printf("dis_proc_ctl(ppc)(opc2)\n");
6035 Cache Management Instructions
6037 static Bool dis_cache_manage ( UInt theInstr,
6039 VexArchInfo* guest_archinfo )
6042 UChar opc1 = ifieldOPC(theInstr);
6043 UChar b21to25 = ifieldRegDS(theInstr);
6044 UChar rA_addr = ifieldRegA(theInstr);
6045 UChar rB_addr = ifieldRegB(theInstr);
6046 UInt opc2 = ifieldOPClo10(theInstr);
6047 UChar b0 = ifieldBIT0(theInstr);
6048 UInt lineszB = guest_archinfo->ppc_cache_line_szB;
6049 Bool is_dcbzl = False;
6051 IRType ty = mode64 ? Ity_I64 : Ity_I32;
6053 /* For dcbt, the lowest two bits of b21to25 encode an
6054 access-direction hint (TH field) which we ignore. Well, that's
6055 what the PowerPC documentation says. In fact xlc -O4 on POWER5
6056 seems to generate values of 8 and 10 for b21to25. */
6057 if (opc1 == 0x1F && opc2 == 0x116) {
6058 /* b21to25 &= ~3; */ /* if the docs were true */
6059 b21to25 = 0; /* blunt instrument */
6061 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
6065 if (!(guest_archinfo->ppc_dcbzl_szB)) {
6066 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
6072 if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
6073 if (0) vex_printf("dis_cache_manage %d %d %d\n",
6074 (Int)opc1, (Int)b21to25, (Int)b0);
6075 vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n");
6080 vassert(lineszB == 32 || lineszB == 64 || lineszB == 128);
6083 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
6084 //zz vassert(0); /* AWAITING TEST CASE */
6085 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
6086 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n");
6089 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
6090 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
6091 /* nop as far as vex is concerned */
6094 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
6095 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
6096 /* nop as far as vex is concerned */
6099 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
6100 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
6101 /* nop as far as vex is concerned */
6104 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
6105 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
6106 /* nop as far as vex is concerned */
6109 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
6110 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
6111 /* Clear all bytes in cache block at (rA|0) + rB. */
6112 IRTemp EA = newTemp(ty);
6113 IRTemp addr = newTemp(ty);
6118 clearszB = guest_archinfo->ppc_dcbzl_szB;
6119 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
6122 clearszB = guest_archinfo->ppc_dcbz_szB;
6123 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
6126 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6129 /* Round EA down to the start of the containing block. */
6130 assign( addr, binop( Iop_And64,
6132 mkU64( ~((ULong)clearszB-1) )) );
6134 for (i = 0; i < clearszB / 8; i++) {
6135 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
6136 storeBE( irx_addr, mkU64(0) );
6139 /* Round EA down to the start of the containing block. */
6140 assign( addr, binop( Iop_And32,
6142 mkU32( ~(clearszB-1) )) );
6144 for (i = 0; i < clearszB / 4; i++) {
6145 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
6146 storeBE( irx_addr, mkU32(0) );
6153 // icbi (Instruction Cache Block Invalidate, PPC32 p431)
6154 /* Invalidate all translations containing code from the cache
6155 block at (rA|0) + rB. */
6156 IRTemp EA = newTemp(ty);
6157 IRTemp addr = newTemp(ty);
6158 DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
6159 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6161 /* Round EA down to the start of the containing block. */
6162 assign( addr, binop( mkSzOp(ty, Iop_And8),
6164 mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
6165 putGST( PPC_GST_TISTART, mkexpr(addr) );
6166 putGST( PPC_GST_TILEN, mkSzImm(ty, lineszB) );
6168 /* be paranoid ... */
6169 stmt( IRStmt_MBE(Imbe_Fence) );
6171 irsb->jumpkind = Ijk_TInval;
6172 irsb->next = mkSzImm(ty, nextInsnAddr());
6173 dres->whatNext = Dis_StopHere;
6178 vex_printf("dis_cache_manage(ppc)(opc2)\n");
6185 /*------------------------------------------------------------*/
6186 /*--- Floating Point Helpers ---*/
6187 /*------------------------------------------------------------*/
6189 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
6190 /* Produces a value in 0 .. 3, which is encoded as per the type
6191 IRRoundingMode. PPCRoundingMode encoding is different to
6192 IRRoundingMode, so need to map it.
6194 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
6197 rounding mode | PPC | IR
6198 ------------------------
6199 to nearest | 00 | 00
6201 to +infinity | 10 | 10
6202 to -infinity | 11 | 01
6204 IRTemp rm_PPC32 = newTemp(Ity_I32);
6205 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
6207 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
6208 return binop( Iop_Xor32,
6211 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
6216 /*------------------------------------------------------------*/
6217 /*--- Floating Point Instruction Translation ---*/
6218 /*------------------------------------------------------------*/
6221 Floating Point Load Instructions
6223 static Bool dis_fp_load ( UInt theInstr )
6225 /* X-Form, D-Form */
6226 UChar opc1 = ifieldOPC(theInstr);
6227 UChar frD_addr = ifieldRegDS(theInstr);
6228 UChar rA_addr = ifieldRegA(theInstr);
6229 UChar rB_addr = ifieldRegB(theInstr);
6230 UInt opc2 = ifieldOPClo10(theInstr);
6231 UChar b0 = ifieldBIT0(theInstr);
6232 UInt uimm16 = ifieldUIMM16(theInstr);
6234 Int simm16 = extend_s_16to32(uimm16);
6235 IRType ty = mode64 ? Ity_I64 : Ity_I32;
6236 IRTemp EA = newTemp(ty);
6237 IRTemp rA = newTemp(ty);
6238 IRTemp rB = newTemp(ty);
6239 IRTemp iHi = newTemp(Ity_I32);
6240 IRTemp iLo = newTemp(Ity_I32);
6242 assign( rA, getIReg(rA_addr) );
6243 assign( rB, getIReg(rB_addr) );
6245 /* These are completely straightforward from a rounding and status
6246 bits perspective: no rounding involved and no funny status or CR
6250 case 0x30: // lfs (Load Float Single, PPC32 p441)
6251 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6252 assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6254 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6257 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
6260 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6261 assign( EA, ea_rA_simm(rA_addr, simm16) );
6263 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6264 putIReg( rA_addr, mkexpr(EA) );
6267 case 0x32: // lfd (Load Float Double, PPC32 p437)
6268 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6269 assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6270 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6273 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
6276 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6277 assign( EA, ea_rA_simm(rA_addr, simm16) );
6278 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6279 putIReg( rA_addr, mkexpr(EA) );
6284 vex_printf("dis_fp_load(ppc)(instr,b0)\n");
6289 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
6290 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6291 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6292 putFReg( frD_addr, unop( Iop_F32toF64,
6293 loadBE(Ity_F32, mkexpr(EA))) );
6296 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
6299 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6300 assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6302 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6303 putIReg( rA_addr, mkexpr(EA) );
6306 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
6307 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6308 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6309 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6312 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
6315 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6316 assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6317 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6318 putIReg( rA_addr, mkexpr(EA) );
6321 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
6322 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6323 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6324 assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
6325 assign( iHi, binop(Iop_Sub32,
6327 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) );
6328 putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
6329 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
6332 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
6334 IRTemp dw = newTemp( Ity_I64 );
6335 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6336 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6337 assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
6338 assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
6339 putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
6344 vex_printf("dis_fp_load(ppc)(opc2)\n");
6350 vex_printf("dis_fp_load(ppc)(opc1)\n");
6359 Floating Point Store Instructions
6361 static Bool dis_fp_store ( UInt theInstr )
6363 /* X-Form, D-Form */
6364 UChar opc1 = ifieldOPC(theInstr);
6365 UChar frS_addr = ifieldRegDS(theInstr);
6366 UChar rA_addr = ifieldRegA(theInstr);
6367 UChar rB_addr = ifieldRegB(theInstr);
6368 UInt opc2 = ifieldOPClo10(theInstr);
6369 UChar b0 = ifieldBIT0(theInstr);
6370 Int uimm16 = ifieldUIMM16(theInstr);
6372 Int simm16 = extend_s_16to32(uimm16);
6373 IRTemp frS = newTemp(Ity_F64);
6374 IRType ty = mode64 ? Ity_I64 : Ity_I32;
6375 IRTemp EA = newTemp(ty);
6376 IRTemp rA = newTemp(ty);
6377 IRTemp rB = newTemp(ty);
6379 assign( frS, getFReg(frS_addr) );
6380 assign( rA, getIReg(rA_addr) );
6381 assign( rB, getIReg(rB_addr) );
6383 /* These are straightforward from a status bits perspective: no
6384 funny status or CR bits affected. For single precision stores,
6385 the values are truncated and denormalised (not rounded) to turn
6386 them into single precision values. */
6390 case 0x34: // stfs (Store Float Single, PPC32 p518)
6391 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6392 assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6393 /* Use Iop_TruncF64asF32 to truncate and possible denormalise
6394 the value to be stored in the correct way, without any
6396 storeBE( mkexpr(EA),
6397 unop(Iop_TruncF64asF32, mkexpr(frS)) );
6400 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
6403 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6404 assign( EA, ea_rA_simm(rA_addr, simm16) );
6405 /* See comment for stfs */
6406 storeBE( mkexpr(EA),
6407 unop(Iop_TruncF64asF32, mkexpr(frS)) );
6408 putIReg( rA_addr, mkexpr(EA) );
6411 case 0x36: // stfd (Store Float Double, PPC32 p513)
6412 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6413 assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6414 storeBE( mkexpr(EA), mkexpr(frS) );
6417 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
6420 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6421 assign( EA, ea_rA_simm(rA_addr, simm16) );
6422 storeBE( mkexpr(EA), mkexpr(frS) );
6423 putIReg( rA_addr, mkexpr(EA) );
6428 vex_printf("dis_fp_store(ppc)(instr,b0)\n");
6432 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
6433 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6434 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6435 /* See note for stfs */
6436 storeBE( mkexpr(EA),
6437 unop(Iop_TruncF64asF32, mkexpr(frS)) );
6440 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
6443 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6444 assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6445 /* See note for stfs */
6446 storeBE( mkexpr(EA),
6447 unop(Iop_TruncF64asF32, mkexpr(frS)) );
6448 putIReg( rA_addr, mkexpr(EA) );
6451 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
6452 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6453 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6454 storeBE( mkexpr(EA), mkexpr(frS) );
6457 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
6460 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6461 assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6462 storeBE( mkexpr(EA), mkexpr(frS) );
6463 putIReg( rA_addr, mkexpr(EA) );
6466 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
6467 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6468 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6469 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6470 storeBE( mkexpr(EA),
6471 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
6475 vex_printf("dis_fp_store(ppc)(opc2)\n");
6481 vex_printf("dis_fp_store(ppc)(opc1)\n");
6490 Floating Point Arith Instructions
6492 static Bool dis_fp_arith ( UInt theInstr )
6495 UChar opc1 = ifieldOPC(theInstr);
6496 UChar frD_addr = ifieldRegDS(theInstr);
6497 UChar frA_addr = ifieldRegA(theInstr);
6498 UChar frB_addr = ifieldRegB(theInstr);
6499 UChar frC_addr = ifieldRegC(theInstr);
6500 UChar opc2 = ifieldOPClo5(theInstr);
6501 UChar flag_rC = ifieldBIT0(theInstr);
6503 IRTemp frD = newTemp(Ity_F64);
6504 IRTemp frA = newTemp(Ity_F64);
6505 IRTemp frB = newTemp(Ity_F64);
6506 IRTemp frC = newTemp(Ity_F64);
6507 IRExpr* rm = get_IR_roundingmode();
6509 /* By default, we will examine the results of the operation and set
6510 fpscr[FPRF] accordingly. */
6511 Bool set_FPRF = True;
6513 /* By default, if flag_RC is set, we will clear cr1 after the
6514 operation. In reality we should set cr1 to indicate the
6515 exception status of the operation, but since we're not
6516 simulating exceptions, the exception status will appear to be
6517 zero. Hence cr1 should be cleared if this is a . form insn. */
6518 Bool clear_CR1 = True;
6520 assign( frA, getFReg(frA_addr));
6521 assign( frB, getFReg(frB_addr));
6522 assign( frC, getFReg(frC_addr));
6527 case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
6530 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6531 frD_addr, frA_addr, frB_addr);
6532 assign( frD, triop( Iop_DivF64r32,
6533 rm, mkexpr(frA), mkexpr(frB) ));
6536 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
6539 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6540 frD_addr, frA_addr, frB_addr);
6541 assign( frD, triop( Iop_SubF64r32,
6542 rm, mkexpr(frA), mkexpr(frB) ));
6545 case 0x15: // fadds (Floating Add Single, PPC32 p401)
6548 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6549 frD_addr, frA_addr, frB_addr);
6550 assign( frD, triop( Iop_AddF64r32,
6551 rm, mkexpr(frA), mkexpr(frB) ));
6554 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
6555 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
6556 if (frA_addr != 0 || frC_addr != 0)
6558 DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
6559 frD_addr, frB_addr);
6560 // however illogically, on ppc970 this insn behaves identically
6561 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32.
6562 assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
6565 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
6566 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6567 if (frA_addr != 0 || frC_addr != 0)
6569 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
6570 frD_addr, frB_addr);
6572 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
6573 assign( frD, triop( Iop_DivF64r32,
6575 ieee_one, mkexpr(frB) ));
6579 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
6582 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6583 frD_addr, frA_addr, frC_addr);
6584 assign( frD, triop( Iop_MulF64r32,
6585 rm, mkexpr(frA), mkexpr(frC) ));
6588 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
6589 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6590 // Undocumented instruction?
6591 if (frA_addr != 0 || frC_addr != 0)
6593 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
6594 frD_addr, frB_addr);
6595 assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
6599 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
6606 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
6609 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6610 frD_addr, frA_addr, frB_addr);
6611 assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
6614 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
6617 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6618 frD_addr, frA_addr, frB_addr);
6619 assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
6622 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
6625 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6626 frD_addr, frA_addr, frB_addr);
6627 assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
6630 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
6631 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
6632 if (frA_addr != 0 || frC_addr != 0)
6634 DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
6635 frD_addr, frB_addr);
6636 assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
6639 case 0x17: { // fsel (Floating Select, PPC32 p426)
6640 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6641 IRTemp cc = newTemp(Ity_I32);
6642 IRTemp cc_b0 = newTemp(Ity_I32);
6644 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6645 frD_addr, frA_addr, frC_addr, frB_addr);
6647 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
6648 // => GT|EQ == (cc & 0x1 == 0)
6649 assign( cc, binop(Iop_CmpF64, mkexpr(frA),
6650 IRExpr_Const(IRConst_F64(0))) );
6651 assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
6653 // frD = (frA >= 0.0) ? frC : frB
6654 // = (cc_b0 == 0) ? frC : frB
6658 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0))),
6662 /* One of the rare ones which don't mess with FPRF */
6667 case 0x18: // fre (Floating Reciprocal Estimate)
6668 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6669 // Note: unclear whether this insn really exists or not
6670 // ppc970 doesn't have it, but POWER5 does
6671 if (frA_addr != 0 || frC_addr != 0)
6673 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
6674 frD_addr, frB_addr);
6676 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
6677 assign( frD, triop( Iop_DivF64,
6679 ieee_one, mkexpr(frB) ));
6683 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
6685 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
6686 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6687 frD_addr, frA_addr, frC_addr);
6688 assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
6691 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
6692 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6693 if (frA_addr != 0 || frC_addr != 0)
6695 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
6696 frD_addr, frB_addr);
6697 assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
6701 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
6707 vex_printf("dis_fp_arith(ppc)(opc1)\n");
6711 putFReg( frD_addr, mkexpr(frD) );
6714 // XXX XXX XXX FIXME
6715 // set FPRF from frD
6718 if (flag_rC && clear_CR1) {
6719 putCR321( 1, mkU8(0) );
6720 putCR0( 1, mkU8(0) );
6729 Floating Point Mult-Add Instructions
6731 static Bool dis_fp_multadd ( UInt theInstr )
6734 UChar opc1 = ifieldOPC(theInstr);
6735 UChar frD_addr = ifieldRegDS(theInstr);
6736 UChar frA_addr = ifieldRegA(theInstr);
6737 UChar frB_addr = ifieldRegB(theInstr);
6738 UChar frC_addr = ifieldRegC(theInstr);
6739 UChar opc2 = ifieldOPClo5(theInstr);
6740 UChar flag_rC = ifieldBIT0(theInstr);
6742 IRTemp frD = newTemp(Ity_F64);
6743 IRTemp frA = newTemp(Ity_F64);
6744 IRTemp frB = newTemp(Ity_F64);
6745 IRTemp frC = newTemp(Ity_F64);
6746 IRTemp rmt = newTemp(Ity_I32);
6749 /* By default, we will examine the results of the operation and set
6750 fpscr[FPRF] accordingly. */
6751 Bool set_FPRF = True;
6753 /* By default, if flag_RC is set, we will clear cr1 after the
6754 operation. In reality we should set cr1 to indicate the
6755 exception status of the operation, but since we're not
6756 simulating exceptions, the exception status will appear to be
6757 zero. Hence cr1 should be cleared if this is a . form insn. */
6758 Bool clear_CR1 = True;
6760 /* Bind the rounding mode expression to a temp; there's no
6761 point in creating gratuitous CSEs, as we know we'll need
6763 assign( rmt, get_IR_roundingmode() );
6766 assign( frA, getFReg(frA_addr));
6767 assign( frB, getFReg(frB_addr));
6768 assign( frC, getFReg(frC_addr));
6770 /* The rounding in this is all a bit dodgy. The idea is to only do
6771 one rounding. That clearly isn't achieveable without dedicated
6772 four-input IR primops, although in the single precision case we
6773 can sort-of simulate it by doing the inner multiply in double
6776 In the negated cases, the negation happens after rounding. */
6781 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
6782 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6783 frD_addr, frA_addr, frC_addr, frB_addr);
6784 assign( frD, qop( Iop_MSubF64r32, rm,
6785 mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
6788 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
6789 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6790 frD_addr, frA_addr, frC_addr, frB_addr);
6791 assign( frD, qop( Iop_MAddF64r32, rm,
6792 mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
6795 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
6796 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6797 frD_addr, frA_addr, frC_addr, frB_addr);
6798 assign( frD, unop( Iop_NegF64,
6799 qop( Iop_MSubF64r32, rm,
6800 mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
6803 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
6804 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6805 frD_addr, frA_addr, frC_addr, frB_addr);
6806 assign( frD, unop( Iop_NegF64,
6807 qop( Iop_MAddF64r32, rm,
6808 mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
6812 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
6819 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
6820 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6821 frD_addr, frA_addr, frC_addr, frB_addr);
6822 assign( frD, qop( Iop_MSubF64, rm,
6823 mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
6826 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
6827 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6828 frD_addr, frA_addr, frC_addr, frB_addr);
6829 assign( frD, qop( Iop_MAddF64, rm,
6830 mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
6833 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
6834 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6835 frD_addr, frA_addr, frC_addr, frB_addr);
6836 assign( frD, unop( Iop_NegF64,
6837 qop( Iop_MSubF64, rm,
6838 mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
6841 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
6842 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
6843 frD_addr, frA_addr, frC_addr, frB_addr);
6844 assign( frD, unop( Iop_NegF64,
6845 qop( Iop_MAddF64, rm,
6846 mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
6850 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
6856 vex_printf("dis_fp_multadd(ppc)(opc1)\n");
6860 putFReg( frD_addr, mkexpr(frD) );
6863 // XXX XXX XXX FIXME
6864 // set FPRF from frD
6867 if (flag_rC && clear_CR1) {
6868 putCR321( 1, mkU8(0) );
6869 putCR0( 1, mkU8(0) );
6876 * fe_flag is set to 1 if any of the following conditions occurs:
6877 * - The double-precision floating-point operand in register FRA is a NaN or an
6879 * - The double-precision floating-point operand in register FRB is a Zero, a
6880 * NaN, or an Infinity.
6881 * - e_b is less than or equal to -1022.
6882 * - e_b is greater than or equal to 1021.
6883 * - The double-precision floating-point operand in register FRA is not a zero
6884 * and the difference, e_a - e_b, is greater than or equal to 1023.
6885 * - The double-precision floating-point operand in register FRA is not a zero
6886 * and the difference, e_a - e_b, is less than or equal to -1021.
6887 * - The double-precision floating-point operand in register FRA is not a zero
6888 * and e_a is less than or equal to -970
6889 * Otherwise fe_flag is set to 0.
6891 * fg_flag is set to 1 if either of the following conditions occurs.
6892 * - The double-precision floating-point operand in register FRA is an Infinity.
6893 * - The double-precision floating-point operand in register FRB is a Zero, an
6894 * Infinity, or a denormalized value.
6895 * Otherwise fg_flag is set to 0.
6898 static Bool dis_fp_ftdiv ( UInt theInstr )
6900 UChar opc1 = ifieldOPC(theInstr);
6901 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
6902 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
6903 UChar frA_addr = ifieldRegA(theInstr);
6904 UChar frB_addr = ifieldRegB(theInstr);
6905 UChar b0 = ifieldBIT0(theInstr);
6907 // The following temps are for holding intermediate results
6908 IRTemp frA_I64 = newTemp(Ity_I64);
6909 IRTemp frB_I64 = newTemp(Ity_I64);
6910 IRTemp e_a = newTemp(Ity_I32);
6911 IRTemp e_b = newTemp(Ity_I32);
6912 IRTemp frA_exp_shR = newTemp(Ity_I32);
6913 IRTemp frB_exp_shR = newTemp(Ity_I32);
6917 /* The following variables hold boolean results from tests
6918 * that are OR'ed together for setting the fe_ and fg_ flags.
6919 * For some cases, the booleans are used more than once, so
6920 * I make those IRTemp's instead of IRExpr's.
6922 IRExpr * fraNaN, * frbNaN, * frbDenorm;
6923 IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
6924 IRTemp fraInf_tmp = newTemp(Ity_I1);
6925 IRTemp frbZero_tmp = newTemp(Ity_I1);
6926 IRTemp frbInf_tmp = newTemp(Ity_I1);
6927 IRTemp fraNotZero_tmp = newTemp(Ity_I1);
6929 /* The following are the flags that are set by OR'ing the results of
6930 * all the tests done for ftdiv. These flags are the input to the specified CR.
6932 IRExpr * fe_flag, * fl_flag, * fg_flag;
6935 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
6936 vex_printf("dis_fp_ftdiv(ppc)(instr)\n");
6940 // Create temps that will be used throughout the following tests.
6941 assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
6942 assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
6943 assign( frA_exp_shR, fp_exp_part( frA_I64 ) );
6944 assign( frB_exp_shR, fp_exp_part( frB_I64 ) );
6945 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
6946 assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
6947 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
6950 ////////////////// fe_flag tests BEGIN //////////////////////
6951 /* We first do all tests that may result in setting fe_flag to '1'. */
6954 * Test if the double-precision floating-point operand in register FRA is
6956 * exp = 7ff and fraction is non-zero; s = 0/1
6958 fraNaN = is_NaN(frA_I64);
6960 * Test if the double-precision floating-point operand in register FRA is
6962 * exp = 7ff and fraction is zero; s = 0/1
6964 assign(fraInf_tmp, is_Inf(frA_I64));
6967 * Test if the double-precision floating-point operand in register FRB is
6969 * exp = 7ff and fraction is non-zero; s = 0/1
6971 frbNaN = is_NaN(frB_I64);
6973 * Test if the double-precision floating-point operand in register FRB is
6975 * exp = 7ff and fraction is zero; s = 0/1
6977 assign( frbInf_tmp, is_Inf(frB_I64) );
6979 * Test if the double-precision floating-point operand in register FRB is
6981 * exp is zero and fraction is zero; s = 0/1
6983 assign( frbZero_tmp, is_Zero(frB_I64) );
6986 * Test if e_b <= -1022
6989 UInt test_value = 0xfffffc02; //Int test_value = -1022;
6990 eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
6994 * Test if e_b >= 1021
6998 Int test_value = 1021;
6999 eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
7003 * Test if FRA != Zero and (e_a - e_b) >= 1023
7004 * ==> FRA != Zero && (1023 < (e_a - e_b)
7006 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_I64 ) ) );
7007 ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
7008 binop( Iop_CmpLT32S, mkU32( bias ),
7009 binop( Iop_Sub32, mkexpr( e_a ),
7010 mkexpr( e_b ) ) ) );
7013 * Test if FRA != Zero and (e_a - e_b) <= -1021
7016 UInt test_value = 0xfffffc03; //Int test_value = -1021;
7018 ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
7019 binop( Iop_CmpLE32S,
7023 mkU32( test_value ) ) );
7027 * Test if FRA != Zero and e_a <= -970
7030 UInt test_value = 0xfffffc36; //Int test_value = -970;
7032 ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
7034 mkU32( test_value ) ) );
7036 ////////////////// fe_flag tests END //////////////////////
7038 ////////////////// fg_flag tests BEGIN //////////////////////
7040 * The following tests were already performed above in the fe_flag
7041 * tests. So these conditions will result in both fe_ and fg_ flags
7043 * - Test if FRA is an Infinity
7044 * - Test if FRB ix Zero
7045 * - Test if FRB is an Infinity
7049 * Test if FRB holds a denormalized value. A denormalized value is one where
7050 * the exp is 0 and the fraction is non-zero.
7053 IRExpr * hi32, * low32, * fraction_is_nonzero;
7054 IRTemp frac_part = newTemp(Ity_I64);
7056 assign( frac_part, FP_FRAC_PART(frB_I64) );
7057 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
7058 low32 = unop( Iop_64to32, mkexpr( frac_part ) );
7059 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
7061 frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
7062 mkU32( 0x0ULL ) ), fraction_is_nonzero );
7065 ////////////////// fg_flag tests END //////////////////////
7067 /////////////////////////
7068 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
7069 * where fl_flag == 1 on ppc64.
7071 fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
7078 mkexpr( fraInf_tmp ),
7080 mkexpr( frbZero_tmp ),
7084 mkexpr( frbInf_tmp ),
7089 ea_LTE ) ) ) ) ) ) ) ) );
7091 fe_flag = unop(Iop_1Uto32, fe_flag);
7093 fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
7094 mkOR1( mkexpr( frbInf_tmp ),
7096 fg_flag = unop(Iop_1Uto32, fg_flag);
7098 putGST_field( PPC_GST_CR, binop( Iop_Or32,
7100 binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
7101 binop( Iop_Shl32, fg_flag, mkU8( 2 ) ) ),
7102 binop( Iop_Shl32, fe_flag, mkU8( 1 ) ) ), crfD );
7104 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7109 Floating Point Compare Instructions
7111 static Bool dis_fp_cmp ( UInt theInstr )
7114 UChar opc1 = ifieldOPC(theInstr);
7115 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
7116 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
7117 UChar frA_addr = ifieldRegA(theInstr);
7118 UChar frB_addr = ifieldRegB(theInstr);
7119 UInt opc2 = ifieldOPClo10(theInstr);
7120 UChar b0 = ifieldBIT0(theInstr);
7122 IRTemp ccIR = newTemp(Ity_I32);
7123 IRTemp ccPPC32 = newTemp(Ity_I32);
7125 IRTemp frA = newTemp(Ity_F64);
7126 IRTemp frB = newTemp(Ity_F64);
7128 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
7129 vex_printf("dis_fp_cmp(ppc)(instr)\n");
7133 assign( frA, getFReg(frA_addr));
7134 assign( frB, getFReg(frB_addr));
7136 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
7138 /* Map compare result from IR to PPC32 */
7140 FP cmp result | PPC | IR
7141 --------------------------
7148 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
7149 // | ((ccIR ^ (ccIR>>6)) & 1)
7163 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
7172 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
7181 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
7183 /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
7184 putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
7186 // XXX XXX XXX FIXME
7187 // Also write the result into FPRF (it's not entirely clear how)
7189 /* Note: Differences between fcmpu and fcmpo are only in exception
7190 flag settings, which aren't supported anyway. */
7192 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
7193 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7195 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
7196 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7199 vex_printf("dis_fp_cmp(ppc)(opc2)\n");
7208 Floating Point Rounding/Conversion Instructions
7210 static Bool dis_fp_round ( UInt theInstr )
7213 UChar opc1 = ifieldOPC(theInstr);
7214 UChar b16to20 = ifieldRegA(theInstr);
7215 UChar frD_addr = ifieldRegDS(theInstr);
7216 UChar frB_addr = ifieldRegB(theInstr);
7217 UInt opc2 = ifieldOPClo10(theInstr);
7218 UChar flag_rC = ifieldBIT0(theInstr);
7220 IRTemp frD = newTemp(Ity_F64);
7221 IRTemp frB = newTemp(Ity_F64);
7222 IRTemp r_tmp32 = newTemp(Ity_I32);
7223 IRTemp r_tmp64 = newTemp(Ity_I64);
7224 IRExpr* rm = get_IR_roundingmode();
7226 /* By default, we will examine the results of the operation and set
7227 fpscr[FPRF] accordingly. */
7228 Bool set_FPRF = True;
7230 /* By default, if flag_RC is set, we will clear cr1 after the
7231 operation. In reality we should set cr1 to indicate the
7232 exception status of the operation, but since we're not
7233 simulating exceptions, the exception status will appear to be
7234 zero. Hence cr1 should be cleared if this is a . form insn. */
7235 Bool clear_CR1 = True;
7236 if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
7237 vex_printf("dis_fp_round(ppc)(instr)\n");
7241 assign( frB, getFReg(frB_addr));
7242 // TODO : add support here for fcfdus
7244 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
7245 * they're very similar to the other instructions handled here, but have
7246 * a different primary opcode.
7249 case 0x34E: // fcfids (Float convert from signed DWord to single precision)
7250 DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7251 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7252 assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
7253 mkexpr( r_tmp64 ) ) ) );
7256 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
7257 DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7258 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7259 assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
7266 case 0x00C: // frsp (Float Round to Single, PPC32 p423)
7267 DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7268 assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
7271 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
7272 DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7274 binop(Iop_F64toI32S, rm, mkexpr(frB)) );
7275 assign( frD, unop( Iop_ReinterpI64asF64,
7276 unop( Iop_32Uto64, mkexpr(r_tmp32))));
7277 /* FPRF is undefined after fctiw. Leave unchanged. */
7281 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
7282 DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7284 binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
7285 assign( frD, unop( Iop_ReinterpI64asF64,
7286 unop( Iop_32Uto64, mkexpr(r_tmp32))));
7287 /* FPRF is undefined after fctiwz. Leave unchanged. */
7291 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
7292 DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7294 binop(Iop_F64toI64S, rm, mkexpr(frB)) );
7295 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
7296 /* FPRF is undefined after fctid. Leave unchanged. */
7300 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
7301 DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7303 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
7304 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
7305 /* FPRF is undefined after fctidz. Leave unchanged. */
7309 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
7310 DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7311 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7313 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
7316 case 0x3CE: // fcfidu (Float convert from unsigned DWord)
7317 DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7318 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7319 assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
7322 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
7324 case 0x188: // frin (Floating Round to Integer Nearest)
7325 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7327 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
7329 case 0x1A8: // friz (Floating Round to Integer Toward Zero)
7330 DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7332 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
7334 case 0x1C8: // frip (Floating Round to Integer Plus)
7335 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7337 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
7339 case 0x1E8: // frim (Floating Round to Integer Minus)
7340 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7342 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
7346 /* don't use the rounded integer if frB is outside -9e18..9e18 */
7347 /* F64 has only log10(2**52) significant digits anyway */
7348 /* need to preserve sign of zero */
7349 /* frD = (fabs(frB) > 9e18) ? frB :
7350 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */
7351 assign(frD, IRExpr_Mux0X( unop(Iop_32to8,
7353 IRExpr_Const(IRConst_F64(9e18)),
7354 unop(Iop_AbsF64, mkexpr(frB)))),
7355 IRExpr_Mux0X(unop(Iop_32to8,
7358 unop(Iop_ReinterpF64asI64,
7359 mkexpr(frB))), mkU8(31))),
7360 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ),
7363 binop(Iop_I64StoF64, mkU32(0),
7364 mkexpr(r_tmp64)) )) ),
7369 vex_printf("dis_fp_round(ppc)(opc2)\n");
7373 putFReg( frD_addr, mkexpr(frD) );
7376 // XXX XXX XXX FIXME
7377 // set FPRF from frD
7380 if (flag_rC && clear_CR1) {
7381 putCR321( 1, mkU8(0) );
7382 putCR0( 1, mkU8(0) );
7389 Floating Point Pair Instructions
7391 static Bool dis_fp_pair ( UInt theInstr )
7393 /* X-Form/DS-Form */
7394 UChar opc1 = ifieldOPC(theInstr);
7395 UChar frT_hi_addr = ifieldRegDS(theInstr);
7396 UChar frT_lo_addr = frT_hi_addr + 1;
7397 UChar rA_addr = ifieldRegA(theInstr);
7398 UChar rB_addr = ifieldRegB(theInstr);
7399 UInt uimm16 = ifieldUIMM16(theInstr);
7400 Int simm16 = extend_s_16to32(uimm16);
7401 UInt opc2 = ifieldOPClo10(theInstr);
7402 IRType ty = mode64 ? Ity_I64 : Ity_I32;
7403 IRTemp EA_hi = newTemp(ty);
7404 IRTemp EA_lo = newTemp(ty);
7405 IRTemp frT_hi = newTemp(Ity_F64);
7406 IRTemp frT_lo = newTemp(Ity_F64);
7407 UChar b0 = ifieldBIT0(theInstr);
7410 if ((frT_hi_addr %2) != 0) {
7411 vex_printf("dis_fp_pair(ppc) : odd frT register\n");
7416 case 0x1F: // register offset
7418 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125)
7419 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
7422 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125)
7423 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
7426 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
7431 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
7434 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
7436 case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125)
7437 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
7438 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
7441 case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125)
7442 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
7443 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
7445 default: // immediate offset
7446 vex_printf("dis_fp_pair(ppc)(instr)\n");
7451 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
7453 assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
7455 assign( frT_hi, getFReg(frT_hi_addr) );
7456 assign( frT_lo, getFReg(frT_lo_addr) );
7459 putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) );
7460 putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) );
7462 storeBE( mkexpr(EA_hi), mkexpr(frT_hi) );
7463 storeBE( mkexpr(EA_lo), mkexpr(frT_lo) );
7471 Floating Point Move Instructions
7473 static Bool dis_fp_move ( UInt theInstr )
7476 UChar opc1 = ifieldOPC(theInstr);
7477 UChar frD_addr = ifieldRegDS(theInstr);
7478 UChar frA_addr = ifieldRegA(theInstr);
7479 UChar frB_addr = ifieldRegB(theInstr);
7480 UInt opc2 = ifieldOPClo10(theInstr);
7481 UChar flag_rC = ifieldBIT0(theInstr);
7483 IRTemp frD = newTemp(Ity_F64);
7484 IRTemp frB = newTemp(Ity_F64);
7485 IRTemp itmpB = newTemp(Ity_F64);
7490 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
7491 vex_printf("dis_fp_move(ppc)(instr)\n");
7495 assign( frB, getFReg(frB_addr));
7498 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
7499 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
7501 signA = newTemp(Ity_I32);
7502 hiD = newTemp(Ity_I32);
7503 itmpB = newTemp(Ity_I64);
7504 frA = newTemp(Ity_F64);
7505 assign( frA, getFReg(frA_addr) );
7507 /* get A's sign bit */
7508 assign(signA, binop(Iop_And32,
7509 unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
7511 mkU32(0x80000000)) );
7513 assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
7515 /* mask off B's sign bit and or in A's sign bit */
7516 assign(hiD, binop(Iop_Or32,
7519 mkexpr(itmpB)), /* frB's high 32 bits */
7523 /* combine hiD/loB into frD */
7524 assign( frD, unop(Iop_ReinterpI64asF64,
7528 mkexpr(itmpB)))) ); /* frB's low 32 bits */
7531 case 0x028: // fneg (Floating Negate, PPC32 p416)
7532 DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7533 assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
7536 case 0x048: // fmr (Floating Move Register, PPC32 p410)
7537 DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7538 assign( frD, mkexpr(frB) );
7541 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
7542 DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7543 assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
7546 case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
7547 DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7548 assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
7552 vex_printf("dis_fp_move(ppc)(opc2)\n");
7556 putFReg( frD_addr, mkexpr(frD) );
7558 /* None of these change FPRF. cr1 is set in the usual way though,
7559 if flag_rC is set. */
7562 putCR321( 1, mkU8(0) );
7563 putCR0( 1, mkU8(0) );
7572 Floating Point Status/Control Register Instructions
7574 static Bool dis_fp_scr ( UInt theInstr )
7576 /* Many forms - see each switch case */
7577 UChar opc1 = ifieldOPC(theInstr);
7578 UInt opc2 = ifieldOPClo10(theInstr);
7579 UChar flag_rC = ifieldBIT0(theInstr);
7582 vex_printf("dis_fp_scr(ppc)(instr)\n");
7587 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
7588 // Bit crbD of the FPSCR is set.
7589 UChar crbD = ifieldRegDS(theInstr);
7590 UInt b11to20 = IFIELD(theInstr, 11, 10);
7593 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
7596 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
7597 putGST_masked( PPC_GST_FPSCR, mkU32(1<<(31-crbD)), 1<<(31-crbD) );
7601 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
7602 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
7603 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
7604 UChar crfS = toUChar( IFIELD( theInstr, 18, 3 ) );
7605 UChar b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
7606 IRTemp tmp = newTemp(Ity_I32);
7608 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
7609 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
7612 DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
7615 fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
7616 assign( tmp, binop(Iop_And32,
7617 binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
7619 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
7623 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
7624 // Bit crbD of the FPSCR is cleared.
7625 UChar crbD = ifieldRegDS(theInstr);
7626 UInt b11to20 = IFIELD(theInstr, 11, 10);
7629 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
7632 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
7633 putGST_masked( PPC_GST_FPSCR, mkU32(0), 1<<(31-crbD) );
7637 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
7638 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
7639 UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
7640 UChar IMM = toUChar( IFIELD( theInstr, 12, 4 ) );
7641 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) );
7643 if (b16to22 != 0 || b11 != 0) {
7644 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
7647 DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM);
7648 putGST_field( PPC_GST_FPSCR, mkU32(IMM), crfD );
7652 case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
7653 UChar frD_addr = ifieldRegDS(theInstr);
7654 UInt b11to20 = IFIELD(theInstr, 11, 10);
7655 IRExpr* fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
7658 vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
7661 DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
7663 unop( Iop_ReinterpI64asF64,
7664 unop( Iop_32Uto64, fpscr_all )));
7668 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
7669 UChar b25 = toUChar( IFIELD(theInstr, 25, 1) );
7670 UChar FM = toUChar( IFIELD(theInstr, 17, 8) );
7671 UChar frB_addr = ifieldRegB(theInstr);
7672 IRTemp frB = newTemp(Ity_F64);
7673 IRTemp rB_32 = newTemp(Ity_I32);
7677 /* new 64 bit move variant for power 6. If L field (bit 25) is
7678 * a one do a full 64 bit move. Note, the FPSCR is not really
7679 * properly modeled. This instruciton only changes the value of
7680 * the rounding mode. The HW exception bits do not get set in
7681 * the simulator. 1/12/09
7683 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
7687 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
7688 // Build 32bit mask from FM:
7690 for (i=0; i<8; i++) {
7691 if ((FM & (1<<(7-i))) == 1) {
7692 mask |= 0xF << (7-i);
7696 assign( frB, getFReg(frB_addr));
7697 assign( rB_32, unop( Iop_64to32,
7698 unop( Iop_ReinterpF64asI64, mkexpr(frB) )));
7699 putGST_masked( PPC_GST_FPSCR, mkexpr(rB_32), mask );
7704 vex_printf("dis_fp_scr(ppc)(opc2)\n");
7712 /*------------------------------------------------------------*/
7713 /*--- AltiVec Instruction Translation ---*/
7714 /*------------------------------------------------------------*/
7717 Altivec Cache Control Instructions (Data Streams)
7719 static Bool dis_av_datastream ( UInt theInstr )
7722 UChar opc1 = ifieldOPC(theInstr);
7723 UChar flag_T = toUChar( IFIELD( theInstr, 25, 1 ) );
7724 UChar flag_A = flag_T;
7725 UChar b23to24 = toUChar( IFIELD( theInstr, 23, 2 ) );
7726 UChar STRM = toUChar( IFIELD( theInstr, 21, 2 ) );
7727 UChar rA_addr = ifieldRegA(theInstr);
7728 UChar rB_addr = ifieldRegB(theInstr);
7729 UInt opc2 = ifieldOPClo10(theInstr);
7730 UChar b0 = ifieldBIT0(theInstr);
7732 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
7733 vex_printf("dis_av_datastream(ppc)(instr)\n");
7738 case 0x156: // dst (Data Stream Touch, AV p115)
7739 DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
7740 rA_addr, rB_addr, STRM);
7743 case 0x176: // dstst (Data Stream Touch for Store, AV p117)
7744 DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
7745 rA_addr, rB_addr, STRM);
7748 case 0x336: // dss (Data Stream Stop, AV p114)
7749 if (rA_addr != 0 || rB_addr != 0) {
7750 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
7754 DIP("dss %d\n", STRM);
7761 vex_printf("dis_av_datastream(ppc)(opc2)\n");
7768 AltiVec Processor Control Instructions
7770 static Bool dis_av_procctl ( UInt theInstr )
7773 UChar opc1 = ifieldOPC(theInstr);
7774 UChar vD_addr = ifieldRegDS(theInstr);
7775 UChar vA_addr = ifieldRegA(theInstr);
7776 UChar vB_addr = ifieldRegB(theInstr);
7777 UInt opc2 = IFIELD( theInstr, 0, 11 );
7780 vex_printf("dis_av_procctl(ppc)(instr)\n");
7785 case 0x604: // mfvscr (Move from VSCR, AV p129)
7786 if (vA_addr != 0 || vB_addr != 0) {
7787 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
7790 DIP("mfvscr v%d\n", vD_addr);
7791 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
7794 case 0x644: { // mtvscr (Move to VSCR, AV p130)
7795 IRTemp vB = newTemp(Ity_V128);
7796 if (vD_addr != 0 || vA_addr != 0) {
7797 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
7800 DIP("mtvscr v%d\n", vB_addr);
7801 assign( vB, getVReg(vB_addr));
7802 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
7806 vex_printf("dis_av_procctl(ppc)(opc2)\n");
7816 dis_vx_conv ( UInt theInstr, UInt opc2 )
7819 UChar opc1 = ifieldOPC( theInstr );
7820 UChar XT = ifieldRegXT( theInstr );
7821 UChar XB = ifieldRegXB( theInstr );
7822 IRTemp frB = newTemp(Ity_F64);
7823 IRTemp r_tmp64 = newTemp(Ity_I64);
7824 IRExpr* rm = get_IR_roundingmode();
7827 vex_printf( "dis_vx_conv(ppc)(instr)\n" );
7831 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
7832 /* For all the VSX convert instructions, the contents of doubleword element 1
7833 * of VSX[XT] are undefined after the operation; therefore, we can simply
7834 * move the entire array element where it makes sense to do so.
7839 // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
7840 // to Signed Integer Doubleword format with Saturate)
7841 DIP("xscvdpsxds fr%u,fr%u\n", (UInt)XT, (UInt)XB);
7843 binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
7845 mkexpr( frB ) ), mkU64( 0 ) ) );
7848 // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
7849 // Double-Precision format)
7850 DIP("xscvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
7852 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7854 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7855 binop( Iop_I64StoF64, rm,
7856 mkexpr( r_tmp64 ) ) ),
7860 // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
7861 // Double-Precision format)
7862 DIP("xscvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
7864 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7866 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7867 binop( Iop_I64UtoF64, rm,
7868 mkexpr( r_tmp64 ) ) ),
7873 vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
7880 * VSX Scalar Floating Point Arithmetic Instructions
7883 dis_vx_arith ( UInt theInstr, UInt opc2 )
7886 UChar opc1 = ifieldOPC( theInstr );
7887 UChar XT = ifieldRegXT( theInstr );
7888 UChar XA = ifieldRegXA( theInstr );
7889 UChar XB = ifieldRegXB( theInstr );
7890 IRExpr* rm = get_IR_roundingmode();
7891 IRTemp frA = newTemp(Ity_F64);
7892 IRTemp frB = newTemp(Ity_F64);
7895 vex_printf( "dis_vx_arith(ppc)(instr)\n" );
7899 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
7900 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
7902 /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
7903 * of VSX[XT] are undefined after the operation; therefore, we can simply set
7904 * element to zero where it makes sense to do so.
7907 case 0x080: // xsadddp (VSX scalar add double-precision)
7908 DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
7909 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7910 triop( Iop_AddF64, rm,
7915 case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
7916 DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
7917 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7918 triop( Iop_DivF64, rm,
7923 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
7925 IRTemp frT = newTemp(Ity_F64);
7926 Bool mdp = opc2 == 0x0A4;
7927 DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
7928 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
7929 getVSReg( XT ) ) ) );
7930 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7931 qop( Iop_MAddF64, rm,
7933 mkexpr( mdp ? frT : frB ),
7934 mkexpr( mdp ? frB : frT ) ) ),
7938 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
7940 IRTemp frT = newTemp(Ity_F64);
7941 Bool mdp = opc2 == 0x0E4;
7942 DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
7943 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
7944 getVSReg( XT ) ) ) );
7945 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
7946 qop( Iop_MSubF64, rm,
7948 mkexpr( mdp ? frT : frB ),
7949 mkexpr( mdp ? frB : frT ) ) ),
7953 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
7955 /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
7956 * of fnmadd and use pretty much the same code. However, that code has a bug in the
7957 * way it blindly negates the signbit, even if the floating point result is a NaN.
7958 * So, the TODO is to fix fnmadd (which I'll do in a different patch).
7960 ULong signbit_mask = 0x8000000000000000ULL;
7961 Bool mdp = opc2 == 0x2A4;
7962 IRTemp frT = newTemp(Ity_F64);
7963 IRTemp maddResult = newTemp(Ity_I64);
7964 IRTemp negatedResult = newTemp(Ity_I64);
7965 IRTemp signbit_32 = newTemp(Ity_I32);
7966 IRTemp resultantSignbit = newTemp(Ity_I1);
7968 DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
7969 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
7970 getVSReg( XT ) ) ) );
7971 assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
7973 mkexpr( mdp ? frT : frB ),
7974 mkexpr( mdp ? frB : frT ) ) ) );
7975 assign( signbit_32, binop( Iop_Shr32,
7977 binop( Iop_And64, mkexpr( maddResult ),
7978 mkU64( signbit_mask ) ) ),
7980 /* We negate the signbit if and only if the intermediate result from the
7981 * multiply-add was NOT a NaN. This is an XNOR predicate.
7983 assign( resultantSignbit,
7986 binop( Iop_Xor32, mkexpr( signbit_32 ),
7988 is_NaN( maddResult ) ) ),
7991 assign( negatedResult,
7992 binop( Iop_Or64, binop( Iop_And64, mkexpr( maddResult ),
7993 mkU64( ~signbit_mask ) ),
7994 binop( Iop_32HLto64,
7997 mkexpr( resultantSignbit ) ),
7998 mkU8( 31 ) ), mkU32( 0 ) ) ) );
8000 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( negatedResult ),
8004 case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
8005 DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8006 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
8007 triop( Iop_MulF64, rm,
8012 case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
8013 DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8014 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
8015 triop( Iop_SubF64, rm,
8022 vex_printf( "dis_vx_arith(ppc)(opc2)\n" );
8029 * VSX Floating Point Compare Instructions
8032 dis_vx_cmp( UInt theInstr, UInt opc2 )
8034 /* XX3-Form and XX2-Form */
8035 UChar opc1 = ifieldOPC( theInstr );
8036 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
8037 IRTemp ccPPC32 = newTemp(Ity_I32);
8038 IRTemp ccIR = newTemp(Ity_I32);
8039 UChar XA = ifieldRegXA ( theInstr );
8040 UChar XB = ifieldRegXB ( theInstr );
8041 IRTemp frA = newTemp(Ity_F64);
8042 IRTemp frB = newTemp(Ity_F64);
8045 vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
8049 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
8050 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
8052 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
8053 /* Note: Differences between xscmpudp and xscmpodp are only in
8054 * exception flag settings, which aren't supported anyway. */
8055 DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
8056 crfD, (UInt)XA, (UInt)XB);
8057 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
8059 /* Map compare result from IR to PPC32 */
8061 FP cmp result | PPC | IR
8062 --------------------------
8069 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
8070 // | ((ccIR ^ (ccIR>>6)) & 1)
8084 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
8093 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
8102 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
8106 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
8112 * VSX Move Instructions
8115 dis_vx_move( UInt theInstr, UInt opc2 )
8117 /* XX3-Form and XX2-Form */
8118 UChar opc1 = ifieldOPC( theInstr );
8119 UChar XT = ifieldRegXT ( theInstr );
8120 UChar XA = ifieldRegXA ( theInstr );
8121 UChar XB = ifieldRegXB ( theInstr );
8122 IRTemp vA = newTemp( Ity_V128 );
8123 IRTemp vB = newTemp( Ity_V128 );
8126 vex_printf( "dis_vx_move(ppc)(instr)\n" );
8130 assign( vA, getVSReg( XA ) );
8131 assign( vB, getVSReg( XB ) );
8133 /* For all the VSX move instructions, the contents of doubleword element 1
8134 * of VSX[XT] are undefined after the operation; therefore, we can simply
8135 * move the entire array element where it makes sense to do so.
8139 case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
8141 /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
8142 IRTemp absVal = newTemp(Ity_V128);
8143 assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1)));
8144 DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
8145 putVSReg(XT, mkexpr(absVal));
8148 case 0x2C0: // xscpsgndp
8150 /* Scalar copy sign double-precision */
8151 IRTemp vecA_signbit = newTemp(Ity_V128);
8152 IRTemp vecB_no_signbit = newTemp(Ity_V128);
8153 IRTemp vec_result = newTemp(Ity_V128);
8154 DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8155 assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
8159 assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128,
8163 assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) );
8164 putVSReg(XT, mkexpr(vec_result));
8167 case 0x2D2: // xsnabsdp
8169 /* Scalar negative absolute value double-precision */
8170 IRTemp vec_neg_signbit = newTemp(Ity_V128);
8171 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
8172 assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128,
8175 putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB)));
8178 case 0x2F2: // xsnegdp
8180 /* Scalar negate double-precision */
8181 IRTemp vecB_no_signbit = newTemp(Ity_V128);
8182 IRTemp vecB_signbit_comp = newTemp(Ity_V128);
8183 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
8184 assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
8188 assign( vecB_signbit_comp, binop( Iop_ShlV128,
8194 putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ),
8195 mkexpr( vecB_signbit_comp ) ) );
8200 vex_printf( "dis_vx_move(ppc)(opc2)\n" );
8207 * VSX Logical Instructions
8210 dis_vx_logic ( UInt theInstr, UInt opc2 )
8213 UChar opc1 = ifieldOPC( theInstr );
8214 UChar XT = ifieldRegXT ( theInstr );
8215 UChar XA = ifieldRegXA ( theInstr );
8216 UChar XB = ifieldRegXB ( theInstr );
8217 IRTemp vA = newTemp( Ity_V128 );
8218 IRTemp vB = newTemp( Ity_V128 );
8221 vex_printf( "dis_vx_logic(ppc)(instr)\n" );
8225 assign( vA, getVSReg( XA ) );
8226 assign( vB, getVSReg( XB ) );
8229 case 0x268: // xxlxor
8230 DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8231 putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
8233 case 0x248: // xxlor
8234 DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8235 putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
8237 case 0x288: // xxlnor
8238 DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8239 putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
8242 case 0x208: // xxland
8243 DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8244 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
8246 case 0x228: //xxlandc
8247 DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
8248 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
8252 vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
8259 * VSX Load Instructions
8260 * NOTE: VSX supports word-aligned storage access.
8263 dis_vx_load ( UInt theInstr )
8266 UChar opc1 = ifieldOPC( theInstr );
8267 UChar XT = ifieldRegXT ( theInstr );
8268 UChar rA_addr = ifieldRegA( theInstr );
8269 UChar rB_addr = ifieldRegB( theInstr );
8270 UInt opc2 = ifieldOPClo10( theInstr );
8272 IRType ty = mode64 ? Ity_I64 : Ity_I32;
8273 IRTemp EA = newTemp( ty );
8276 vex_printf( "dis_vx_load(ppc)(instr)\n" );
8280 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
8283 case 0x24C: // lxsdx
8286 DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
8287 exp = loadBE( Ity_I64, mkexpr( EA ) );
8288 // We need to pass an expression of type Ity_V128 with putVSReg, but the load
8289 // we just performed is only a DW. But since the contents of VSR[XT] element 1
8290 // are undefined after this operation, we can just do a splat op.
8291 putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
8294 case 0x34C: // lxvd2x
8296 IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
8297 IRExpr * high, *low;
8300 DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
8301 high = loadBE( Ity_I64, mkexpr( EA ) );
8302 high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
8303 : mkU32( ea_off ) );
8304 low = loadBE( Ity_I64, high_addr );
8305 putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
8308 case 0x14C: // lxvdsx
8310 IRTemp data = newTemp(Ity_I64);
8311 DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
8312 assign( data, loadBE( Ity_I64, mkexpr( EA ) ) );
8313 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
8318 IRExpr * t3, *t2, *t1, *t0;
8322 DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
8323 t3 = loadBE( Ity_I32, mkexpr( EA ) );
8325 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8326 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8327 t2 = loadBE( Ity_I32, irx_addr );
8329 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8330 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8331 t1 = loadBE( Ity_I32, irx_addr );
8333 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8334 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8335 t0 = loadBE( Ity_I32, irx_addr );
8336 putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ),
8337 binop( Iop_32HLto64, t1, t0 ) ) );
8341 vex_printf( "dis_vx_load(ppc)(opc2)\n" );
8348 * VSX Store Instructions
8349 * NOTE: VSX supports word-aligned storage access.
8352 dis_vx_store ( UInt theInstr )
8355 UChar opc1 = ifieldOPC( theInstr );
8356 UChar XS = ifieldRegXS( theInstr );
8357 UChar rA_addr = ifieldRegA( theInstr );
8358 UChar rB_addr = ifieldRegB( theInstr );
8359 IRTemp vS = newTemp( Ity_V128 );
8360 UInt opc2 = ifieldOPClo10( theInstr );
8362 IRType ty = mode64 ? Ity_I64 : Ity_I32;
8363 IRTemp EA = newTemp( ty );
8366 vex_printf( "dis_vx_store(ppc)(instr)\n" );
8370 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
8371 assign( vS, getVSReg( XS ) );
8377 DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
8378 high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
8379 storeBE( mkexpr( EA ), high64 );
8384 IRExpr * high64, *low64;
8385 DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
8386 high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
8387 low64 = unop( Iop_V128to64, mkexpr( vS ) );
8388 storeBE( mkexpr( EA ), high64 );
8389 storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 )
8390 : mkU32( 8 ) ), low64 );
8397 IRTemp hi64 = newTemp( Ity_I64 );
8398 IRTemp lo64 = newTemp( Ity_I64 );
8400 DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
8402 // This instruction supports word-aligned stores, so EA may not be
8403 // quad-word aligned. Therefore, do 4 individual word-size stores.
8404 assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
8405 assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
8407 storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
8409 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8410 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8411 storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
8413 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8414 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8415 storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
8417 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
8418 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
8419 storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
8424 vex_printf( "dis_vx_store(ppc)(opc2)\n" );
8431 * VSX Permute Instructions
8434 dis_vx_permute( UInt theInstr, UInt opc2 )
8437 UChar opc1 = ifieldOPC( theInstr );
8438 UChar XT = ifieldRegXT ( theInstr );
8439 UChar XA = ifieldRegXA ( theInstr );
8440 UChar XB = ifieldRegXB ( theInstr );
8441 IRTemp vT = newTemp( Ity_V128 );
8442 IRTemp vA = newTemp( Ity_V128 );
8443 IRTemp vB = newTemp( Ity_V128 );
8446 vex_printf( "dis_vx_permute(ppc)(instr)\n" );
8450 assign( vA, getVSReg( XA ) );
8451 assign( vB, getVSReg( XB ) );
8454 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
8456 UChar SHW = ifieldSHW ( theInstr );
8457 IRTemp result = newTemp(Ity_V128);
8459 IRTemp hi = newTemp(Ity_V128);
8460 IRTemp lo = newTemp(Ity_V128);
8461 assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
8462 assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
8463 assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
8465 assign ( result, mkexpr(vA) );
8466 DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW);
8467 putVSReg( XT, mkexpr(result) );
8470 case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
8472 UChar DM = ifieldDM ( theInstr );
8473 IRTemp hi = newTemp(Ity_I64);
8474 IRTemp lo = newTemp(Ity_I64);
8477 assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
8479 assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
8482 assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
8484 assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
8486 assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
8488 DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM);
8489 putVSReg( XT, mkexpr( vT ) );
8492 case 0x48: // xxmrghw (VSX Merge High Word)
8493 case 0xc8: // xxmrglw (VSX Merge Low Word)
8495 char type = (opc2 == 0x48) ? 'h' : 'l';
8496 IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
8497 IRTemp a64 = newTemp(Ity_I64);
8498 IRTemp ahi32 = newTemp(Ity_I32);
8499 IRTemp alo32 = newTemp(Ity_I32);
8500 IRTemp b64 = newTemp(Ity_I64);
8501 IRTemp bhi32 = newTemp(Ity_I32);
8502 IRTemp blo32 = newTemp(Ity_I32);
8504 assign( a64, unop(word_op, mkexpr(vA)) );
8505 assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
8506 assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
8508 assign( b64, unop(word_op, mkexpr(vB)) );
8509 assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
8510 assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
8512 assign( vT, binop(Iop_64HLtoV128,
8513 binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
8514 binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
8516 DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB);
8517 putVSReg( XT, mkexpr( vT ) );
8522 vex_printf( "dis_vx_permute(ppc)(opc2)\n" );
8529 AltiVec Load Instructions
8531 static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
8534 UChar opc1 = ifieldOPC(theInstr);
8535 UChar vD_addr = ifieldRegDS(theInstr);
8536 UChar rA_addr = ifieldRegA(theInstr);
8537 UChar rB_addr = ifieldRegB(theInstr);
8538 UInt opc2 = ifieldOPClo10(theInstr);
8539 UChar b0 = ifieldBIT0(theInstr);
8541 IRType ty = mode64 ? Ity_I64 : Ity_I32;
8542 IRTemp EA = newTemp(ty);
8543 IRTemp EA_align16 = newTemp(ty);
8545 if (opc1 != 0x1F || b0 != 0) {
8546 vex_printf("dis_av_load(ppc)(instr)\n");
8550 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8551 assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
8555 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
8557 UInt vD_off = vectorGuestRegOffset(vD_addr);
8558 IRExpr** args = mkIRExprVec_3(
8560 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
8564 d = unsafeIRDirty_0_N (
8566 "ppc32g_dirtyhelper_LVS",
8567 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
8570 d = unsafeIRDirty_0_N (
8572 "ppc64g_dirtyhelper_LVS",
8573 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
8576 DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8577 /* declare guest state effects */
8580 d->fxState[0].fx = Ifx_Write;
8581 d->fxState[0].offset = vD_off;
8582 d->fxState[0].size = sizeof(U128);
8584 /* execute the dirty call, side-effecting guest state */
8585 stmt( IRStmt_Dirty(d) );
8588 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
8590 UInt vD_off = vectorGuestRegOffset(vD_addr);
8591 IRExpr** args = mkIRExprVec_3(
8593 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
8595 mkU32(1)/*right*/ );
8597 d = unsafeIRDirty_0_N (
8599 "ppc32g_dirtyhelper_LVS",
8600 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
8603 d = unsafeIRDirty_0_N (
8605 "ppc64g_dirtyhelper_LVS",
8606 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
8609 DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8610 /* declare guest state effects */
8613 d->fxState[0].fx = Ifx_Write;
8614 d->fxState[0].offset = vD_off;
8615 d->fxState[0].size = sizeof(U128);
8617 /* execute the dirty call, side-effecting guest state */
8618 stmt( IRStmt_Dirty(d) );
8621 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
8622 DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8623 /* loads addressed byte into vector[EA[0:3]
8624 since all other destination bytes are undefined,
8625 can simply load entire vector from 16-aligned EA */
8626 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
8629 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
8630 DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8631 /* see note for lvebx */
8632 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
8635 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
8636 DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8637 /* see note for lvebx */
8638 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
8641 case 0x067: // lvx (Load Vector Indexed, AV p127)
8642 DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8643 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
8646 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
8647 DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
8648 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
8652 vex_printf("dis_av_load(ppc)(opc2)\n");
8659 AltiVec Store Instructions
8661 static Bool dis_av_store ( UInt theInstr )
8664 UChar opc1 = ifieldOPC(theInstr);
8665 UChar vS_addr = ifieldRegDS(theInstr);
8666 UChar rA_addr = ifieldRegA(theInstr);
8667 UChar rB_addr = ifieldRegB(theInstr);
8668 UInt opc2 = ifieldOPClo10(theInstr);
8669 UChar b0 = ifieldBIT0(theInstr);
8671 IRType ty = mode64 ? Ity_I64 : Ity_I32;
8672 IRTemp EA = newTemp(ty);
8673 IRTemp addr_aligned = newTemp(ty);
8674 IRTemp vS = newTemp(Ity_V128);
8675 IRTemp eb = newTemp(Ity_I8);
8676 IRTemp idx = newTemp(Ity_I8);
8678 if (opc1 != 0x1F || b0 != 0) {
8679 vex_printf("dis_av_store(ppc)(instr)\n");
8683 assign( vS, getVReg(vS_addr));
8684 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8687 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
8688 DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
8689 assign( eb, binop(Iop_And8, mkU8(0xF),
8691 mkNarrowTo32(ty, mkexpr(EA)) )) );
8692 assign( idx, binop(Iop_Shl8,
8693 binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
8695 storeBE( mkexpr(EA),
8696 unop(Iop_32to8, unop(Iop_V128to32,
8697 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
8700 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
8701 DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
8702 assign( addr_aligned, addr_align(mkexpr(EA), 2) );
8703 assign( eb, binop(Iop_And8, mkU8(0xF),
8704 mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
8705 assign( idx, binop(Iop_Shl8,
8706 binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
8708 storeBE( mkexpr(addr_aligned),
8709 unop(Iop_32to16, unop(Iop_V128to32,
8710 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
8713 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
8714 DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
8715 assign( addr_aligned, addr_align(mkexpr(EA), 4) );
8716 assign( eb, binop(Iop_And8, mkU8(0xF),
8717 mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
8718 assign( idx, binop(Iop_Shl8,
8719 binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
8721 storeBE( mkexpr(addr_aligned),
8723 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
8727 case 0x0E7: // stvx (Store Vector Indexed, AV p134)
8728 DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
8729 storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
8732 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
8733 DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
8734 storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
8738 vex_printf("dis_av_store(ppc)(opc2)\n");
8745 AltiVec Arithmetic Instructions
8747 static Bool dis_av_arith ( UInt theInstr )
8750 UChar opc1 = ifieldOPC(theInstr);
8751 UChar vD_addr = ifieldRegDS(theInstr);
8752 UChar vA_addr = ifieldRegA(theInstr);
8753 UChar vB_addr = ifieldRegB(theInstr);
8754 UInt opc2 = IFIELD( theInstr, 0, 11 );
8756 IRTemp vA = newTemp(Ity_V128);
8757 IRTemp vB = newTemp(Ity_V128);
8758 IRTemp z3 = newTemp(Ity_I64);
8759 IRTemp z2 = newTemp(Ity_I64);
8760 IRTemp z1 = newTemp(Ity_I64);
8761 IRTemp z0 = newTemp(Ity_I64);
8763 IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
8764 IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
8765 IRTemp b3, b2, b1, b0;
8767 aEvn = aOdd = IRTemp_INVALID;
8768 a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
8769 a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
8770 b3 = b2 = b1 = b0 = IRTemp_INVALID;
8772 assign( vA, getVReg(vA_addr));
8773 assign( vB, getVReg(vB_addr));
8776 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
8782 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
8783 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8784 /* unsigned_ov(x+y) = (y >u not(x)) */
8785 putVReg( vD_addr, binop(Iop_ShrN32x4,
8786 binop(Iop_CmpGT32Ux4, mkexpr(vB),
8787 unop(Iop_NotV128, mkexpr(vA))),
8791 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
8792 DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8793 putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
8796 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
8797 DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8798 putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
8801 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
8802 DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8803 putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
8806 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
8807 DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8808 putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
8809 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
8812 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
8813 DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8814 putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
8815 // TODO: set VSCR[SAT]
8818 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
8819 DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8820 putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
8821 // TODO: set VSCR[SAT]
8824 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
8825 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8826 putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
8827 // TODO: set VSCR[SAT]
8830 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
8831 DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8832 putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
8833 // TODO: set VSCR[SAT]
8836 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
8837 DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8838 putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
8839 // TODO: set VSCR[SAT]
8844 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
8845 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8846 /* unsigned_ov(x-y) = (y >u x) */
8847 putVReg( vD_addr, binop(Iop_ShrN32x4,
8849 binop(Iop_CmpGT32Ux4, mkexpr(vB),
8854 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
8855 DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8856 putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
8859 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
8860 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8861 putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
8864 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
8865 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8866 putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
8869 case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
8870 DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8871 putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
8872 // TODO: set VSCR[SAT]
8875 case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
8876 DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8877 putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
8878 // TODO: set VSCR[SAT]
8881 case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
8882 DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8883 putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
8884 // TODO: set VSCR[SAT]
8887 case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
8888 DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8889 putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
8890 // TODO: set VSCR[SAT]
8893 case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
8894 DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8895 putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
8896 // TODO: set VSCR[SAT]
8899 case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
8900 DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8901 putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
8902 // TODO: set VSCR[SAT]
8907 case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
8908 DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8909 putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
8912 case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
8913 DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8914 putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
8917 case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
8918 DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8919 putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
8922 case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
8923 DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8924 putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
8927 case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
8928 DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8929 putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
8932 case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
8933 DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8934 putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
8939 case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
8940 DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8941 putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
8944 case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
8945 DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8946 putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
8949 case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
8950 DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8951 putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
8954 case 0x302: // vminsb (Minimum Signed Byte, AV p188)
8955 DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8956 putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
8959 case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
8960 DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8961 putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
8964 case 0x382: // vminsw (Minimum Signed Word, AV p190)
8965 DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8966 putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
8971 case 0x402: // vavgub (Average Unsigned Byte, AV p152)
8972 DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8973 putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
8976 case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
8977 DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8978 putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
8981 case 0x482: // vavguw (Average Unsigned Word, AV p154)
8982 DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8983 putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
8986 case 0x502: // vavgsb (Average Signed Byte, AV p149)
8987 DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8988 putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
8991 case 0x542: // vavgsh (Average Signed Half Word, AV p150)
8992 DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8993 putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
8996 case 0x582: // vavgsw (Average Signed Word, AV p151)
8997 DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
8998 putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
9003 case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
9004 DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9006 binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
9009 case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
9010 DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9012 binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
9015 case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
9016 DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9018 binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
9021 case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
9022 DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9024 binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
9027 case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
9028 DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9029 putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
9032 case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
9033 DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9034 putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
9037 case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
9038 DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9039 putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
9042 case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
9043 DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9044 putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
9048 /* Sum Across Partial */
9049 case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
9050 IRTemp aEE, aEO, aOE, aOO;
9051 aEE = aEO = aOE = aOO = IRTemp_INVALID;
9052 DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9054 /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
9055 expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
9056 expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
9057 expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
9059 /* break V128 to 4xI32's, zero-extending to I64's */
9060 breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
9061 breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
9062 breakV128to4x64U( mkexpr(aEO), &a13, &a9, &a5, &a1 );
9063 breakV128to4x64U( mkexpr(aOO), &a12, &a8, &a4, &a0 );
9064 breakV128to4x64U( mkexpr(vB), &b3, &b2, &b1, &b0 );
9067 assign( z3, binop(Iop_Add64, mkexpr(b3),
9069 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
9070 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
9071 assign( z2, binop(Iop_Add64, mkexpr(b2),
9073 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
9074 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
9075 assign( z1, binop(Iop_Add64, mkexpr(b1),
9077 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
9078 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
9079 assign( z0, binop(Iop_Add64, mkexpr(b0),
9081 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
9082 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
9084 /* saturate-narrow to 32bit, and combine to V128 */
9085 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
9086 mkexpr(z1), mkexpr(z0)) );
9089 case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
9090 IRTemp aEE, aEO, aOE, aOO;
9091 aEE = aEO = aOE = aOO = IRTemp_INVALID;
9092 DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9094 /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
9095 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
9096 expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
9097 expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
9099 /* break V128 to 4xI32's, sign-extending to I64's */
9100 breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
9101 breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
9102 breakV128to4x64S( mkexpr(aEO), &a13, &a9, &a5, &a1 );
9103 breakV128to4x64S( mkexpr(aOO), &a12, &a8, &a4, &a0 );
9104 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
9107 assign( z3, binop(Iop_Add64, mkexpr(b3),
9109 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
9110 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
9111 assign( z2, binop(Iop_Add64, mkexpr(b2),
9113 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
9114 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
9115 assign( z1, binop(Iop_Add64, mkexpr(b1),
9117 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
9118 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
9119 assign( z0, binop(Iop_Add64, mkexpr(b0),
9121 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
9122 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
9124 /* saturate-narrow to 32bit, and combine to V128 */
9125 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
9126 mkexpr(z1), mkexpr(z0)) );
9129 case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
9130 DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9132 /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
9133 expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
9135 /* break V128 to 4xI32's, sign-extending to I64's */
9136 breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
9137 breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
9138 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
9141 assign( z3, binop(Iop_Add64, mkexpr(b3),
9142 binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
9143 assign( z2, binop(Iop_Add64, mkexpr(b2),
9144 binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
9145 assign( z1, binop(Iop_Add64, mkexpr(b1),
9146 binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
9147 assign( z0, binop(Iop_Add64, mkexpr(b0),
9148 binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
9150 /* saturate-narrow to 32bit, and combine to V128 */
9151 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
9152 mkexpr(z1), mkexpr(z0)) );
9155 case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
9156 DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9158 /* break V128 to 4xI32's, sign-extending to I64's */
9159 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
9160 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
9163 assign( z2, binop(Iop_Add64, mkexpr(b2),
9164 binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
9165 assign( z0, binop(Iop_Add64, mkexpr(b0),
9166 binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
9168 /* saturate-narrow to 32bit, and combine to V128 */
9169 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
9170 mkU64(0), mkexpr(z0)) );
9173 case 0x788: { // vsumsws (Sum SW Saturate, AV p271)
9174 DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9176 /* break V128 to 4xI32's, sign-extending to I64's */
9177 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
9178 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
9181 assign( z0, binop(Iop_Add64, mkexpr(b0),
9183 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
9184 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
9186 /* saturate-narrow to 32bit, and combine to V128 */
9187 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
9188 mkU64(0), mkexpr(z0)) );
9192 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
9199 AltiVec Logic Instructions
9201 static Bool dis_av_logic ( UInt theInstr )
9204 UChar opc1 = ifieldOPC(theInstr);
9205 UChar vD_addr = ifieldRegDS(theInstr);
9206 UChar vA_addr = ifieldRegA(theInstr);
9207 UChar vB_addr = ifieldRegB(theInstr);
9208 UInt opc2 = IFIELD( theInstr, 0, 11 );
9210 IRTemp vA = newTemp(Ity_V128);
9211 IRTemp vB = newTemp(Ity_V128);
9212 assign( vA, getVReg(vA_addr));
9213 assign( vB, getVReg(vB_addr));
9216 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
9221 case 0x404: // vand (And, AV p147)
9222 DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9223 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
9226 case 0x444: // vandc (And, AV p148)
9227 DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9228 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
9229 unop(Iop_NotV128, mkexpr(vB))) );
9232 case 0x484: // vor (Or, AV p217)
9233 DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9234 putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
9237 case 0x4C4: // vxor (Xor, AV p282)
9238 DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9239 putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
9242 case 0x504: // vnor (Nor, AV p216)
9243 DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9245 unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
9249 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
9256 AltiVec Compare Instructions
9258 static Bool dis_av_cmp ( UInt theInstr )
9261 UChar opc1 = ifieldOPC(theInstr);
9262 UChar vD_addr = ifieldRegDS(theInstr);
9263 UChar vA_addr = ifieldRegA(theInstr);
9264 UChar vB_addr = ifieldRegB(theInstr);
9265 UChar flag_rC = ifieldBIT10(theInstr);
9266 UInt opc2 = IFIELD( theInstr, 0, 10 );
9268 IRTemp vA = newTemp(Ity_V128);
9269 IRTemp vB = newTemp(Ity_V128);
9270 IRTemp vD = newTemp(Ity_V128);
9271 assign( vA, getVReg(vA_addr));
9272 assign( vB, getVReg(vB_addr));
9275 vex_printf("dis_av_cmp(ppc)(instr)\n");
9280 case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
9281 DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9282 vD_addr, vA_addr, vB_addr);
9283 assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
9286 case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
9287 DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9288 vD_addr, vA_addr, vB_addr);
9289 assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
9292 case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
9293 DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9294 vD_addr, vA_addr, vB_addr);
9295 assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
9298 case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
9299 DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9300 vD_addr, vA_addr, vB_addr);
9301 assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
9304 case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
9305 DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9306 vD_addr, vA_addr, vB_addr);
9307 assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
9310 case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
9311 DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9312 vD_addr, vA_addr, vB_addr);
9313 assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
9316 case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
9317 DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9318 vD_addr, vA_addr, vB_addr);
9319 assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
9322 case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
9323 DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9324 vD_addr, vA_addr, vB_addr);
9325 assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
9328 case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
9329 DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
9330 vD_addr, vA_addr, vB_addr);
9331 assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
9335 vex_printf("dis_av_cmp(ppc)(opc2)\n");
9339 putVReg( vD_addr, mkexpr(vD) );
9342 set_AV_CR6( mkexpr(vD), True );
9348 AltiVec Multiply-Sum Instructions
9350 static Bool dis_av_multarith ( UInt theInstr )
9353 UChar opc1 = ifieldOPC(theInstr);
9354 UChar vD_addr = ifieldRegDS(theInstr);
9355 UChar vA_addr = ifieldRegA(theInstr);
9356 UChar vB_addr = ifieldRegB(theInstr);
9357 UChar vC_addr = ifieldRegC(theInstr);
9358 UChar opc2 = toUChar( IFIELD( theInstr, 0, 6 ) );
9360 IRTemp vA = newTemp(Ity_V128);
9361 IRTemp vB = newTemp(Ity_V128);
9362 IRTemp vC = newTemp(Ity_V128);
9363 IRTemp zeros = newTemp(Ity_V128);
9364 IRTemp aLo = newTemp(Ity_V128);
9365 IRTemp bLo = newTemp(Ity_V128);
9366 IRTemp cLo = newTemp(Ity_V128);
9367 IRTemp zLo = newTemp(Ity_V128);
9368 IRTemp aHi = newTemp(Ity_V128);
9369 IRTemp bHi = newTemp(Ity_V128);
9370 IRTemp cHi = newTemp(Ity_V128);
9371 IRTemp zHi = newTemp(Ity_V128);
9372 IRTemp abEvn = newTemp(Ity_V128);
9373 IRTemp abOdd = newTemp(Ity_V128);
9374 IRTemp z3 = newTemp(Ity_I64);
9375 IRTemp z2 = newTemp(Ity_I64);
9376 IRTemp z1 = newTemp(Ity_I64);
9377 IRTemp z0 = newTemp(Ity_I64);
9378 IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
9379 IRTemp c3, c2, c1, c0;
9381 ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
9382 c3 = c2 = c1 = c0 = IRTemp_INVALID;
9384 assign( vA, getVReg(vA_addr));
9385 assign( vB, getVReg(vB_addr));
9386 assign( vC, getVReg(vC_addr));
9387 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
9390 vex_printf("dis_av_multarith(ppc)(instr)\n");
9396 case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
9397 IRTemp cSigns = newTemp(Ity_V128);
9398 DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
9399 vD_addr, vA_addr, vB_addr, vC_addr);
9400 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
9401 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
9402 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
9403 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
9404 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
9405 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
9406 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
9408 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
9410 binop(Iop_MullEven16Sx8,
9411 mkexpr(aLo), mkexpr(bLo)),
9414 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
9416 binop(Iop_MullEven16Sx8,
9417 mkexpr(aHi), mkexpr(bHi)),
9421 binop(Iop_QNarrow32Sx4, mkexpr(zHi), mkexpr(zLo)) );
9424 case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
9425 IRTemp zKonst = newTemp(Ity_V128);
9426 IRTemp cSigns = newTemp(Ity_V128);
9427 DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
9428 vD_addr, vA_addr, vB_addr, vC_addr);
9429 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
9430 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
9431 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
9432 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
9433 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
9434 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
9435 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
9437 /* shifting our const avoids store/load version of Dup */
9438 assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
9441 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
9443 binop(Iop_Add32x4, mkexpr(zKonst),
9444 binop(Iop_MullEven16Sx8,
9445 mkexpr(aLo), mkexpr(bLo))),
9448 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
9450 binop(Iop_Add32x4, mkexpr(zKonst),
9451 binop(Iop_MullEven16Sx8,
9452 mkexpr(aHi), mkexpr(bHi))),
9455 putVReg( vD_addr, binop(Iop_QNarrow32Sx4, mkexpr(zHi), mkexpr(zLo)) );
9458 case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
9459 DIP("vmladduhm v%d,v%d,v%d,v%d\n",
9460 vD_addr, vA_addr, vB_addr, vC_addr);
9461 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
9462 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
9463 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
9464 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
9465 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
9466 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
9467 assign(zLo, binop(Iop_Add32x4,
9468 binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
9470 assign(zHi, binop(Iop_Add32x4,
9471 binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
9473 putVReg(vD_addr, binop(Iop_Narrow32x4, mkexpr(zHi), mkexpr(zLo)));
9479 case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
9480 IRTemp abEE, abEO, abOE, abOO;
9481 abEE = abEO = abOE = abOO = IRTemp_INVALID;
9482 DIP("vmsumubm v%d,v%d,v%d,v%d\n",
9483 vD_addr, vA_addr, vB_addr, vC_addr);
9485 /* multiply vA,vB (unsigned, widening) */
9486 assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
9487 assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
9489 /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
9490 expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
9491 expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
9494 binop(Iop_Add32x4, mkexpr(vC),
9496 binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
9497 binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
9500 case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
9501 IRTemp aEvn, aOdd, bEvn, bOdd;
9502 IRTemp abEE = newTemp(Ity_V128);
9503 IRTemp abEO = newTemp(Ity_V128);
9504 IRTemp abOE = newTemp(Ity_V128);
9505 IRTemp abOO = newTemp(Ity_V128);
9506 aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
9507 DIP("vmsummbm v%d,v%d,v%d,v%d\n",
9508 vD_addr, vA_addr, vB_addr, vC_addr);
9510 /* sign-extend vA, zero-extend vB, for mixed-sign multiply
9511 (separating out adjacent lanes to different vectors) */
9512 expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
9513 expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
9515 /* multiply vA, vB, again separating adjacent lanes */
9516 assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
9517 assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
9518 assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
9519 assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
9521 /* add results together, + vC */
9523 binop(Iop_QAdd32Sx4, mkexpr(vC),
9524 binop(Iop_QAdd32Sx4,
9525 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
9526 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
9529 case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
9530 DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
9531 vD_addr, vA_addr, vB_addr, vC_addr);
9532 assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
9533 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
9535 binop(Iop_Add32x4, mkexpr(vC),
9536 binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
9539 case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
9540 DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
9541 vD_addr, vA_addr, vB_addr, vC_addr);
9542 /* widening multiply, separating lanes */
9543 assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
9544 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
9546 /* break V128 to 4xI32's, zero-extending to I64's */
9547 breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
9548 breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
9549 breakV128to4x64U( mkexpr(vC), &c3, &c2, &c1, &c0 );
9552 assign( z3, binop(Iop_Add64, mkexpr(c3),
9553 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
9554 assign( z2, binop(Iop_Add64, mkexpr(c2),
9555 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
9556 assign( z1, binop(Iop_Add64, mkexpr(c1),
9557 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
9558 assign( z0, binop(Iop_Add64, mkexpr(c0),
9559 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
9561 /* saturate-narrow to 32bit, and combine to V128 */
9562 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
9563 mkexpr(z1), mkexpr(z0)) );
9567 case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
9568 DIP("vmsumshm v%d,v%d,v%d,v%d\n",
9569 vD_addr, vA_addr, vB_addr, vC_addr);
9570 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
9571 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
9573 binop(Iop_Add32x4, mkexpr(vC),
9574 binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
9577 case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
9578 DIP("vmsumshs v%d,v%d,v%d,v%d\n",
9579 vD_addr, vA_addr, vB_addr, vC_addr);
9580 /* widening multiply, separating lanes */
9581 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
9582 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
9584 /* break V128 to 4xI32's, sign-extending to I64's */
9585 breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
9586 breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
9587 breakV128to4x64S( mkexpr(vC), &c3, &c2, &c1, &c0 );
9590 assign( z3, binop(Iop_Add64, mkexpr(c3),
9591 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
9592 assign( z2, binop(Iop_Add64, mkexpr(c2),
9593 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
9594 assign( z1, binop(Iop_Add64, mkexpr(c1),
9595 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
9596 assign( z0, binop(Iop_Add64, mkexpr(c0),
9597 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
9599 /* saturate-narrow to 32bit, and combine to V128 */
9600 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
9601 mkexpr(z1), mkexpr(z0)) );
9605 vex_printf("dis_av_multarith(ppc)(opc2)\n");
9612 AltiVec Shift/Rotate Instructions
9614 static Bool dis_av_shift ( UInt theInstr )
9617 UChar opc1 = ifieldOPC(theInstr);
9618 UChar vD_addr = ifieldRegDS(theInstr);
9619 UChar vA_addr = ifieldRegA(theInstr);
9620 UChar vB_addr = ifieldRegB(theInstr);
9621 UInt opc2 = IFIELD( theInstr, 0, 11 );
9623 IRTemp vA = newTemp(Ity_V128);
9624 IRTemp vB = newTemp(Ity_V128);
9625 assign( vA, getVReg(vA_addr));
9626 assign( vB, getVReg(vB_addr));
9629 vex_printf("dis_av_shift(ppc)(instr)\n");
9635 case 0x004: // vrlb (Rotate Left Integer B, AV p234)
9636 DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9637 putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
9640 case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
9641 DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9642 putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
9645 case 0x084: // vrlw (Rotate Left Integer W, AV p236)
9646 DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9647 putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
9652 case 0x104: // vslb (Shift Left Integer B, AV p240)
9653 DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9654 putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
9657 case 0x144: // vslh (Shift Left Integer HW, AV p242)
9658 DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9659 putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
9662 case 0x184: // vslw (Shift Left Integer W, AV p244)
9663 DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9664 putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
9667 case 0x1C4: { // vsl (Shift Left, AV p239)
9668 IRTemp sh = newTemp(Ity_I8);
9669 DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9670 assign( sh, binop(Iop_And8, mkU8(0x7),
9672 unop(Iop_V128to32, mkexpr(vB)))) );
9674 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
9677 case 0x40C: { // vslo (Shift Left by Octet, AV p243)
9678 IRTemp sh = newTemp(Ity_I8);
9679 DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9680 assign( sh, binop(Iop_And8, mkU8(0x78),
9682 unop(Iop_V128to32, mkexpr(vB)))) );
9684 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
9690 case 0x204: // vsrb (Shift Right B, AV p256)
9691 DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9692 putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
9695 case 0x244: // vsrh (Shift Right HW, AV p257)
9696 DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9697 putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
9700 case 0x284: // vsrw (Shift Right W, AV p259)
9701 DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9702 putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
9705 case 0x2C4: { // vsr (Shift Right, AV p251)
9706 IRTemp sh = newTemp(Ity_I8);
9707 DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9708 assign( sh, binop(Iop_And8, mkU8(0x7),
9710 unop(Iop_V128to32, mkexpr(vB)))) );
9712 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
9715 case 0x304: // vsrab (Shift Right Alg B, AV p253)
9716 DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9717 putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
9720 case 0x344: // vsrah (Shift Right Alg HW, AV p254)
9721 DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9722 putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
9725 case 0x384: // vsraw (Shift Right Alg W, AV p255)
9726 DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9727 putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
9730 case 0x44C: { // vsro (Shift Right by Octet, AV p258)
9731 IRTemp sh = newTemp(Ity_I8);
9732 DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9733 assign( sh, binop(Iop_And8, mkU8(0x78),
9735 unop(Iop_V128to32, mkexpr(vB)))) );
9737 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
9742 vex_printf("dis_av_shift(ppc)(opc2)\n");
9749 AltiVec Permute Instructions
9751 static Bool dis_av_permute ( UInt theInstr )
9753 /* VA-Form, VX-Form */
9754 UChar opc1 = ifieldOPC(theInstr);
9755 UChar vD_addr = ifieldRegDS(theInstr);
9756 UChar vA_addr = ifieldRegA(theInstr);
9757 UChar UIMM_5 = vA_addr;
9758 UChar vB_addr = ifieldRegB(theInstr);
9759 UChar vC_addr = ifieldRegC(theInstr);
9760 UChar b10 = ifieldBIT10(theInstr);
9761 UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
9762 UInt opc2 = toUChar( IFIELD( theInstr, 0, 6 ) );
9764 UChar SIMM_8 = extend_s_5to8(UIMM_5);
9766 IRTemp vA = newTemp(Ity_V128);
9767 IRTemp vB = newTemp(Ity_V128);
9768 IRTemp vC = newTemp(Ity_V128);
9769 assign( vA, getVReg(vA_addr));
9770 assign( vB, getVReg(vB_addr));
9771 assign( vC, getVReg(vC_addr));
9774 vex_printf("dis_av_permute(ppc)(instr)\n");
9779 case 0x2A: // vsel (Conditional Select, AV p238)
9780 DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
9781 /* vD = (vA & ~vC) | (vB & vC) */
9782 putVReg( vD_addr, binop(Iop_OrV128,
9783 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
9784 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
9787 case 0x2B: { // vperm (Permute, AV p218)
9788 /* limited to two args for IR, so have to play games... */
9789 IRTemp a_perm = newTemp(Ity_V128);
9790 IRTemp b_perm = newTemp(Ity_V128);
9791 IRTemp mask = newTemp(Ity_V128);
9792 IRTemp vC_andF = newTemp(Ity_V128);
9793 DIP("vperm v%d,v%d,v%d,v%d\n",
9794 vD_addr, vA_addr, vB_addr, vC_addr);
9795 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
9796 IR specifies, and also to hide irrelevant bits from
9799 binop(Iop_AndV128, mkexpr(vC),
9800 unop(Iop_Dup8x16, mkU8(0xF))) );
9802 binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
9804 binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
9805 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
9806 assign( mask, binop(Iop_SarN8x16,
9807 binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
9809 // dst = (a & ~mask) | (b & mask)
9810 putVReg( vD_addr, binop(Iop_OrV128,
9811 binop(Iop_AndV128, mkexpr(a_perm),
9812 unop(Iop_NotV128, mkexpr(mask))),
9813 binop(Iop_AndV128, mkexpr(b_perm),
9817 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
9819 vex_printf("dis_av_permute(ppc)(vsldoi)\n");
9822 DIP("vsldoi v%d,v%d,v%d,%d\n",
9823 vD_addr, vA_addr, vB_addr, SHB_uimm4);
9825 putVReg( vD_addr, mkexpr(vA) );
9829 binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
9830 binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
9834 break; // Fall through...
9837 opc2 = IFIELD( theInstr, 0, 11 );
9841 case 0x00C: // vmrghb (Merge High B, AV p195)
9842 DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9844 binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
9847 case 0x04C: // vmrghh (Merge High HW, AV p196)
9848 DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9850 binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
9853 case 0x08C: // vmrghw (Merge High W, AV p197)
9854 DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9856 binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
9859 case 0x10C: // vmrglb (Merge Low B, AV p198)
9860 DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9862 binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
9865 case 0x14C: // vmrglh (Merge Low HW, AV p199)
9866 DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9868 binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
9871 case 0x18C: // vmrglw (Merge Low W, AV p200)
9872 DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9874 binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
9879 case 0x20C: { // vspltb (Splat Byte, AV p245)
9880 /* vD = Dup8x16( vB[UIMM_5] ) */
9881 UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
9882 DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
9883 putVReg( vD_addr, unop(Iop_Dup8x16,
9884 unop(Iop_32to8, unop(Iop_V128to32,
9885 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
9888 case 0x24C: { // vsplth (Splat Half Word, AV p246)
9889 UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
9890 DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
9891 putVReg( vD_addr, unop(Iop_Dup16x8,
9892 unop(Iop_32to16, unop(Iop_V128to32,
9893 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
9896 case 0x28C: { // vspltw (Splat Word, AV p250)
9897 /* vD = Dup32x4( vB[UIMM_5] ) */
9898 UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
9899 DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
9900 putVReg( vD_addr, unop(Iop_Dup32x4,
9902 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
9905 case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
9906 DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
9907 putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
9910 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
9911 DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
9913 unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
9916 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
9917 DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
9919 unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
9923 vex_printf("dis_av_permute(ppc)(opc2)\n");
9930 AltiVec Pack/Unpack Instructions
9932 static Bool dis_av_pack ( UInt theInstr )
9935 UChar opc1 = ifieldOPC(theInstr);
9936 UChar vD_addr = ifieldRegDS(theInstr);
9937 UChar vA_addr = ifieldRegA(theInstr);
9938 UChar vB_addr = ifieldRegB(theInstr);
9939 UInt opc2 = IFIELD( theInstr, 0, 11 );
9941 IRTemp signs = IRTemp_INVALID;
9942 IRTemp zeros = IRTemp_INVALID;
9943 IRTemp vA = newTemp(Ity_V128);
9944 IRTemp vB = newTemp(Ity_V128);
9945 assign( vA, getVReg(vA_addr));
9946 assign( vB, getVReg(vB_addr));
9949 vex_printf("dis_av_pack(ppc)(instr)\n");
9955 case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
9956 DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9957 putVReg( vD_addr, binop(Iop_Narrow16x8, mkexpr(vA), mkexpr(vB)) );
9960 case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
9961 DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9962 putVReg( vD_addr, binop(Iop_Narrow32x4, mkexpr(vA), mkexpr(vB)) );
9965 case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
9966 DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9968 binop(Iop_QNarrow16Ux8, mkexpr(vA), mkexpr(vB)) );
9969 // TODO: set VSCR[SAT]
9972 case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
9973 DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9975 binop(Iop_QNarrow32Ux4, mkexpr(vA), mkexpr(vB)) );
9976 // TODO: set VSCR[SAT]
9979 case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
9980 // This insn does a signed->unsigned saturating conversion.
9981 // Conversion done here, then uses unsigned->unsigned vpk insn:
9982 // => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
9983 IRTemp vA_tmp = newTemp(Ity_V128);
9984 IRTemp vB_tmp = newTemp(Ity_V128);
9985 DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
9986 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
9989 mkexpr(vA), mkU8(15)))) );
9990 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
9993 mkexpr(vB), mkU8(15)))) );
9994 putVReg( vD_addr, binop(Iop_QNarrow16Ux8,
9995 mkexpr(vA_tmp), mkexpr(vB_tmp)) );
9996 // TODO: set VSCR[SAT]
9999 case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
10000 // This insn does a signed->unsigned saturating conversion.
10001 // Conversion done here, then uses unsigned->unsigned vpk insn:
10002 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
10003 IRTemp vA_tmp = newTemp(Ity_V128);
10004 IRTemp vB_tmp = newTemp(Ity_V128);
10005 DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10006 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
10008 binop(Iop_SarN32x4,
10009 mkexpr(vA), mkU8(31)))) );
10010 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
10012 binop(Iop_SarN32x4,
10013 mkexpr(vB), mkU8(31)))) );
10014 putVReg( vD_addr, binop(Iop_QNarrow32Ux4,
10015 mkexpr(vA_tmp), mkexpr(vB_tmp)) );
10016 // TODO: set VSCR[SAT]
10019 case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
10020 DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10022 binop(Iop_QNarrow16Sx8, mkexpr(vA), mkexpr(vB)) );
10023 // TODO: set VSCR[SAT]
10026 case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
10027 DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10029 binop(Iop_QNarrow32Sx4, mkexpr(vA), mkexpr(vB)) );
10030 // TODO: set VSCR[SAT]
10033 case 0x30E: { // vpkpx (Pack Pixel, AV p219)
10034 /* CAB: Worth a new primop? */
10035 /* Using shifts to compact pixel elements, then packing them */
10036 IRTemp a1 = newTemp(Ity_V128);
10037 IRTemp a2 = newTemp(Ity_V128);
10038 IRTemp a3 = newTemp(Ity_V128);
10039 IRTemp a_tmp = newTemp(Ity_V128);
10040 IRTemp b1 = newTemp(Ity_V128);
10041 IRTemp b2 = newTemp(Ity_V128);
10042 IRTemp b3 = newTemp(Ity_V128);
10043 IRTemp b_tmp = newTemp(Ity_V128);
10044 DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10045 assign( a1, binop(Iop_ShlN16x8,
10046 binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
10048 assign( a2, binop(Iop_ShlN16x8,
10049 binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
10051 assign( a3, binop(Iop_ShrN16x8,
10052 binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
10054 assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
10055 binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
10057 assign( b1, binop(Iop_ShlN16x8,
10058 binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
10060 assign( b2, binop(Iop_ShlN16x8,
10061 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
10063 assign( b3, binop(Iop_ShrN16x8,
10064 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
10066 assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
10067 binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
10069 putVReg( vD_addr, binop(Iop_Narrow32x4,
10070 mkexpr(a_tmp), mkexpr(b_tmp)) );
10075 break; // Fall through...
10079 if (vA_addr != 0) {
10080 vex_printf("dis_av_pack(ppc)(vA_addr)\n");
10084 signs = newTemp(Ity_V128);
10085 zeros = newTemp(Ity_V128);
10086 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
10090 case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
10091 DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
10092 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
10094 binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
10097 case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
10098 DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
10099 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
10101 binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
10104 case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
10105 DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
10106 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
10108 binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
10111 case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
10112 DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
10113 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
10115 binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
10118 case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
10119 /* CAB: Worth a new primop? */
10120 /* Using shifts to isolate pixel elements, then expanding them */
10121 IRTemp z0 = newTemp(Ity_V128);
10122 IRTemp z1 = newTemp(Ity_V128);
10123 IRTemp z01 = newTemp(Ity_V128);
10124 IRTemp z2 = newTemp(Ity_V128);
10125 IRTemp z3 = newTemp(Ity_V128);
10126 IRTemp z23 = newTemp(Ity_V128);
10127 DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
10128 assign( z0, binop(Iop_ShlN16x8,
10129 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
10131 assign( z1, binop(Iop_ShrN16x8,
10132 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
10134 assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
10135 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
10136 assign( z2, binop(Iop_ShrN16x8,
10137 binop(Iop_ShlN16x8,
10138 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
10141 assign( z3, binop(Iop_ShrN16x8,
10142 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
10144 assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
10145 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
10148 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
10152 case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
10153 /* identical to vupkhpx, except interleaving LO */
10154 IRTemp z0 = newTemp(Ity_V128);
10155 IRTemp z1 = newTemp(Ity_V128);
10156 IRTemp z01 = newTemp(Ity_V128);
10157 IRTemp z2 = newTemp(Ity_V128);
10158 IRTemp z3 = newTemp(Ity_V128);
10159 IRTemp z23 = newTemp(Ity_V128);
10160 DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
10161 assign( z0, binop(Iop_ShlN16x8,
10162 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
10164 assign( z1, binop(Iop_ShrN16x8,
10165 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
10167 assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
10168 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
10169 assign( z2, binop(Iop_ShrN16x8,
10170 binop(Iop_ShlN16x8,
10171 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
10174 assign( z3, binop(Iop_ShrN16x8,
10175 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
10177 assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
10178 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
10181 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
10186 vex_printf("dis_av_pack(ppc)(opc2)\n");
10194 AltiVec Floating Point Arithmetic Instructions
10196 static Bool dis_av_fp_arith ( UInt theInstr )
10199 UChar opc1 = ifieldOPC(theInstr);
10200 UChar vD_addr = ifieldRegDS(theInstr);
10201 UChar vA_addr = ifieldRegA(theInstr);
10202 UChar vB_addr = ifieldRegB(theInstr);
10203 UChar vC_addr = ifieldRegC(theInstr);
10206 IRTemp vA = newTemp(Ity_V128);
10207 IRTemp vB = newTemp(Ity_V128);
10208 IRTemp vC = newTemp(Ity_V128);
10209 assign( vA, getVReg(vA_addr));
10210 assign( vB, getVReg(vB_addr));
10211 assign( vC, getVReg(vC_addr));
10214 vex_printf("dis_av_fp_arith(ppc)(instr)\n");
10218 opc2 = IFIELD( theInstr, 0, 6 );
10220 case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
10221 DIP("vmaddfp v%d,v%d,v%d,v%d\n",
10222 vD_addr, vA_addr, vC_addr, vB_addr);
10224 binop(Iop_Add32Fx4, mkexpr(vB),
10225 binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
10228 case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
10229 DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
10230 vD_addr, vA_addr, vC_addr, vB_addr);
10232 binop(Iop_Sub32Fx4,
10234 binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
10239 break; // Fall through...
10242 opc2 = IFIELD( theInstr, 0, 11 );
10244 case 0x00A: // vaddfp (Add FP, AV p137)
10245 DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10246 putVReg( vD_addr, binop(Iop_Add32Fx4, mkexpr(vA), mkexpr(vB)) );
10249 case 0x04A: // vsubfp (Subtract FP, AV p261)
10250 DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10251 putVReg( vD_addr, binop(Iop_Sub32Fx4, mkexpr(vA), mkexpr(vB)) );
10254 case 0x40A: // vmaxfp (Maximum FP, AV p178)
10255 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10256 putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
10259 case 0x44A: // vminfp (Minimum FP, AV p187)
10260 DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
10261 putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
10265 break; // Fall through...
10269 if (vA_addr != 0) {
10270 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
10275 case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
10276 DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
10277 putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) );
10280 case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
10281 DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
10282 putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) );
10285 case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
10286 DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
10287 DIP(" => not implemented\n");
10290 case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
10291 DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
10292 DIP(" => not implemented\n");
10296 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
10303 AltiVec Floating Point Compare Instructions
10305 static Bool dis_av_fp_cmp ( UInt theInstr )
10308 UChar opc1 = ifieldOPC(theInstr);
10309 UChar vD_addr = ifieldRegDS(theInstr);
10310 UChar vA_addr = ifieldRegA(theInstr);
10311 UChar vB_addr = ifieldRegB(theInstr);
10312 UChar flag_rC = ifieldBIT10(theInstr);
10313 UInt opc2 = IFIELD( theInstr, 0, 10 );
10315 Bool cmp_bounds = False;
10317 IRTemp vA = newTemp(Ity_V128);
10318 IRTemp vB = newTemp(Ity_V128);
10319 IRTemp vD = newTemp(Ity_V128);
10320 assign( vA, getVReg(vA_addr));
10321 assign( vB, getVReg(vB_addr));
10324 vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
10329 case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
10330 DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
10331 vD_addr, vA_addr, vB_addr);
10332 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
10335 case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
10336 DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
10337 vD_addr, vA_addr, vB_addr);
10338 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
10341 case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
10342 DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
10343 vD_addr, vA_addr, vB_addr);
10344 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
10347 case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
10348 IRTemp gt = newTemp(Ity_V128);
10349 IRTemp lt = newTemp(Ity_V128);
10350 IRTemp zeros = newTemp(Ity_V128);
10351 DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
10352 vD_addr, vA_addr, vB_addr);
10354 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
10356 /* Note: making use of fact that the ppc backend for compare insns
10357 return zero'd lanes if either of the corresponding arg lanes is
10360 Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
10361 need this for the other compares too (vcmpeqfp etc)...
10362 Better still, tighten down the spec for compare irops.
10364 assign( gt, unop(Iop_NotV128,
10365 binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
10366 assign( lt, unop(Iop_NotV128,
10367 binop(Iop_CmpGE32Fx4, mkexpr(vA),
10368 binop(Iop_Sub32Fx4, mkexpr(zeros),
10371 // finally, just shift gt,lt to correct position
10372 assign( vD, binop(Iop_ShlN32x4,
10374 binop(Iop_AndV128, mkexpr(gt),
10375 unop(Iop_Dup32x4, mkU32(0x2))),
10376 binop(Iop_AndV128, mkexpr(lt),
10377 unop(Iop_Dup32x4, mkU32(0x1)))),
10383 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
10387 putVReg( vD_addr, mkexpr(vD) );
10390 set_AV_CR6( mkexpr(vD), !cmp_bounds );
10396 AltiVec Floating Point Convert/Round Instructions
10398 static Bool dis_av_fp_convert ( UInt theInstr )
10401 UChar opc1 = ifieldOPC(theInstr);
10402 UChar vD_addr = ifieldRegDS(theInstr);
10403 UChar UIMM_5 = ifieldRegA(theInstr);
10404 UChar vB_addr = ifieldRegB(theInstr);
10405 UInt opc2 = IFIELD( theInstr, 0, 11 );
10407 IRTemp vB = newTemp(Ity_V128);
10408 IRTemp vScale = newTemp(Ity_V128);
10409 IRTemp vInvScale = newTemp(Ity_V128);
10411 float scale, inv_scale;
10413 assign( vB, getVReg(vB_addr));
10415 /* scale = 2^UIMM, cast to float, reinterpreted as uint */
10416 scale = (float)( (unsigned int) 1<<UIMM_5 );
10417 assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
10418 inv_scale = 1/scale;
10420 unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
10423 vex_printf("dis_av_fp_convert(ppc)(instr)\n");
10428 case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
10429 DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
10430 putVReg( vD_addr, binop(Iop_Mul32Fx4,
10431 unop(Iop_I32UtoFx4, mkexpr(vB)),
10432 mkexpr(vInvScale)) );
10435 case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
10436 DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
10438 putVReg( vD_addr, binop(Iop_Mul32Fx4,
10439 unop(Iop_I32StoFx4, mkexpr(vB)),
10440 mkexpr(vInvScale)) );
10443 case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
10444 DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
10446 unop(Iop_QFtoI32Ux4_RZ,
10447 binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
10450 case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
10451 DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
10453 unop(Iop_QFtoI32Sx4_RZ,
10454 binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
10458 break; // Fall through...
10462 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
10467 case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
10468 DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
10469 putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
10472 case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
10473 DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
10474 putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
10477 case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
10478 DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
10479 putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
10482 case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
10483 DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
10484 putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
10488 vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
10495 /* The 0x3C primary opcode (VSX category) uses several different forms of
10496 * extended opcodes:
10498 * - [10:2] (IBM notation [21:29])
10499 * o XX3-form variants:
10500 * - variant 1: [10:3] (IBM notation [21:28])
10501 * - variant 2: [9:3] (IBM notation [22:28])
10502 * - variant 3: [7:3] (IBM notation [24:28])
10504 * - [10:6] (IBM notation [21:25])
10506 * The XX2-form needs bit 0 masked from the standard extended opcode
10507 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
10508 * and the XX4-form needs bits 0, 1, and 2 masked. Additionally, the
10509 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
10510 * front end since their encoding does not begin at bit 21 like the standard
10513 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
10514 * secondary opcode for such VSX instructions.
10524 // ATTENTION: Keep this array sorted on the opcocde!!!
10525 static struct vsx_insn vsx_all[] = {
10526 { 0x8, "xxsldwi" },
10528 { 0x28, "xxpermdi" },
10529 { 0x48, "xxmrghw" },
10530 { 0x80, "xsadddp" },
10531 { 0x84, "xsmaddadp" },
10532 { 0x8c, "xscmpudp" },
10533 { 0x90, "xscvdpuxws" },
10534 { 0x92, "xsrdpi" },
10535 { 0x94, "xsrsqrtedp" },
10536 { 0x96, "xssqrtdp" },
10537 { 0xa0, "xssubdp" },
10538 { 0xa4, "xsmaddmdp" },
10539 { 0xac, "xscmpodp" },
10540 { 0xb0, "xscvdpsxws" },
10541 { 0xb2, "xsrdpiz" },
10542 { 0xb4, "xsredp" },
10543 { 0xc0, "xsmuldp" },
10544 { 0xc4, "xsmsubadp" },
10545 { 0xc8, "xxmrglw" },
10546 { 0xd2, "xsrdpip" },
10547 { 0xd4, "xstsqrtdp" },
10548 { 0xd6, "xsrdpic" },
10549 { 0xe0, "xsdivdp" },
10550 { 0xe4, "xsmsubmdp" },
10551 { 0xf2, "xsrdpim" },
10552 { 0xf4, "xstdivdp" },
10553 { 0x100, "xvaddsp" },
10554 { 0x104, "xvmaddasp" },
10555 { 0x10c, "xvcmpeqsp" },
10556 { 0x110, "xvcvspuxws" },
10557 { 0x112, "xvrspi" },
10558 { 0x114, "xvrsqrtesp" },
10559 { 0x116, "xvsqrtsp" },
10560 { 0x120, "xvsubsp" },
10561 { 0x124, "xvmaddmsp" },
10562 { 0x12c, "xvcmpgtsp" },
10563 { 0x130, "xvcvspsxws" },
10564 { 0x132, "xvrspiz" },
10565 { 0x134, "xvresp" },
10566 { 0x140, "xvmulsp" },
10567 { 0x144, "xvmsubasp" },
10568 { 0x148, "xxspltw" },
10569 { 0x14c, "xvcmpgesp" },
10570 { 0x150, "xvcvuxwsp" },
10571 { 0x152, "xvrspip" },
10572 { 0x154, "xvtsqrtsp" },
10573 { 0x156, "xvrspic" },
10574 { 0x160, "xvdivsp" },
10575 { 0x164, "xvmsubmsp" },
10576 { 0x170, "xvcvsxwsp" },
10577 { 0x172, "xvrspim" },
10578 { 0x174, "xvtdivsp" },
10579 { 0x180, "xvadddp" },
10580 { 0x184, "xvmaddadp" },
10581 { 0x18c, "xvcmpeqdp" },
10582 { 0x190, "xvcvdpuxws" },
10583 { 0x192, "xvrdpi" },
10584 { 0x194, "xvrsqrtedp" },
10585 { 0x196, "xvsqrtdp" },
10586 { 0x1a0, "xvsubdp" },
10587 { 0x1a4, "xvmaddmdp" },
10588 { 0x1ac, "xvcmpgtdp" },
10589 { 0x1b0, "xvcvdpsxws" },
10590 { 0x1b2, "xvrdpiz" },
10591 { 0x1b4, "xvredp" },
10592 { 0x1c0, "xvmuldp" },
10593 { 0x1c4, "xvmsubadp" },
10594 { 0x1cc, "xvcmpgedp" },
10595 { 0x1d0, "xvcvuxwdp" },
10596 { 0x1d2, "xvrdpip" },
10597 { 0x1d4, "xvtsqrtdp" },
10598 { 0x1d6, "xvrdpic" },
10599 { 0x1e0, "xvdivdp" },
10600 { 0x1e4, "xvmsubmdp" },
10601 { 0x1f0, "xvcvsxwdp" },
10602 { 0x1f2, "xvrdpim" },
10603 { 0x1f4, "xvtdivdp" },
10604 { 0x208, "xxland" },
10605 { 0x212, "xscvdpsp" },
10606 { 0x228, "xxlandc" },
10607 { 0x248 , "xxlor" },
10608 { 0x268, "xxlxor" },
10609 { 0x280, "xsmaxdp" },
10610 { 0x284, "xsnmaddadp" },
10611 { 0x288, "xxlnor" },
10612 { 0x290, "xscvdpuxds" },
10613 { 0x292, "xscvspdp" },
10614 { 0x2a0, "xsmindp" },
10615 { 0x2a4, "xsnmaddmdp" },
10616 { 0x2b0, "xscvdpsxds" },
10617 { 0x2b2, "xsabsdp" },
10618 { 0x2c0, "xscpsgndp" },
10619 { 0x2c4, "xsnmsubadp" },
10620 { 0x2d0, "xscvuxddp" },
10621 { 0x2d2, "xsnabsdp" },
10622 { 0x2e4, "xsnmsubmdp" },
10623 { 0x2f0, "xscvsxddp" },
10624 { 0x2f2, "xsnegdp" },
10625 { 0x300, "xvmaxsp" },
10626 { 0x304, "xvnmaddasp" },
10627 { 0x30c, "xvcmpeqsp." },
10628 { 0x310, "xvcvspuxds" },
10629 { 0x312, "xvcvdpsp" },
10630 { 0x320, "xvminsp" },
10631 { 0x324, "xvnmaddmsp" },
10632 { 0x32c, "xvcmpgtsp." },
10633 { 0x330, "xvcvspsxds" },
10634 { 0x332, "xvabssp" },
10635 { 0x340, "xvcpsgnsp" },
10636 { 0x344, "xvnmsubasp" },
10637 { 0x34c, "xvcmpgesp." },
10638 { 0x350, "xvcvuxdsp" },
10639 { 0x352, "xvnabssp" },
10640 { 0x364, "xvnmsubmsp" },
10641 { 0x370, "xvcvsxdsp" },
10642 { 0x372, "xvnegsp" },
10643 { 0x380, "xvmaxdp" },
10644 { 0x384, "xvnmaddadp" },
10645 { 0x38c, "xvcmpeqdp." },
10646 { 0x390, "xvcvdpuxds" },
10647 { 0x392, "xvcvspdp" },
10648 { 0x3a0, "xvmindp" },
10649 { 0x3a4, "xvnmaddmdp" },
10650 { 0x3ac, "xvcmpgtdp." },
10651 { 0x3b0, "xvcvdpsxds" },
10652 { 0x3b2, "xvabsdp" },
10653 { 0x3c0, "xvcpsgndp" },
10654 { 0x3c4, "xvnmsubadp" },
10655 { 0x3cc, "xvcmpgedp." },
10656 { 0x3d0, "xvcvuxddp" },
10657 { 0x3d2, "xvnabsdp" },
10658 { 0x3e4, "xvnmsubmdp" },
10659 { 0x3f0, "xvcvsxddp" },
10660 { 0x3f2, "xvnegdp" }
10662 #define VSX_ALL_LEN 135
10664 // ATTENTION: This search function assumes vsx_all array is sorted.
10665 static Int findVSXextOpCode(UInt opcode)
10667 Int low, mid, high;
10669 high = VSX_ALL_LEN - 1;
10670 while (low <= high) {
10671 mid = (low + high)/2;
10672 if (opcode < vsx_all[mid].opcode)
10674 else if (opcode > vsx_all[mid].opcode)
10683 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
10684 * passed, and we then try to match it up with one of the above
10687 static UInt get_VSX60_opc2(UInt opc2_full)
10689 #define XX2_MASK 0x000003FE
10690 #define XX3_1_MASK 0x000003FC
10691 #define XX3_2_MASK 0x000001FC
10692 #define XX3_3_MASK 0x0000007C
10693 #define XX4_MASK 0x000003E0
10695 UInt vsxExtOpcode = 0;
10697 if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
10698 vsxExtOpcode = vsx_all[ret].opcode;
10699 else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
10700 vsxExtOpcode = vsx_all[ret].opcode;
10701 else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
10702 vsxExtOpcode = vsx_all[ret].opcode;
10703 else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
10704 vsxExtOpcode = vsx_all[ret].opcode;
10705 else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
10706 vsxExtOpcode = vsx_all[ret].opcode;
10708 return vsxExtOpcode;
10711 /*------------------------------------------------------------*/
10712 /*--- Disassemble a single instruction ---*/
10713 /*------------------------------------------------------------*/
10715 /* Disassemble a single instruction into IR. The instruction
10716 is located in host memory at &guest_code[delta]. */
10719 DisResult disInstr_PPC_WRK (
10721 Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
10723 void* callback_opaque,
10725 VexArchInfo* archinfo,
10726 VexAbiInfo* abiinfo
10733 IRType ty = mode64 ? Ity_I64 : Ity_I32;
10734 Bool allow_F = False;
10735 Bool allow_V = False;
10736 Bool allow_FX = False;
10737 Bool allow_GX = False;
10738 Bool allow_VX = False;
10739 UInt hwcaps = archinfo->hwcaps;
10742 /* What insn variants are we supporting today? */
10745 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
10746 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
10747 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
10748 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
10750 allow_F = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
10751 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
10752 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
10753 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
10754 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
10757 /* The running delta */
10758 delta = (Long)mkSzAddr(ty, (ULong)delta64);
10760 /* Set result defaults. */
10761 dres.whatNext = Dis_Continue;
10763 dres.continueAt = 0;
10765 /* At least this is simple on PPC32: insns are all 4 bytes long, and
10766 4-aligned. So just fish the whole thing out of memory right now
10768 theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) );
10770 if (0) vex_printf("insn: 0x%x\n", theInstr);
10772 DIP("\t0x%llx: ", (ULong)guest_CIA_curr_instr);
10774 /* We may be asked to update the guest CIA before going further. */
10776 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
10778 /* Spot "Special" instructions (see comment at top of file). */
10780 UChar* code = (UChar*)(guest_code + delta);
10781 /* Spot the 16-byte preamble:
10783 54001800 rlwinm 0,0,3,0,0
10784 54006800 rlwinm 0,0,13,0,0
10785 5400E800 rlwinm 0,0,29,0,0
10786 54009800 rlwinm 0,0,19,0,0
10788 78001800 rotldi 0,0,3
10789 78006800 rotldi 0,0,13
10790 7800E802 rotldi 0,0,61
10791 78009802 rotldi 0,0,51
10793 UInt word1 = mode64 ? 0x78001800 : 0x54001800;
10794 UInt word2 = mode64 ? 0x78006800 : 0x54006800;
10795 UInt word3 = mode64 ? 0x7800E802 : 0x5400E800;
10796 UInt word4 = mode64 ? 0x78009802 : 0x54009800;
10797 if (getUIntBigendianly(code+ 0) == word1 &&
10798 getUIntBigendianly(code+ 4) == word2 &&
10799 getUIntBigendianly(code+ 8) == word3 &&
10800 getUIntBigendianly(code+12) == word4) {
10801 /* Got a "Special" instruction preamble. Which one is it? */
10802 if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
10803 /* %R3 = client_request ( %R4 ) */
10804 DIP("r3 = client_request ( %%r4 )\n");
10806 irsb->next = mkSzImm( ty, guest_CIA_bbstart + delta );
10807 irsb->jumpkind = Ijk_ClientReq;
10808 dres.whatNext = Dis_StopHere;
10809 goto decode_success;
10812 if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
10813 /* %R3 = guest_NRADDR */
10814 DIP("r3 = guest_NRADDR\n");
10817 putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
10818 goto decode_success;
10821 if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
10822 /* branch-and-link-to-noredir %R11 */
10823 DIP("branch-and-link-to-noredir r11\n");
10825 putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
10826 irsb->next = getIReg(11);
10827 irsb->jumpkind = Ijk_NoRedir;
10828 dres.whatNext = Dis_StopHere;
10829 goto decode_success;
10832 if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
10833 /* %R3 = guest_NRADDR_GPR2 */
10834 DIP("r3 = guest_NRADDR_GPR2\n");
10837 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
10838 goto decode_success;
10840 /* We don't know what it is. Set opc1/opc2 so decode_failure
10841 can print the insn following the Special-insn preamble. */
10842 theInstr = getUIntBigendianly(code+16);
10843 opc1 = ifieldOPC(theInstr);
10844 opc2 = ifieldOPClo10(theInstr);
10845 goto decode_failure;
10850 opc1 = ifieldOPC(theInstr);
10851 opc2 = ifieldOPClo10(theInstr);
10853 // Note: all 'reserved' bits must be cleared, else invalid
10856 /* Integer Arithmetic Instructions */
10857 case 0x0C: case 0x0D: case 0x0E: // addic, addic., addi
10858 case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic
10859 if (dis_int_arith( theInstr )) goto decode_success;
10860 goto decode_failure;
10862 /* Integer Compare Instructions */
10863 case 0x0B: case 0x0A: // cmpi, cmpli
10864 if (dis_int_cmp( theInstr )) goto decode_success;
10865 goto decode_failure;
10867 /* Integer Logical Instructions */
10868 case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
10869 case 0x19: case 0x1A: case 0x1B: // oris, xori, xoris
10870 if (dis_int_logic( theInstr )) goto decode_success;
10871 goto decode_failure;
10873 /* Integer Rotate Instructions */
10874 case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm
10875 if (dis_int_rot( theInstr )) goto decode_success;
10876 goto decode_failure;
10878 /* 64bit Integer Rotate Instructions */
10879 case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
10880 if (dis_int_rot( theInstr )) goto decode_success;
10881 goto decode_failure;
10883 /* Integer Load Instructions */
10884 case 0x22: case 0x23: case 0x2A: // lbz, lbzu, lha
10885 case 0x2B: case 0x28: case 0x29: // lhau, lhz, lhzu
10886 case 0x20: case 0x21: // lwz, lwzu
10887 if (dis_int_load( theInstr )) goto decode_success;
10888 goto decode_failure;
10890 /* Integer Store Instructions */
10891 case 0x26: case 0x27: case 0x2C: // stb, stbu, sth
10892 case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu
10893 if (dis_int_store( theInstr, abiinfo )) goto decode_success;
10894 goto decode_failure;
10896 /* Integer Load and Store Multiple Instructions */
10897 case 0x2E: case 0x2F: // lmw, stmw
10898 if (dis_int_ldst_mult( theInstr )) goto decode_success;
10899 goto decode_failure;
10901 /* Branch Instructions */
10902 case 0x12: case 0x10: // b, bc
10903 if (dis_branch(theInstr, abiinfo, &dres,
10904 resteerOkFn, callback_opaque))
10905 goto decode_success;
10906 goto decode_failure;
10908 /* System Linkage Instructions */
10910 if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
10911 goto decode_failure;
10913 /* Trap Instructions */
10914 case 0x02: case 0x03: // tdi, twi
10915 if (dis_trapi(theInstr, &dres)) goto decode_success;
10916 goto decode_failure;
10918 /* Floating Point Load Instructions */
10919 case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
10921 if (!allow_F) goto decode_noF;
10922 if (dis_fp_load( theInstr )) goto decode_success;
10923 goto decode_failure;
10925 /* Floating Point Store Instructions */
10926 case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
10927 case 0x37: // stfdux
10928 if (!allow_F) goto decode_noF;
10929 if (dis_fp_store( theInstr )) goto decode_success;
10930 goto decode_failure;
10932 /* Floating Point Load Double Pair Instructions */
10933 case 0x39: case 0x3D:
10934 if (!allow_F) goto decode_noF;
10935 if (dis_fp_pair( theInstr )) goto decode_success;
10936 goto decode_failure;
10938 /* 64bit Integer Loads */
10939 case 0x3A: // ld, ldu, lwa
10940 if (!mode64) goto decode_failure;
10941 if (dis_int_load( theInstr )) goto decode_success;
10942 goto decode_failure;
10945 if (!allow_F) goto decode_noF;
10946 opc2 = ifieldOPClo10(theInstr);
10948 case 0x3CE: // fcfidus (implemented as native insn
10951 if (dis_fp_round( theInstr ))
10952 goto decode_success;
10953 goto decode_failure;
10954 case 0x34E: // fcfids
10955 if (dis_fp_round( theInstr ))
10956 goto decode_success;
10957 goto decode_failure;
10960 opc2 = IFIELD(theInstr, 1, 5);
10962 /* Floating Point Arith Instructions */
10963 case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds
10964 case 0x19: // fmuls
10965 if (dis_fp_arith(theInstr)) goto decode_success;
10966 goto decode_failure;
10967 case 0x16: // fsqrts
10968 if (!allow_FX) goto decode_noFX;
10969 if (dis_fp_arith(theInstr)) goto decode_success;
10970 goto decode_failure;
10972 if (!allow_GX) goto decode_noGX;
10973 if (dis_fp_arith(theInstr)) goto decode_success;
10974 goto decode_failure;
10976 /* Floating Point Mult-Add Instructions */
10977 case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
10978 case 0x1F: // fnmadds
10979 if (dis_fp_multadd(theInstr)) goto decode_success;
10980 goto decode_failure;
10982 case 0x1A: // frsqrtes
10983 if (!allow_GX) goto decode_noGX;
10984 if (dis_fp_arith(theInstr)) goto decode_success;
10985 goto decode_failure;
10988 goto decode_failure;
10992 case 0x3C: // VSX instructions (except load/store)
10994 UInt vsxOpc2 = get_VSX60_opc2(opc2);
10995 /* The vsxOpc2 returned is the "normalized" value, representing the
10996 * instructions secondary opcode as taken from the standard secondary
10997 * opcode field [21:30] (IBM notatition), even if the actual field
10998 * is non-standard. These normalized values are given in the opcode
10999 * appendices of the ISA 2.06 document.
11002 goto decode_failure;
11005 case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
11006 if (dis_vx_permute(theInstr, vsxOpc2)) goto decode_success;
11007 goto decode_failure;
11008 case 0x268: case 0x248: case 0x288: case 0x208: case 0x228: // xxlxor, xxlor, xxlnor, xxland, xxlandc
11009 if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
11010 goto decode_failure;
11011 case 0x2B2: // xsabsdp
11012 if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
11013 goto decode_failure;
11014 case 0x2C0: // xscpsgndp
11015 if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
11016 goto decode_failure;
11017 case 0x2D2: // xsnabsdp
11018 if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
11019 goto decode_failure;
11020 case 0x2F2: // xsnegdp
11021 if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
11022 goto decode_failure;
11023 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
11024 if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
11025 goto decode_failure;
11026 case 0x080: case 0x0E0: // xsadddp, xsdivdp
11027 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
11028 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
11029 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
11030 case 0x0C0: // xsmuldp
11031 case 0x0A0: // xssubdp
11032 if (dis_vx_arith(theInstr, vsxOpc2)) goto decode_success;
11033 goto decode_failure;
11034 case 0x2B0: case 0x2F0: case 0x2D0: // xscvdpsxds, xscvsxddp, xscvuxddp
11035 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
11036 goto decode_failure;
11039 goto decode_failure;
11044 /* 64bit Integer Stores */
11045 case 0x3E: // std, stdu
11046 if (!mode64) goto decode_failure;
11047 if (dis_int_store( theInstr, abiinfo )) goto decode_success;
11048 goto decode_failure;
11051 if (!allow_F) goto decode_noF;
11052 /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
11053 so we can simply fall through the first switch statement */
11055 opc2 = IFIELD(theInstr, 1, 5);
11057 /* Floating Point Arith Instructions */
11058 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
11060 if (dis_fp_arith(theInstr)) goto decode_success;
11061 goto decode_failure;
11062 case 0x16: // fsqrt
11063 if (!allow_FX) goto decode_noFX;
11064 if (dis_fp_arith(theInstr)) goto decode_success;
11065 goto decode_failure;
11066 case 0x17: case 0x1A: // fsel, frsqrte
11067 if (!allow_GX) goto decode_noGX;
11068 if (dis_fp_arith(theInstr)) goto decode_success;
11069 goto decode_failure;
11071 /* Floating Point Mult-Add Instructions */
11072 case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
11073 case 0x1F: // fnmadd
11074 if (dis_fp_multadd(theInstr)) goto decode_success;
11075 goto decode_failure;
11078 if (!allow_GX) goto decode_noGX;
11079 if (dis_fp_arith(theInstr)) goto decode_success;
11080 goto decode_failure;
11083 break; // Fall through
11086 opc2 = IFIELD(theInstr, 1, 10);
11088 /* Floating Point Compare Instructions */
11089 case 0x000: // fcmpu
11090 case 0x020: // fcmpo
11091 if (dis_fp_cmp(theInstr)) goto decode_success;
11092 goto decode_failure;
11094 case 0x080: // ftdiv
11095 if (dis_fp_ftdiv(theInstr)) goto decode_success;
11096 goto decode_failure;
11098 /* Floating Point Rounding/Conversion Instructions */
11099 case 0x00C: // frsp
11100 case 0x00E: // fctiw
11101 case 0x00F: // fctiwz
11102 case 0x32E: // fctid
11103 case 0x32F: // fctidz
11104 case 0x34E: // fcfid
11105 if (dis_fp_round(theInstr)) goto decode_success;
11106 goto decode_failure;
11107 case 0x3CE: // fcfidu (implemented as native insn)
11108 if (!allow_VX) goto decode_noVX;
11109 if (dis_fp_round(theInstr)) goto decode_success;
11110 goto decode_failure;
11113 /* Power6 rounding stuff */
11114 case 0x1E8: // frim
11115 case 0x1C8: // frip
11116 case 0x188: // frin
11117 case 0x1A8: // friz
11118 /* A hack to check for P6 capability . . . */
11119 if ((allow_F && allow_V && allow_FX && allow_GX) &&
11120 (dis_fp_round(theInstr)))
11121 goto decode_success;
11122 goto decode_failure;
11124 /* Floating Point Move Instructions */
11125 case 0x008: // fcpsgn
11126 case 0x028: // fneg
11128 case 0x088: // fnabs
11129 case 0x108: // fabs
11130 if (dis_fp_move( theInstr )) goto decode_success;
11131 goto decode_failure;
11133 /* Floating Point Status/Control Register Instructions */
11134 case 0x026: // mtfsb1
11135 case 0x040: // mcrfs
11136 case 0x046: // mtfsb0
11137 case 0x086: // mtfsfi
11138 case 0x247: // mffs
11139 case 0x2C7: // mtfsf
11140 if (dis_fp_scr( theInstr )) goto decode_success;
11141 goto decode_failure;
11144 goto decode_failure;
11151 /* Condition Register Logical Instructions */
11152 case 0x101: case 0x081: case 0x121: // crand, crandc, creqv
11153 case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror
11154 case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf
11155 if (dis_cond_logic( theInstr )) goto decode_success;
11156 goto decode_failure;
11158 /* Branch Instructions */
11159 case 0x210: case 0x010: // bcctr, bclr
11160 if (dis_branch(theInstr, abiinfo, &dres,
11161 resteerOkFn, callback_opaque))
11162 goto decode_success;
11163 goto decode_failure;
11165 /* Memory Synchronization Instructions */
11166 case 0x096: // isync
11167 if (dis_memsync( theInstr )) goto decode_success;
11168 goto decode_failure;
11171 goto decode_failure;
11178 /* For arith instns, bit10 is the OE flag (overflow enable) */
11180 opc2 = IFIELD(theInstr, 1, 9);
11182 /* Integer Arithmetic Instructions */
11183 case 0x10A: case 0x00A: case 0x08A: // add, addc, adde
11184 case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
11185 case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
11186 case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf
11187 case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
11188 case 0x0C8: // subfze
11189 if (dis_int_arith( theInstr )) goto decode_success;
11190 goto decode_failure;
11192 /* 64bit Integer Arithmetic */
11193 case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
11194 case 0x1C9: case 0x1E9: // divdu, divd
11195 if (!mode64) goto decode_failure;
11196 if (dis_int_arith( theInstr )) goto decode_success;
11197 goto decode_failure;
11199 case 0x1FC: // cmpb
11200 if (dis_int_logic( theInstr )) goto decode_success;
11201 goto decode_failure;
11204 break; // Fall through...
11207 /* All remaining opcodes use full 10 bits. */
11209 opc2 = IFIELD(theInstr, 1, 10);
11211 /* Integer Compare Instructions */
11212 case 0x000: case 0x020: // cmp, cmpl
11213 if (dis_int_cmp( theInstr )) goto decode_success;
11214 goto decode_failure;
11216 /* Integer Logical Instructions */
11217 case 0x01C: case 0x03C: case 0x01A: // and, andc, cntlzw
11218 case 0x11C: case 0x3BA: case 0x39A: // eqv, extsb, extsh
11219 case 0x1DC: case 0x07C: case 0x1BC: // nand, nor, or
11220 case 0x19C: case 0x13C: // orc, xor
11221 case 0x2DF: case 0x25F: // mftgpr, mffgpr
11222 if (dis_int_logic( theInstr )) goto decode_success;
11223 goto decode_failure;
11225 /* 64bit Integer Logical Instructions */
11226 case 0x3DA: case 0x03A: // extsw, cntlzd
11227 if (!mode64) goto decode_failure;
11228 if (dis_int_logic( theInstr )) goto decode_success;
11229 goto decode_failure;
11231 /* 64bit Integer Parity Instructions */
11232 case 0xba: case 0x9a: // prtyd, prtyw
11233 if (dis_int_parity( theInstr )) goto decode_success;
11234 goto decode_failure;
11236 /* Integer Shift Instructions */
11237 case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
11239 if (dis_int_shift( theInstr )) goto decode_success;
11240 goto decode_failure;
11242 /* 64bit Integer Shift Instructions */
11243 case 0x01B: case 0x31A: // sld, srad
11244 case 0x33A: case 0x33B: // sradi
11246 if (!mode64) goto decode_failure;
11247 if (dis_int_shift( theInstr )) goto decode_success;
11248 goto decode_failure;
11250 /* Integer Load Instructions */
11251 case 0x057: case 0x077: case 0x157: // lbzx, lbzux, lhax
11252 case 0x177: case 0x117: case 0x137: // lhaux, lhzx, lhzux
11253 case 0x017: case 0x037: // lwzx, lwzux
11254 if (dis_int_load( theInstr )) goto decode_success;
11255 goto decode_failure;
11257 /* 64bit Integer Load Instructions */
11258 case 0x035: case 0x015: // ldux, ldx
11259 case 0x175: case 0x155: // lwaux, lwax
11260 if (!mode64) goto decode_failure;
11261 if (dis_int_load( theInstr )) goto decode_success;
11262 goto decode_failure;
11264 /* Integer Store Instructions */
11265 case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux
11266 case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx
11267 if (dis_int_store( theInstr, abiinfo )) goto decode_success;
11268 goto decode_failure;
11270 /* 64bit Integer Store Instructions */
11271 case 0x0B5: case 0x095: // stdux, stdx
11272 if (!mode64) goto decode_failure;
11273 if (dis_int_store( theInstr, abiinfo )) goto decode_success;
11274 goto decode_failure;
11276 /* Integer Load and Store with Byte Reverse Instructions */
11277 case 0x316: case 0x216: case 0x396: // lhbrx, lwbrx, sthbrx
11278 case 0x296: case 0x214: // stwbrx, ldbrx
11279 if (dis_int_ldst_rev( theInstr )) goto decode_success;
11280 goto decode_failure;
11282 /* Integer Load and Store String Instructions */
11283 case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
11284 case 0x295: { // stswx
11285 Bool stopHere = False;
11286 Bool ok = dis_int_ldst_str( theInstr, &stopHere );
11287 if (!ok) goto decode_failure;
11289 irsb->next = mkSzImm(ty, nextInsnAddr());
11290 irsb->jumpkind = Ijk_Boring;
11291 dres.whatNext = Dis_StopHere;
11293 goto decode_success;
11296 /* Memory Synchronization Instructions */
11297 case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
11298 case 0x256: // sync
11299 if (dis_memsync( theInstr )) goto decode_success;
11300 goto decode_failure;
11302 /* 64bit Memory Synchronization Instructions */
11303 case 0x054: case 0x0D6: // ldarx, stdcx.
11304 if (!mode64) goto decode_failure;
11305 if (dis_memsync( theInstr )) goto decode_success;
11306 goto decode_failure;
11308 /* Processor Control Instructions */
11309 case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr
11310 case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr
11311 if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
11312 goto decode_failure;
11314 /* Cache Management Instructions */
11315 case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst
11316 case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
11317 case 0x3D6: // icbi
11318 if (dis_cache_manage( theInstr, &dres, archinfo ))
11319 goto decode_success;
11320 goto decode_failure;
11322 //zz /* External Control Instructions */
11323 //zz case 0x136: case 0x1B6: // eciwx, ecowx
11324 //zz DIP("external control op => not implemented\n");
11325 //zz goto decode_failure;
11327 /* Trap Instructions */
11328 case 0x004: case 0x044: // tw, td
11329 if (dis_trap(theInstr, &dres)) goto decode_success;
11330 goto decode_failure;
11332 /* Floating Point Load Instructions */
11333 case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
11334 case 0x277: // lfdux
11335 if (!allow_F) goto decode_noF;
11336 if (dis_fp_load( theInstr )) goto decode_success;
11337 goto decode_failure;
11339 /* Floating Point Store Instructions */
11340 case 0x297: case 0x2B7: case 0x2D7: // stfs, stfsu, stfd
11341 case 0x2F7: // stfdu, stfiwx
11342 if (!allow_F) goto decode_noF;
11343 if (dis_fp_store( theInstr )) goto decode_success;
11344 goto decode_failure;
11345 case 0x3D7: // stfiwx
11346 if (!allow_F) goto decode_noF;
11347 if (!allow_GX) goto decode_noGX;
11348 if (dis_fp_store( theInstr )) goto decode_success;
11349 goto decode_failure;
11351 /* Floating Point Double Pair Indexed Instructions */
11352 case 0x317: // lfdpx (Power6)
11353 case 0x397: // stfdpx (Power6)
11354 if (!allow_F) goto decode_noF;
11355 if (dis_fp_pair(theInstr)) goto decode_success;
11356 goto decode_failure;
11358 case 0x357: // lfiwax
11359 if (!allow_F) goto decode_noF;
11360 if (dis_fp_load( theInstr )) goto decode_success;
11361 goto decode_failure;
11363 case 0x377: // lfiwzx
11364 if (!allow_F) goto decode_noF;
11365 if (dis_fp_load( theInstr )) goto decode_success;
11366 goto decode_failure;
11368 /* AltiVec instructions */
11370 /* AV Cache Control - Data streams */
11371 case 0x156: case 0x176: case 0x336: // dst, dstst, dss
11372 if (!allow_V) goto decode_noV;
11373 if (dis_av_datastream( theInstr )) goto decode_success;
11374 goto decode_failure;
11377 case 0x006: case 0x026: // lvsl, lvsr
11378 case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
11379 case 0x067: case 0x167: // lvx, lvxl
11380 if (!allow_V) goto decode_noV;
11381 if (dis_av_load( abiinfo, theInstr )) goto decode_success;
11382 goto decode_failure;
11385 case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
11386 case 0x0E7: case 0x1E7: // stvx, stvxl
11387 if (!allow_V) goto decode_noV;
11388 if (dis_av_store( theInstr )) goto decode_success;
11389 goto decode_failure;
11392 case 0x24C: // lxsdx
11393 case 0x34C: // lxvd2x
11394 case 0x14C: // lxvdsx
11395 case 0x30C: // lxvw4x
11396 if (dis_vx_load( theInstr )) goto decode_success;
11397 goto decode_failure;
11400 case 0x2CC: // stxsdx
11401 case 0x3CC: // stxvd2x
11402 case 0x38C: // stxvw4x
11403 if (dis_vx_store( theInstr )) goto decode_success;
11404 goto decode_failure;
11406 /* Miscellaneous ISA 2.06 instructions */
11407 case 0x1FA: // popcntd
11408 if (dis_int_logic( theInstr )) goto decode_success;
11409 goto decode_failure;
11412 /* Deal with some other cases that we would otherwise have
11414 /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
11415 /* only decode this insn when reserved bit 0 (31 in IBM's
11416 notation) is zero */
11417 if (IFIELD(theInstr, 0, 6) == (15<<1)) {
11418 UInt rT = ifieldRegDS( theInstr );
11419 UInt rA = ifieldRegA( theInstr );
11420 UInt rB = ifieldRegB( theInstr );
11421 UInt bi = ifieldRegC( theInstr );
11424 IRExpr_Mux0X( unop(Iop_32to8,getCRbit( bi )),
11426 rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
11429 DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
11430 goto decode_success;
11432 goto decode_failure;
11438 /* AltiVec instructions */
11440 opc2 = IFIELD(theInstr, 0, 6);
11442 /* AV Mult-Add, Mult-Sum */
11443 case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
11444 case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
11445 case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
11446 if (!allow_V) goto decode_noV;
11447 if (dis_av_multarith( theInstr )) goto decode_success;
11448 goto decode_failure;
11450 /* AV Permutations */
11452 case 0x2B: // vperm
11453 case 0x2C: // vsldoi
11454 if (!allow_V) goto decode_noV;
11455 if (dis_av_permute( theInstr )) goto decode_success;
11456 goto decode_failure;
11458 /* AV Floating Point Mult-Add/Sub */
11459 case 0x2E: case 0x2F: // vmaddfp, vnmsubfp
11460 if (!allow_V) goto decode_noV;
11461 if (dis_av_fp_arith( theInstr )) goto decode_success;
11462 goto decode_failure;
11465 break; // Fall through...
11468 opc2 = IFIELD(theInstr, 0, 11);
11470 /* AV Arithmetic */
11471 case 0x180: // vaddcuw
11472 case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
11473 case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
11474 case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
11475 case 0x580: // vsubcuw
11476 case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
11477 case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
11478 case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
11479 case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
11480 case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
11481 case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
11482 case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
11483 case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
11484 case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
11485 case 0x008: case 0x048: // vmuloub, vmulouh
11486 case 0x108: case 0x148: // vmulosb, vmulosh
11487 case 0x208: case 0x248: // vmuleub, vmuleuh
11488 case 0x308: case 0x348: // vmulesb, vmulesh
11489 case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
11490 case 0x688: case 0x788: // vsum2sws, vsumsws
11491 if (!allow_V) goto decode_noV;
11492 if (dis_av_arith( theInstr )) goto decode_success;
11493 goto decode_failure;
11495 /* AV Rotate, Shift */
11496 case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
11497 case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
11498 case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
11499 case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
11500 case 0x1C4: case 0x2C4: // vsl, vsr
11501 case 0x40C: case 0x44C: // vslo, vsro
11502 if (!allow_V) goto decode_noV;
11503 if (dis_av_shift( theInstr )) goto decode_success;
11504 goto decode_failure;
11507 case 0x404: case 0x444: case 0x484: // vand, vandc, vor
11508 case 0x4C4: case 0x504: // vxor, vnor
11509 if (!allow_V) goto decode_noV;
11510 if (dis_av_logic( theInstr )) goto decode_success;
11511 goto decode_failure;
11513 /* AV Processor Control */
11514 case 0x604: case 0x644: // mfvscr, mtvscr
11515 if (!allow_V) goto decode_noV;
11516 if (dis_av_procctl( theInstr )) goto decode_success;
11517 goto decode_failure;
11519 /* AV Floating Point Arithmetic */
11520 case 0x00A: case 0x04A: // vaddfp, vsubfp
11521 case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
11522 case 0x1CA: // vlogefp
11523 case 0x40A: case 0x44A: // vmaxfp, vminfp
11524 if (!allow_V) goto decode_noV;
11525 if (dis_av_fp_arith( theInstr )) goto decode_success;
11526 goto decode_failure;
11528 /* AV Floating Point Round/Convert */
11529 case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
11530 case 0x2CA: // vrfim
11531 case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
11532 case 0x3CA: // vctsxs
11533 if (!allow_V) goto decode_noV;
11534 if (dis_av_fp_convert( theInstr )) goto decode_success;
11535 goto decode_failure;
11537 /* AV Merge, Splat */
11538 case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
11539 case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
11540 case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
11541 case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
11542 if (!allow_V) goto decode_noV;
11543 if (dis_av_permute( theInstr )) goto decode_success;
11544 goto decode_failure;
11546 /* AV Pack, Unpack */
11547 case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
11548 case 0x0CE: // vpkuwus
11549 case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
11550 case 0x1CE: // vpkswss
11551 case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
11552 case 0x2CE: // vupklsh
11553 case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
11554 if (!allow_V) goto decode_noV;
11555 if (dis_av_pack( theInstr )) goto decode_success;
11556 goto decode_failure;
11559 break; // Fall through...
11562 opc2 = IFIELD(theInstr, 0, 10);
11566 case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
11567 case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
11568 case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
11569 if (!allow_V) goto decode_noV;
11570 if (dis_av_cmp( theInstr )) goto decode_success;
11571 goto decode_failure;
11573 /* AV Floating Point Compare */
11574 case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
11575 case 0x3C6: // vcmpbfp
11576 if (!allow_V) goto decode_noV;
11577 if (dis_av_fp_cmp( theInstr )) goto decode_success;
11578 goto decode_failure;
11581 goto decode_failure;
11586 goto decode_failure;
11590 vex_printf("disInstr(ppc): declined to decode an FP insn.\n");
11591 goto decode_failure;
11594 vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n");
11595 goto decode_failure;
11597 vassert(!allow_VX);
11598 vex_printf("disInstr(ppc): declined to decode a VSX insn.\n");
11599 goto decode_failure;
11601 vassert(!allow_FX);
11602 vex_printf("disInstr(ppc): "
11603 "declined to decode a GeneralPurpose-Optional insn.\n");
11604 goto decode_failure;
11606 vassert(!allow_GX);
11607 vex_printf("disInstr(ppc): "
11608 "declined to decode a Graphics-Optional insn.\n");
11609 goto decode_failure;
11612 /* All decode failures end up here. */
11613 opc2 = (theInstr) & 0x7FF;
11614 vex_printf("disInstr(ppc): unhandled instruction: "
11615 "0x%x\n", theInstr);
11616 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n",
11617 opc1, opc1, opc2, opc2);
11619 /* Tell the dispatcher that this insn cannot be decoded, and so has
11620 not been executed, and (is currently) the next to be executed.
11621 CIA should be up-to-date since it made so at the start of each
11622 insn, but nevertheless be paranoid and update it again right
11624 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
11625 irsb->next = mkSzImm(ty, guest_CIA_curr_instr);
11626 irsb->jumpkind = Ijk_NoDecode;
11627 dres.whatNext = Dis_StopHere;
11631 } /* switch (opc) for the main (primary) opcode switch. */
11634 /* All decode successes end up here. */
11637 if (dres.len == 0) {
11640 vassert(dres.len == 20);
11649 /*------------------------------------------------------------*/
11650 /*--- Top-level fn ---*/
11651 /*------------------------------------------------------------*/
11653 /* Disassemble a single instruction into IR. The instruction
11654 is located in host memory at &guest_code[delta]. */
11656 DisResult disInstr_PPC ( IRSB* irsb_IN,
11658 Bool (*resteerOkFn) ( void*, Addr64 ),
11660 void* callback_opaque,
11661 UChar* guest_code_IN,
11664 VexArch guest_arch,
11665 VexArchInfo* archinfo,
11666 VexAbiInfo* abiinfo,
11667 Bool host_bigendian_IN )
11671 UInt mask32, mask64;
11672 UInt hwcaps_guest = archinfo->hwcaps;
11674 vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
11676 /* global -- ick */
11677 mode64 = guest_arch == VexArchPPC64;
11678 ty = mode64 ? Ity_I64 : Ity_I32;
11680 /* do some sanity checks */
11681 mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
11682 | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX;
11684 mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
11685 | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX;
11688 vassert((hwcaps_guest & mask32) == 0);
11690 vassert((hwcaps_guest & mask64) == 0);
11693 /* Set globals (see top of this file) */
11694 guest_code = guest_code_IN;
11696 host_is_bigendian = host_bigendian_IN;
11698 guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
11699 guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta);
11701 dres = disInstr_PPC_WRK ( put_IP,
11702 resteerOkFn, resteerCisOk, callback_opaque,
11703 delta, archinfo, abiinfo );
11709 /*------------------------------------------------------------*/
11710 /*--- Unused stuff ---*/
11711 /*------------------------------------------------------------*/
11713 ///* A potentially more memcheck-friendly implementation of Clz32, with
11714 // the boundary case Clz32(0) = 32, which is what ppc requires. */
11716 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
11718 // /* Welcome ... to SSA R Us. */
11719 // IRTemp n1 = newTemp(Ity_I32);
11720 // IRTemp n2 = newTemp(Ity_I32);
11721 // IRTemp n3 = newTemp(Ity_I32);
11722 // IRTemp n4 = newTemp(Ity_I32);
11723 // IRTemp n5 = newTemp(Ity_I32);
11724 // IRTemp n6 = newTemp(Ity_I32);
11725 // IRTemp n7 = newTemp(Ity_I32);
11726 // IRTemp n8 = newTemp(Ity_I32);
11727 // IRTemp n9 = newTemp(Ity_I32);
11728 // IRTemp n10 = newTemp(Ity_I32);
11729 // IRTemp n11 = newTemp(Ity_I32);
11730 // IRTemp n12 = newTemp(Ity_I32);
11732 // /* First, propagate the most significant 1-bit into all lower
11733 // positions in the word. */
11734 // /* unsigned int clz ( unsigned int n )
11741 // return bitcount(~n);
11744 // assign(n1, mkexpr(arg));
11745 // assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
11746 // assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
11747 // assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
11748 // assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
11749 // assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
11750 // /* This gives a word of the form 0---01---1. Now invert it, giving
11751 // a word of the form 1---10---0, then do a population-count idiom
11752 // (to count the 1s, which is the number of leading zeroes, or 32
11753 // if the original word was 0. */
11754 // assign(n7, unop(Iop_Not32, mkexpr(n6)));
11756 // /* unsigned int bitcount ( unsigned int n )
11758 // n = n - ((n >> 1) & 0x55555555);
11759 // n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
11760 // n = (n + (n >> 4)) & 0x0F0F0F0F;
11761 // n = n + (n >> 8);
11762 // n = (n + (n >> 16)) & 0x3F;
11767 // binop(Iop_Sub32,
11769 // binop(Iop_And32,
11770 // binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
11771 // mkU32(0x55555555))));
11773 // binop(Iop_Add32,
11774 // binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
11775 // binop(Iop_And32,
11776 // binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
11777 // mkU32(0x33333333))));
11779 // binop(Iop_And32,
11780 // binop(Iop_Add32,
11782 // binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
11783 // mkU32(0x0F0F0F0F)));
11785 // binop(Iop_Add32,
11787 // binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
11789 // binop(Iop_Add32,
11791 // binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
11793 // binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
11796 /*--------------------------------------------------------------------*/
11797 /*--- end guest_ppc_toIR.c ---*/
11798 /*--------------------------------------------------------------------*/