2 /*--------------------------------------------------------------------*/
3 /*--- begin guest_ppc_toIR.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2004-2017 OpenWorks LLP
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
28 Neither the names of the U.S. Department of Energy nor the
29 University of California nor the names of its contributors may be
30 used to endorse or promote products derived from this software
31 without prior written permission.
36 Spot rld... cases which are simply left/right shifts and emit
37 Shl64/Shr64 accordingly.
41 - lvxl,stvxl: load/store with 'least recently used' hint
48 - Some invalid forms of lswi and lswx are accepted when they should
52 - All exceptions disabled in FPSCR
53 - condition codes not set in FPSCR
55 - Altivec floating point:
57 Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
58 system default of Non-Java mode, we get some small errors
60 This is because Non-Java mode brutally hacks denormalised results
61 to zero, whereas we keep maximum accuracy. However, using
62 Non-Java mode would give us more inaccuracy, as our intermediate
63 results would then be zeroed, too.
65 - AbiHints for the stack red zone are only emitted for
66 unconditional calls and returns (bl, blr). They should also be
67 emitted for conditional calls and returns, but we don't have a
68 way to express that right now. Ah well.
70 - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c)
71 ignores the rounding mode, and generates code that assumes
72 round-to-nearest. This means V will compute incorrect results
73 for uses of these IROps when the rounding mode (first) arg is
74 not mkU32(Irrm_NEAREST).
77 /* "Special" instructions.
79 This instruction decoder can decode four special instructions
80 which mean nothing natively (are no-ops as far as regs/mem are
81 concerned) but have meaning for supporting Valgrind. A special
82 instruction is flagged by a 16-byte preamble:
84 32-bit mode: 5400183E 5400683E 5400E83E 5400983E
85 (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31;
86 rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31)
88 64-bit mode: 78001800 78006800 7800E802 78009802
89 (rotldi 0,0,3; rotldi 0,0,13;
90 rotldi 0,0,61; rotldi 0,0,51)
92 Following that, one of the following 3 are allowed
93 (standard interpretation in parentheses):
95 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 )
96 7C421378 (or 2,2,2) %R3 = guest_NRADDR
97 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 Big endian
98 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R12 Little endian
99 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2
100 7CA52B78 (or 5,5,5) IR injection
102 Any other bytes following the 16-byte preamble are illegal and
103 constitute a failure in instruction decoding. This all assumes
104 that the preamble will never occur except in specific code
105 fragments designed for Valgrind to catch.
108 /* Little Endian notes */
110 * Vector operations in little Endian mode behave in non-obvious ways at times.
111 * Below is an attempt at explaining this.
113 * LE/BE vector example
114 * With a vector of unsigned ints declared as follows:
115 * vector unsigned int vec_inA =
116 { 0x11111111, 0x22222222, 0x33333333, 0x44444444 };
117 * The '0x11111111' word is word zero in both LE and BE format. But the
118 * loaded vector register will have word zero on the far left in BE mode and
119 * on the far right in LE mode. The lvx and stvx instructions work naturally
120 * for whatever endianness is in effect. For example, in LE mode, the stvx
121 * stores word zero (far right word) of the vector at the lowest memory
122 * address of the EA; in BE mode, stvx still stores word zero at the lowest
123 * memory address, but with word zero interpreted as the one at the far left
126 * The lxvd2x and stxvd2x instructions are not so well suited for LE mode.
127 * When the compiler generates an lxvd2x instruction to load the
128 * above-declared vector of unsigned integers, it loads the vector as two
129 * double words, but they are in BE word-wise format. To put the vector in
130 * the right order for LE, the compiler also generates an xxswapd after the
131 * load, which puts it in proper LE format. Similarly, the stxvd2x
132 * instruction has a BE bias, storing the vector in BE word-wise format. But
133 * the compiler also generates an xxswapd prior to the store, thus ensuring
134 * the vector is stored in memory in the correct LE order.
136 * Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts
137 * of a double words and words within a vector. Because of the reverse order
138 * of numbering for LE as described above, the high part refers to word 1 in
139 * LE format. When input data is saved to a guest state vector register
140 * (e.g., via Iop_64HLtoV128), it is first saved to memory and then the
141 * register is loaded via PPCInstr_AvLdSt, which does an lvx instruction.
142 * The saving of the data to memory must be done in proper LE order. For the
143 * inverse operation of extracting data from a vector register (e.g.,
144 * Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting
145 * in stvx), and then integer registers are loaded from the memory location
146 * from where the vector register was saved. Again, this must be done in
147 * proper LE order. So for these various vector Iops, we have LE-specific
148 * code in host_ppc_isel.c
150 * Another unique behavior of vectors in LE mode is with the vector scalar
151 * (VSX) operations that operate on "double word 0" of the source register,
152 * storing the result in "double word 0" of the output vector register. For
153 * these operations, "double word 0" is interpreted as "high half of the
154 * register" (i.e, the part on the left side).
158 /* Notes on handling subnormal results:
160 * The various vector floating point instructions:
161 * vmaddfp, vaddfp, vsubfp, vmaxfp, vminfp, vrefp, vexptefp,
162 * vlogefp, vcmpeqfp, vcmpgefp, vcmpgtfp, vcmpbfp, vrfin, vrfiz,
164 * generate subnormal results that are controled by the VSCR[NJ] bit setting.
166 * The following describes how the host and guest is setup so that the function
167 * dnorm_adj_Vector() can properly handle the results of the Iops in the guest
170 * At startup, on all host variants, we set VSCR[NJ].host = 0 (don't flush to
171 * zero). It stays at 0 permanently.
173 * At startup, we set VSCR[NJ].guest = (if BE then 1 else 0)
175 * When running, guest insns can set/clear/query VSCR[NJ].guest as they
178 * When running, any (guest) insn whose result depends on VSCR[NJ] will query
179 * VSCR[NJ].guest and the results will be truncated accordingly, by
180 * dnorm_adj_Vector(). Because VSCR[NJ].host is always 0, we will always
181 * be able to provide correct guest results for either value of
186 /* Translates PPC32/64 code to IR. */
191 "PowerPC Microprocessor Family:
192 The Programming Environments Manual for 32-Bit Microprocessors"
194 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
197 "PowerPC Microprocessor Family:
198 Programming Environments Manual for 64-Bit Microprocessors"
200 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
203 "PowerPC Microprocessor Family:
204 AltiVec(TM) Technology Programming Environments Manual"
206 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
209 #include "libvex_basictypes.h"
210 #include "libvex_ir.h"
212 #include "libvex_emnote.h"
213 #include "libvex_guest_ppc32.h"
214 #include "libvex_guest_ppc64.h"
216 #include "main_util.h"
217 #include "main_globals.h"
218 #include "guest_generic_bb_to_IR.h"
219 #include "guest_ppc_defs.h"
221 /*------------------------------------------------------------*/
223 /*------------------------------------------------------------*/
225 /* These are set at the start of the translation of an insn, right
226 down in disInstr_PPC, so that we don't have to pass them around
227 endlessly. They are all constant during the translation of any
230 /* We need to know this to do sub-register accesses correctly. */
231 static VexEndness host_endness
;
233 /* Pointer to the guest code area. */
234 static const UChar
* guest_code
;
236 /* The guest address corresponding to guest_code[0]. */
237 static Addr64 guest_CIA_bbstart
;
239 /* The guest address for the instruction currently being
241 static Addr64 guest_CIA_curr_instr
;
243 /* The IRSB* into which we're generating code. */
246 /* Is our guest binary 32 or 64bit? Set at each call to
247 disInstr_PPC below. */
248 static Bool mode64
= False
;
250 // Given a pointer to a function as obtained by "& functionname" in C,
251 // produce a pointer to the actual entry point for the function. For
252 // most platforms it's the identity function. Unfortunately, on
253 // ppc64-linux it isn't (sigh)
254 static void* fnptr_to_fnentry( const VexAbiInfo
* vbi
, void* f
)
256 if (vbi
->host_ppc_calls_use_fndescrs
) {
257 /* f is a pointer to a 3-word function descriptor, of which the
258 first word is the entry address. */
259 /* note, this is correct even with cross-jitting, since this is
260 purely a host issue, not a guest one. */
261 HWord
* fdescr
= (HWord
*)f
;
262 return (void*)(fdescr
[0]);
264 /* Simple; "& f" points directly at the code for f. */
269 /* The OV32 and CA32 bits were added with ISA3.0 */
270 static Bool OV32_CA32_supported
= False
;
272 #define SIGN_BIT 0x8000000000000000ULL
273 #define SIGN_MASK 0x7fffffffffffffffULL
274 #define SIGN_BIT32 0x80000000
275 #define SIGN_MASK32 0x7fffffff
278 /*------------------------------------------------------------*/
279 /*--- Debugging output ---*/
280 /*------------------------------------------------------------*/
282 #define DIP(format, args...) \
283 if (vex_traceflags & VEX_TRACE_FE) \
284 vex_printf(format, ## args)
286 #define DIS(buf, format, args...) \
287 if (vex_traceflags & VEX_TRACE_FE) \
288 vex_sprintf(buf, format, ## args)
291 /*------------------------------------------------------------*/
292 /*--- Offsets of various parts of the ppc32/64 guest state ---*/
293 /*------------------------------------------------------------*/
295 #define offsetofPPCGuestState(_x) \
296 (mode64 ? offsetof(VexGuestPPC64State, _x) : \
297 offsetof(VexGuestPPC32State, _x))
299 #define OFFB_CIA offsetofPPCGuestState(guest_CIA)
300 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
301 #define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO)
302 #define OFFB_LR offsetofPPCGuestState(guest_LR)
303 #define OFFB_CTR offsetofPPCGuestState(guest_CTR)
304 #define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO)
305 #define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV)
306 #define OFFB_XER_OV32 offsetofPPCGuestState(guest_XER_OV32)
307 #define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA)
308 #define OFFB_XER_CA32 offsetofPPCGuestState(guest_XER_CA32)
309 #define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC)
310 #define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND)
311 #define OFFB_DFPROUND offsetofPPCGuestState(guest_DFPROUND)
312 #define OFFB_C_FPCC offsetofPPCGuestState(guest_C_FPCC)
313 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE)
314 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR)
315 #define OFFB_EMNOTE offsetofPPCGuestState(guest_EMNOTE)
316 #define OFFB_CMSTART offsetofPPCGuestState(guest_CMSTART)
317 #define OFFB_CMLEN offsetofPPCGuestState(guest_CMLEN)
318 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR)
319 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
320 #define OFFB_TFHAR offsetofPPCGuestState(guest_TFHAR)
321 #define OFFB_TEXASR offsetofPPCGuestState(guest_TEXASR)
322 #define OFFB_TEXASRU offsetofPPCGuestState(guest_TEXASRU)
323 #define OFFB_TFIAR offsetofPPCGuestState(guest_TFIAR)
324 #define OFFB_PPR offsetofPPCGuestState(guest_PPR)
325 #define OFFB_PSPB offsetofPPCGuestState(guest_PSPB)
326 #define OFFB_DSCR offsetofPPCGuestState(guest_DSCR)
329 /*------------------------------------------------------------*/
330 /*--- Extract instruction fields --- */
331 /*------------------------------------------------------------*/
333 /* Extract field from insn, given idx (zero = lsb) and field length */
334 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
336 /* Extract primary opcode, instr[31:26] */
337 static UChar
ifieldOPC( UInt instr
) {
338 return toUChar( IFIELD( instr
, 26, 6 ) );
341 /* Extract 10-bit secondary opcode, instr[10:1] */
342 static UInt
ifieldOPClo10 ( UInt instr
) {
343 return IFIELD( instr
, 1, 10 );
346 /* Extract 9-bit secondary opcode, instr[9:1] */
347 static UInt
ifieldOPClo9 ( UInt instr
) {
348 return IFIELD( instr
, 1, 9 );
351 /* Extract 8-bit secondary opcode, instr[8:1] */
352 static UInt
ifieldOPClo8 ( UInt instr
) {
353 return IFIELD( instr
, 1, 8 );
356 /* Extract 5-bit secondary opcode, instr[5:1] */
357 static UInt
ifieldOPClo5 ( UInt instr
) {
358 return IFIELD( instr
, 1, 5 );
361 /* Extract 2-bit secondary opcode, instr[1:0] */
362 static UInt
ifieldOPC0o2 ( UInt instr
) {
363 return IFIELD( instr
, 0, 2 );
366 /* Extract RD (destination register) field, instr[25:21] */
367 static UChar
ifieldRegDS( UInt instr
) {
368 return toUChar( IFIELD( instr
, 21, 5 ) );
371 /* Extract XT (destination register) field, instr[0,25:21] */
372 static UChar
ifieldRegXT ( UInt instr
)
374 UChar upper_bit
= toUChar (IFIELD (instr
, 0, 1));
375 UChar lower_bits
= toUChar (IFIELD (instr
, 21, 5));
376 return (upper_bit
<< 5) | lower_bits
;
379 /* Extract XS (store source register) field, instr[0,25:21] */
380 static inline UChar
ifieldRegXS ( UInt instr
)
382 return ifieldRegXT ( instr
);
385 /* Extract RA (1st source register) field, instr[20:16] */
386 static UChar
ifieldRegA ( UInt instr
) {
387 return toUChar( IFIELD( instr
, 16, 5 ) );
390 /* Extract XA (1st source register) field, instr[2,20:16] */
391 static UChar
ifieldRegXA ( UInt instr
)
393 UChar upper_bit
= toUChar (IFIELD (instr
, 2, 1));
394 UChar lower_bits
= toUChar (IFIELD (instr
, 16, 5));
395 return (upper_bit
<< 5) | lower_bits
;
398 /* Extract RB (2nd source register) field, instr[15:11] */
399 static UChar
ifieldRegB ( UInt instr
) {
400 return toUChar( IFIELD( instr
, 11, 5 ) );
403 /* Extract XB (2nd source register) field, instr[1,15:11] */
404 static UChar
ifieldRegXB ( UInt instr
)
406 UChar upper_bit
= toUChar (IFIELD (instr
, 1, 1));
407 UChar lower_bits
= toUChar (IFIELD (instr
, 11, 5));
408 return (upper_bit
<< 5) | lower_bits
;
411 /* Extract RC (3rd source register) field, instr[10:6] */
412 static UChar
ifieldRegC ( UInt instr
) {
413 return toUChar( IFIELD( instr
, 6, 5 ) );
416 /* Extract XC (3rd source register) field, instr[3,10:6] */
417 static UChar
ifieldRegXC ( UInt instr
)
419 UChar upper_bit
= toUChar (IFIELD (instr
, 3, 1));
420 UChar lower_bits
= toUChar (IFIELD (instr
, 6, 5));
421 return (upper_bit
<< 5) | lower_bits
;
424 /* Extract bit 10, instr[10] */
425 static UChar
ifieldBIT10 ( UInt instr
) {
426 return toUChar( IFIELD( instr
, 10, 1 ) );
429 /* Extract 2nd lowest bit, instr[1] */
430 static UChar
ifieldBIT1 ( UInt instr
) {
431 return toUChar( IFIELD( instr
, 1, 1 ) );
434 /* Extract lowest bit, instr[0] */
435 static UChar
ifieldBIT0 ( UInt instr
) {
436 return toUChar( instr
& 0x1 );
439 /* Extract unsigned bottom half, instr[15:0] */
440 static UInt
ifieldUIMM16 ( UInt instr
) {
441 return instr
& 0xFFFF;
444 /* Extract unsigned bottom 26 bits, instr[25:0] */
445 static UInt
ifieldUIMM26 ( UInt instr
) {
446 return instr
& 0x3FFFFFF;
449 /* Extract DM field, instr[9:8] */
450 static UChar
ifieldDM ( UInt instr
) {
451 return toUChar( IFIELD( instr
, 8, 2 ) );
454 /* Extract SHW field, instr[9:8] */
455 static inline UChar
ifieldSHW ( UInt instr
)
457 return ifieldDM ( instr
);
460 /*------------------------------------------------------------*/
461 /*--- Guest-state identifiers ---*/
462 /*------------------------------------------------------------*/
465 PPC_GST_CIA
, // Current Instruction Address
466 PPC_GST_LR
, // Link Register
467 PPC_GST_CTR
, // Count Register
468 PPC_GST_XER
, // Overflow, carry flags, byte count
469 PPC_GST_CR
, // Condition Register
470 PPC_GST_FPSCR
, // Floating Point Status/Control Register
471 PPC_GST_VRSAVE
, // Vector Save/Restore Register
472 PPC_GST_VSCR
, // Vector Status and Control Register
473 PPC_GST_EMWARN
, // Emulation warnings
474 PPC_GST_CMSTART
,// For icbi: start of area to invalidate
475 PPC_GST_CMLEN
, // For icbi: length of area to invalidate
476 PPC_GST_IP_AT_SYSCALL
, // the CIA of the most recently executed SC insn
477 PPC_GST_SPRG3_RO
, // SPRG3
478 PPC_GST_TFHAR
, // Transactional Failure Handler Address Register
479 PPC_GST_TFIAR
, // Transactional Failure Instruction Address Register
480 PPC_GST_TEXASR
, // Transactional EXception And Summary Register
481 PPC_GST_TEXASRU
, // Transactional EXception And Summary Register Upper
482 PPC_GST_PPR
, // Program Priority register
483 PPC_GST_PPR32
, // Upper 32-bits of Program Priority register
484 PPC_GST_PSPB
, /* Problem State Priority Boost register, Note, the
485 * register is initialized to a non-zero value. Currently
486 * Valgrind is not supporting the register value to
487 * automatically decrement. Could be added later if
490 PPC_GST_DSCR
, // Data Stream Control Register
494 #define MASK_FPSCR_RN 0x3ULL // Binary floating point rounding mode
495 #define MASK_FPSCR_DRN 0x700000000ULL // Decimal floating point rounding mode
496 #define MASK_FPSCR_C_FPCC 0x1F000ULL // Floating-Point Condition code FPCC
498 #define MASK_VSCR_VALID 0x00010001
501 /*------------------------------------------------------------*/
502 /*--- Misc Helpers ---*/
503 /*------------------------------------------------------------*/
505 /* Generate mask with 1's from 'begin' through 'end',
506 wrapping if begin > end.
507 begin->end works from right to left, 0=lsb
509 static UInt
MASK32( UInt begin
, UInt end
)
514 m1
= ((UInt
)(-1)) << begin
;
515 m2
= ((UInt
)(-1)) << end
<< 1;
517 if (begin
> end
) mask
= ~mask
; // wrap mask
521 static ULong
MASK64( UInt begin
, UInt end
)
526 m1
= ((ULong
)(-1)) << begin
;
527 m2
= ((ULong
)(-1)) << end
<< 1;
529 if (begin
> end
) mask
= ~mask
; // wrap mask
533 static Addr64
nextInsnAddr( void )
535 return guest_CIA_curr_instr
+ 4;
539 /*------------------------------------------------------------*/
540 /*--- Helper bits and pieces for deconstructing the ---*/
541 /*--- ppc32/64 insn stream. ---*/
542 /*------------------------------------------------------------*/
544 /* Add a statement to the list held by "irsb". */
545 static void stmt ( IRStmt
* st
)
547 addStmtToIRSB( irsb
, st
);
550 /* Generate a new temporary of the given type. */
551 static IRTemp
newTemp ( IRType ty
)
553 vassert(isPlausibleIRType(ty
));
554 return newIRTemp( irsb
->tyenv
, ty
);
557 /* Various simple conversions */
559 static UChar
extend_s_5to8 ( UChar x
)
561 return toUChar((((Int
)x
) << 27) >> 27);
564 static UInt
extend_s_8to32( UChar x
)
566 return (UInt
)((((Int
)x
) << 24) >> 24);
569 static UInt
extend_s_16to32 ( UInt x
)
571 return (UInt
)((((Int
)x
) << 16) >> 16);
574 static ULong
extend_s_16to64 ( UInt x
)
576 return (ULong
)((((Long
)x
) << 48) >> 48);
579 static ULong
extend_s_26to64 ( UInt x
)
581 return (ULong
)((((Long
)x
) << 38) >> 38);
584 static ULong
extend_s_32to64 ( UInt x
)
586 return (ULong
)((((Long
)x
) << 32) >> 32);
589 /* Do a proper-endian load of a 32-bit word, regardless of the endianness
590 of the underlying host. */
591 static UInt
getUIntPPCendianly ( const UChar
* p
)
594 if (host_endness
== VexEndnessBE
) {
609 /*------------------------------------------------------------*/
610 /*--- Helpers for constructing IR. ---*/
611 /*------------------------------------------------------------*/
613 static void assign ( IRTemp dst
, IRExpr
* e
)
615 stmt( IRStmt_WrTmp(dst
, e
) );
618 /* This generates a normal (non store-conditional) store. */
619 static void store ( IRExpr
* addr
, IRExpr
* data
)
621 IRType tyA
= typeOfIRExpr(irsb
->tyenv
, addr
);
622 vassert(tyA
== Ity_I32
|| tyA
== Ity_I64
);
624 if (host_endness
== VexEndnessBE
)
625 stmt( IRStmt_Store(Iend_BE
, addr
, data
) );
627 stmt( IRStmt_Store(Iend_LE
, addr
, data
) );
630 static IRExpr
* unop ( IROp op
, IRExpr
* a
)
632 return IRExpr_Unop(op
, a
);
635 static IRExpr
* binop ( IROp op
, IRExpr
* a1
, IRExpr
* a2
)
637 return IRExpr_Binop(op
, a1
, a2
);
640 static IRExpr
* triop ( IROp op
, IRExpr
* a1
, IRExpr
* a2
, IRExpr
* a3
)
642 return IRExpr_Triop(op
, a1
, a2
, a3
);
645 static IRExpr
* qop ( IROp op
, IRExpr
* a1
, IRExpr
* a2
,
646 IRExpr
* a3
, IRExpr
* a4
)
648 return IRExpr_Qop(op
, a1
, a2
, a3
, a4
);
651 static IRExpr
* mkexpr ( IRTemp tmp
)
653 return IRExpr_RdTmp(tmp
);
656 #define mkU1(_n) IRExpr_Const(IRConst_U1(_n))
658 static IRExpr
* mkU8 ( UChar i
)
660 return IRExpr_Const(IRConst_U8(i
));
663 static IRExpr
* mkU16 ( UInt i
)
665 return IRExpr_Const(IRConst_U16(i
));
668 static IRExpr
* mkU32 ( UInt i
)
670 return IRExpr_Const(IRConst_U32(i
));
673 static IRExpr
* mkU64 ( ULong i
)
675 return IRExpr_Const(IRConst_U64(i
));
678 static IRExpr
* mkV128 ( UShort i
)
680 vassert(i
== 0 || i
== 0xffff);
681 return IRExpr_Const(IRConst_V128(i
));
684 /* This generates a normal (non load-linked) load. */
685 static IRExpr
* load ( IRType ty
, IRExpr
* addr
)
687 if (host_endness
== VexEndnessBE
)
688 return IRExpr_Load(Iend_BE
, ty
, addr
);
690 return IRExpr_Load(Iend_LE
, ty
, addr
);
693 static IRStmt
* stmt_load ( IRTemp result
,
694 IRExpr
* addr
, IRExpr
* storedata
)
696 if (host_endness
== VexEndnessBE
)
697 return IRStmt_LLSC(Iend_BE
, result
, addr
, storedata
);
699 return IRStmt_LLSC(Iend_LE
, result
, addr
, storedata
);
702 static IRExpr
* mkOR1 ( IRExpr
* arg1
, IRExpr
* arg2
)
704 vassert(typeOfIRExpr(irsb
->tyenv
, arg1
) == Ity_I1
);
705 vassert(typeOfIRExpr(irsb
->tyenv
, arg2
) == Ity_I1
);
706 return unop(Iop_32to1
, binop(Iop_Or32
, unop(Iop_1Uto32
, arg1
),
707 unop(Iop_1Uto32
, arg2
)));
710 static IRExpr
* mkAND1 ( IRExpr
* arg1
, IRExpr
* arg2
)
712 vassert(typeOfIRExpr(irsb
->tyenv
, arg1
) == Ity_I1
);
713 vassert(typeOfIRExpr(irsb
->tyenv
, arg2
) == Ity_I1
);
714 return unop(Iop_32to1
, binop(Iop_And32
, unop(Iop_1Uto32
, arg1
),
715 unop(Iop_1Uto32
, arg2
)));
718 static inline IRExpr
* mkXOr4_32( IRTemp t0
, IRTemp t1
, IRTemp t2
,
721 return binop( Iop_Xor32
,
722 binop( Iop_Xor32
, mkexpr( t0
), mkexpr( t1
) ),
723 binop( Iop_Xor32
, mkexpr( t2
), mkexpr( t3
) ) );
726 static inline IRExpr
* mkOr3_V128( IRTemp t0
, IRTemp t1
, IRTemp t2
)
728 return binop( Iop_OrV128
,
730 binop( Iop_OrV128
, mkexpr( t1
), mkexpr( t2
) ) );
733 static inline IRExpr
* mkOr4_V128( IRTemp t0
, IRTemp t1
, IRTemp t2
,
736 return binop( Iop_OrV128
,
737 binop( Iop_OrV128
, mkexpr( t0
), mkexpr( t1
) ),
738 binop( Iop_OrV128
, mkexpr( t2
), mkexpr( t3
) ) );
741 static inline IRExpr
* mkOr4_V128_expr( IRExpr
* t0
, IRExpr
* t1
, IRExpr
* t2
,
744 /* arguments are already expressions */
745 return binop( Iop_OrV128
,
746 binop( Iop_OrV128
, ( t0
), ( t1
) ),
747 binop( Iop_OrV128
, ( t2
), ( t3
) ) );
750 static IRExpr
* mkNOT1 ( IRExpr
* arg1
)
752 vassert(typeOfIRExpr(irsb
->tyenv
, arg1
) == Ity_I1
);
753 return unop(Iop_32to1
, unop(Iop_Not32
, unop(Iop_1Uto32
, arg1
) ) );
756 /* expand V128_8Ux16 to 2x V128_16Ux8's */
757 static void expand8Ux16( IRExpr
* vIn
,
758 /*OUTs*/ IRTemp
* vEvn
, IRTemp
* vOdd
)
760 IRTemp ones8x16
= newTemp(Ity_V128
);
762 vassert(typeOfIRExpr(irsb
->tyenv
, vIn
) == Ity_V128
);
763 vassert(vEvn
&& *vEvn
== IRTemp_INVALID
);
764 vassert(vOdd
&& *vOdd
== IRTemp_INVALID
);
765 *vEvn
= newTemp(Ity_V128
);
766 *vOdd
= newTemp(Ity_V128
);
768 assign( ones8x16
, unop(Iop_Dup8x16
, mkU8(0x1)) );
769 assign( *vOdd
, binop(Iop_MullEven8Ux16
, mkexpr(ones8x16
), vIn
) );
770 assign( *vEvn
, binop(Iop_MullEven8Ux16
, mkexpr(ones8x16
),
771 binop(Iop_ShrV128
, vIn
, mkU8(8))) );
774 /* expand V128_8Sx16 to 2x V128_16Sx8's */
775 static void expand8Sx16( IRExpr
* vIn
,
776 /*OUTs*/ IRTemp
* vEvn
, IRTemp
* vOdd
)
778 IRTemp ones8x16
= newTemp(Ity_V128
);
780 vassert(typeOfIRExpr(irsb
->tyenv
, vIn
) == Ity_V128
);
781 vassert(vEvn
&& *vEvn
== IRTemp_INVALID
);
782 vassert(vOdd
&& *vOdd
== IRTemp_INVALID
);
783 *vEvn
= newTemp(Ity_V128
);
784 *vOdd
= newTemp(Ity_V128
);
786 assign( ones8x16
, unop(Iop_Dup8x16
, mkU8(0x1)) );
787 assign( *vOdd
, binop(Iop_MullEven8Sx16
, mkexpr(ones8x16
), vIn
) );
788 assign( *vEvn
, binop(Iop_MullEven8Sx16
, mkexpr(ones8x16
),
789 binop(Iop_ShrV128
, vIn
, mkU8(8))) );
792 /* expand V128_16Uto8 to 2x V128_32Ux4's */
793 static void expand16Ux8( IRExpr
* vIn
,
794 /*OUTs*/ IRTemp
* vEvn
, IRTemp
* vOdd
)
796 IRTemp ones16x8
= newTemp(Ity_V128
);
798 vassert(typeOfIRExpr(irsb
->tyenv
, vIn
) == Ity_V128
);
799 vassert(vEvn
&& *vEvn
== IRTemp_INVALID
);
800 vassert(vOdd
&& *vOdd
== IRTemp_INVALID
);
801 *vEvn
= newTemp(Ity_V128
);
802 *vOdd
= newTemp(Ity_V128
);
804 assign( ones16x8
, unop(Iop_Dup16x8
, mkU16(0x1)) );
805 assign( *vOdd
, binop(Iop_MullEven16Ux8
, mkexpr(ones16x8
), vIn
) );
806 assign( *vEvn
, binop(Iop_MullEven16Ux8
, mkexpr(ones16x8
),
807 binop(Iop_ShrV128
, vIn
, mkU8(16))) );
810 /* expand V128_16Sto8 to 2x V128_32Sx4's */
811 static void expand16Sx8( IRExpr
* vIn
,
812 /*OUTs*/ IRTemp
* vEvn
, IRTemp
* vOdd
)
814 IRTemp ones16x8
= newTemp(Ity_V128
);
816 vassert(typeOfIRExpr(irsb
->tyenv
, vIn
) == Ity_V128
);
817 vassert(vEvn
&& *vEvn
== IRTemp_INVALID
);
818 vassert(vOdd
&& *vOdd
== IRTemp_INVALID
);
819 *vEvn
= newTemp(Ity_V128
);
820 *vOdd
= newTemp(Ity_V128
);
822 assign( ones16x8
, unop(Iop_Dup16x8
, mkU16(0x1)) );
823 assign( *vOdd
, binop(Iop_MullEven16Sx8
, mkexpr(ones16x8
), vIn
) );
824 assign( *vEvn
, binop(Iop_MullEven16Sx8
, mkexpr(ones16x8
),
825 binop(Iop_ShrV128
, vIn
, mkU8(16))) );
828 /* break V128 to 4xF64's*/
829 static void breakV128to4xF64( IRExpr
* t128
,
831 IRTemp
* t3
, IRTemp
* t2
,
832 IRTemp
* t1
, IRTemp
* t0
)
834 IRTemp hi64
= newTemp(Ity_I64
);
835 IRTemp lo64
= newTemp(Ity_I64
);
837 vassert(typeOfIRExpr(irsb
->tyenv
, t128
) == Ity_V128
);
838 vassert(t0
&& *t0
== IRTemp_INVALID
);
839 vassert(t1
&& *t1
== IRTemp_INVALID
);
840 vassert(t2
&& *t2
== IRTemp_INVALID
);
841 vassert(t3
&& *t3
== IRTemp_INVALID
);
842 *t0
= newTemp(Ity_F64
);
843 *t1
= newTemp(Ity_F64
);
844 *t2
= newTemp(Ity_F64
);
845 *t3
= newTemp(Ity_F64
);
847 assign( hi64
, unop(Iop_V128HIto64
, t128
) );
848 assign( lo64
, unop(Iop_V128to64
, t128
) );
851 unop( Iop_ReinterpI32asF32
,
852 unop( Iop_64HIto32
, mkexpr( hi64
) ) ) ) );
855 unop( Iop_ReinterpI32asF32
, unop( Iop_64to32
, mkexpr( hi64
) ) ) ) );
858 unop( Iop_ReinterpI32asF32
,
859 unop( Iop_64HIto32
, mkexpr( lo64
) ) ) ) );
862 unop( Iop_ReinterpI32asF32
, unop( Iop_64to32
, mkexpr( lo64
) ) ) ) );
866 /* break V128 to 4xI32's, then sign-extend to I64's */
867 static void breakV128to4x64S( IRExpr
* t128
,
869 IRTemp
* t3
, IRTemp
* t2
,
870 IRTemp
* t1
, IRTemp
* t0
)
872 IRTemp hi64
= newTemp(Ity_I64
);
873 IRTemp lo64
= newTemp(Ity_I64
);
875 vassert(typeOfIRExpr(irsb
->tyenv
, t128
) == Ity_V128
);
876 vassert(t0
&& *t0
== IRTemp_INVALID
);
877 vassert(t1
&& *t1
== IRTemp_INVALID
);
878 vassert(t2
&& *t2
== IRTemp_INVALID
);
879 vassert(t3
&& *t3
== IRTemp_INVALID
);
880 *t0
= newTemp(Ity_I64
);
881 *t1
= newTemp(Ity_I64
);
882 *t2
= newTemp(Ity_I64
);
883 *t3
= newTemp(Ity_I64
);
885 assign( hi64
, unop(Iop_V128HIto64
, t128
) );
886 assign( lo64
, unop(Iop_V128to64
, t128
) );
887 assign( *t3
, unop(Iop_32Sto64
, unop(Iop_64HIto32
, mkexpr(hi64
))) );
888 assign( *t2
, unop(Iop_32Sto64
, unop(Iop_64to32
, mkexpr(hi64
))) );
889 assign( *t1
, unop(Iop_32Sto64
, unop(Iop_64HIto32
, mkexpr(lo64
))) );
890 assign( *t0
, unop(Iop_32Sto64
, unop(Iop_64to32
, mkexpr(lo64
))) );
893 /* break V128 to 4xI32's, then zero-extend to I64's */
894 static void breakV128to4x64U ( IRExpr
* t128
,
896 IRTemp
* t3
, IRTemp
* t2
,
897 IRTemp
* t1
, IRTemp
* t0
)
899 IRTemp hi64
= newTemp(Ity_I64
);
900 IRTemp lo64
= newTemp(Ity_I64
);
902 vassert(typeOfIRExpr(irsb
->tyenv
, t128
) == Ity_V128
);
903 vassert(t0
&& *t0
== IRTemp_INVALID
);
904 vassert(t1
&& *t1
== IRTemp_INVALID
);
905 vassert(t2
&& *t2
== IRTemp_INVALID
);
906 vassert(t3
&& *t3
== IRTemp_INVALID
);
907 *t0
= newTemp(Ity_I64
);
908 *t1
= newTemp(Ity_I64
);
909 *t2
= newTemp(Ity_I64
);
910 *t3
= newTemp(Ity_I64
);
912 assign( hi64
, unop(Iop_V128HIto64
, t128
) );
913 assign( lo64
, unop(Iop_V128to64
, t128
) );
914 assign( *t3
, unop(Iop_32Uto64
, unop(Iop_64HIto32
, mkexpr(hi64
))) );
915 assign( *t2
, unop(Iop_32Uto64
, unop(Iop_64to32
, mkexpr(hi64
))) );
916 assign( *t1
, unop(Iop_32Uto64
, unop(Iop_64HIto32
, mkexpr(lo64
))) );
917 assign( *t0
, unop(Iop_32Uto64
, unop(Iop_64to32
, mkexpr(lo64
))) );
920 static void breakV128to4x32( IRExpr
* t128
,
922 IRTemp
* t3
, IRTemp
* t2
,
923 IRTemp
* t1
, IRTemp
* t0
)
925 IRTemp hi64
= newTemp(Ity_I64
);
926 IRTemp lo64
= newTemp(Ity_I64
);
928 vassert(typeOfIRExpr(irsb
->tyenv
, t128
) == Ity_V128
);
929 vassert(t0
&& *t0
== IRTemp_INVALID
);
930 vassert(t1
&& *t1
== IRTemp_INVALID
);
931 vassert(t2
&& *t2
== IRTemp_INVALID
);
932 vassert(t3
&& *t3
== IRTemp_INVALID
);
933 *t0
= newTemp(Ity_I32
);
934 *t1
= newTemp(Ity_I32
);
935 *t2
= newTemp(Ity_I32
);
936 *t3
= newTemp(Ity_I32
);
938 assign( hi64
, unop(Iop_V128HIto64
, t128
) );
939 assign( lo64
, unop(Iop_V128to64
, t128
) );
940 assign( *t3
, unop(Iop_64HIto32
, mkexpr(hi64
)) );
941 assign( *t2
, unop(Iop_64to32
, mkexpr(hi64
)) );
942 assign( *t1
, unop(Iop_64HIto32
, mkexpr(lo64
)) );
943 assign( *t0
, unop(Iop_64to32
, mkexpr(lo64
)) );
946 static IRExpr
* mkV128from32( IRTemp t3
, IRTemp t2
,
947 IRTemp t1
, IRTemp t0
)
950 binop( Iop_64HLtoV128
,
951 binop(Iop_32HLto64
, mkexpr(t3
), mkexpr(t2
)),
952 binop(Iop_32HLto64
, mkexpr(t1
), mkexpr(t0
))
956 static IRExpr
* extract_field_from_vector( IRTemp vB
, IRExpr
* index
, UInt mask
)
958 /* vB is a vector, extract bits starting at index to size of mask */
959 return unop( Iop_V128to64
,
964 binop( Iop_Mul64
, index
,
966 binop( Iop_64HLtoV128
,
971 /* Signed saturating narrow 64S to 32 */
972 static IRExpr
* mkQNarrow64Sto32 ( IRExpr
* t64
)
974 IRTemp hi32
= newTemp(Ity_I32
);
975 IRTemp lo32
= newTemp(Ity_I32
);
977 vassert(typeOfIRExpr(irsb
->tyenv
, t64
) == Ity_I64
);
979 assign( hi32
, unop(Iop_64HIto32
, t64
));
980 assign( lo32
, unop(Iop_64to32
, t64
));
983 /* if (hi32 == (lo32 >>s 31)) */
984 binop(Iop_CmpEQ32
, mkexpr(hi32
),
985 binop( Iop_Sar32
, mkexpr(lo32
), mkU8(31))),
986 /* then: within signed-32 range: lo half good enough */
988 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
989 binop(Iop_Add32
, mkU32(0x7FFFFFFF),
990 binop(Iop_Shr32
, mkexpr(hi32
), mkU8(31))));
993 /* Unsigned saturating narrow 64S to 32 */
994 static IRExpr
* mkQNarrow64Uto32 ( IRExpr
* t64
)
996 IRTemp hi32
= newTemp(Ity_I32
);
997 IRTemp lo32
= newTemp(Ity_I32
);
999 vassert(typeOfIRExpr(irsb
->tyenv
, t64
) == Ity_I64
);
1001 assign( hi32
, unop(Iop_64HIto32
, t64
));
1002 assign( lo32
, unop(Iop_64to32
, t64
));
1005 /* if (top 32 bits of t64 are 0) */
1006 binop(Iop_CmpEQ32
, mkexpr(hi32
), mkU32(0)),
1007 /* then: within unsigned-32 range: lo half good enough */
1009 /* else: positive saturate -> 0xFFFFFFFF */
1013 /* Signed saturate narrow 64->32, combining to V128 */
1014 static IRExpr
* mkV128from4x64S ( IRExpr
* t3
, IRExpr
* t2
,
1015 IRExpr
* t1
, IRExpr
* t0
)
1017 vassert(typeOfIRExpr(irsb
->tyenv
, t3
) == Ity_I64
);
1018 vassert(typeOfIRExpr(irsb
->tyenv
, t2
) == Ity_I64
);
1019 vassert(typeOfIRExpr(irsb
->tyenv
, t1
) == Ity_I64
);
1020 vassert(typeOfIRExpr(irsb
->tyenv
, t0
) == Ity_I64
);
1021 return binop(Iop_64HLtoV128
,
1023 mkQNarrow64Sto32( t3
),
1024 mkQNarrow64Sto32( t2
)),
1026 mkQNarrow64Sto32( t1
),
1027 mkQNarrow64Sto32( t0
)));
1030 /* Unsigned saturate narrow 64->32, combining to V128 */
1031 static IRExpr
* mkV128from4x64U ( IRExpr
* t3
, IRExpr
* t2
,
1032 IRExpr
* t1
, IRExpr
* t0
)
1034 vassert(typeOfIRExpr(irsb
->tyenv
, t3
) == Ity_I64
);
1035 vassert(typeOfIRExpr(irsb
->tyenv
, t2
) == Ity_I64
);
1036 vassert(typeOfIRExpr(irsb
->tyenv
, t1
) == Ity_I64
);
1037 vassert(typeOfIRExpr(irsb
->tyenv
, t0
) == Ity_I64
);
1038 return binop(Iop_64HLtoV128
,
1040 mkQNarrow64Uto32( t3
),
1041 mkQNarrow64Uto32( t2
)),
1043 mkQNarrow64Uto32( t1
),
1044 mkQNarrow64Uto32( t0
)));
1047 /* Simulate irops Iop_MullOdd*, since we don't have them */
1048 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
1049 binop(Iop_MullEven8Ux16, \
1050 binop(Iop_ShrV128, expr_vA, mkU8(8)), \
1051 binop(Iop_ShrV128, expr_vB, mkU8(8)))
1053 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
1054 binop(Iop_MullEven8Sx16, \
1055 binop(Iop_ShrV128, expr_vA, mkU8(8)), \
1056 binop(Iop_ShrV128, expr_vB, mkU8(8)))
1058 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
1059 binop(Iop_MullEven16Ux8, \
1060 binop(Iop_ShrV128, expr_vA, mkU8(16)), \
1061 binop(Iop_ShrV128, expr_vB, mkU8(16)))
1063 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
1064 binop(Iop_MullEven32Ux4, \
1065 binop(Iop_ShrV128, expr_vA, mkU8(32)), \
1066 binop(Iop_ShrV128, expr_vB, mkU8(32)))
1068 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
1069 binop(Iop_MullEven16Sx8, \
1070 binop(Iop_ShrV128, expr_vA, mkU8(16)), \
1071 binop(Iop_ShrV128, expr_vB, mkU8(16)))
1073 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
1074 binop(Iop_MullEven32Sx4, \
1075 binop(Iop_ShrV128, expr_vA, mkU8(32)), \
1076 binop(Iop_ShrV128, expr_vB, mkU8(32)))
1079 static IRExpr
* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr
* src
)
1081 vassert(typeOfIRExpr(irsb
->tyenv
, src
) == Ity_I64
);
1082 return unop(Iop_32Sto64
, unop(Iop_64to32
, src
));
1085 static IRExpr
* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr
* src
)
1087 vassert(typeOfIRExpr(irsb
->tyenv
, src
) == Ity_I64
);
1088 return unop(Iop_32Uto64
, unop(Iop_64to32
, src
));
1091 static IROp
mkSzOp ( IRType ty
, IROp op8
)
1094 vassert(ty
== Ity_I8
|| ty
== Ity_I16
||
1095 ty
== Ity_I32
|| ty
== Ity_I64
);
1096 vassert(op8
== Iop_Add8
|| op8
== Iop_Sub8
|| op8
== Iop_Mul8
||
1097 op8
== Iop_Or8
|| op8
== Iop_And8
|| op8
== Iop_Xor8
||
1098 op8
== Iop_Shl8
|| op8
== Iop_Shr8
|| op8
== Iop_Sar8
||
1099 op8
== Iop_CmpEQ8
|| op8
== Iop_CmpNE8
||
1101 adj
= ty
==Ity_I8
? 0 : (ty
==Ity_I16
? 1 : (ty
==Ity_I32
? 2 : 3));
1105 /* Make sure we get valid 32 and 64bit addresses */
1106 static Addr64
mkSzAddr ( IRType ty
, Addr64 addr
)
1108 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1109 return ( ty
== Ity_I64
?
1111 (Addr64
)extend_s_32to64( toUInt(addr
) ) );
1114 /* sz, ULong -> IRExpr */
1115 static IRExpr
* mkSzImm ( IRType ty
, ULong imm64
)
1117 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1118 return ty
== Ity_I64
? mkU64(imm64
) : mkU32((UInt
)imm64
);
1121 /* sz, ULong -> IRConst */
1122 static IRConst
* mkSzConst ( IRType ty
, ULong imm64
)
1124 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1125 return ( ty
== Ity_I64
?
1126 IRConst_U64(imm64
) :
1127 IRConst_U32((UInt
)imm64
) );
1130 /* Sign extend imm16 -> IRExpr* */
1131 static IRExpr
* mkSzExtendS16 ( IRType ty
, UInt imm16
)
1133 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1134 return ( ty
== Ity_I64
?
1135 mkU64(extend_s_16to64(imm16
)) :
1136 mkU32(extend_s_16to32(imm16
)) );
1139 /* Sign extend imm32 -> IRExpr* */
1140 static IRExpr
* mkSzExtendS32 ( IRType ty
, UInt imm32
)
1142 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1143 return ( ty
== Ity_I64
?
1144 mkU64(extend_s_32to64(imm32
)) :
1148 /* IR narrows I32/I64 -> I8/I16/I32 */
1149 static IRExpr
* mkNarrowTo8 ( IRType ty
, IRExpr
* src
)
1151 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1152 return ty
== Ity_I64
? unop(Iop_64to8
, src
) : unop(Iop_32to8
, src
);
1155 static IRExpr
* mkNarrowTo16 ( IRType ty
, IRExpr
* src
)
1157 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1158 return ty
== Ity_I64
? unop(Iop_64to16
, src
) : unop(Iop_32to16
, src
);
1161 static IRExpr
* mkNarrowTo32 ( IRType ty
, IRExpr
* src
)
1163 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1164 return ty
== Ity_I64
? unop(Iop_64to32
, src
) : src
;
1167 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
1168 static IRExpr
* mkWidenFrom8 ( IRType ty
, IRExpr
* src
, Bool sined
)
1171 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1172 if (sined
) op
= (ty
==Ity_I32
) ? Iop_8Sto32
: Iop_8Sto64
;
1173 else op
= (ty
==Ity_I32
) ? Iop_8Uto32
: Iop_8Uto64
;
1174 return unop(op
, src
);
1177 static IRExpr
* mkWidenFrom16 ( IRType ty
, IRExpr
* src
, Bool sined
)
1180 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1181 if (sined
) op
= (ty
==Ity_I32
) ? Iop_16Sto32
: Iop_16Sto64
;
1182 else op
= (ty
==Ity_I32
) ? Iop_16Uto32
: Iop_16Uto64
;
1183 return unop(op
, src
);
1186 static IRExpr
* mkWidenFrom32 ( IRType ty
, IRExpr
* src
, Bool sined
)
1188 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1191 return (sined
) ? unop(Iop_32Sto64
, src
) : unop(Iop_32Uto64
, src
);
1195 static Int
integerGuestRegOffset ( UInt archreg
)
1197 vassert(archreg
< 32);
1199 // jrs: probably not necessary; only matters if we reference sub-parts
1200 // of the ppc registers, but that isn't the case
1201 // later: this might affect Altivec though?
1204 case 0: return offsetofPPCGuestState(guest_GPR0
);
1205 case 1: return offsetofPPCGuestState(guest_GPR1
);
1206 case 2: return offsetofPPCGuestState(guest_GPR2
);
1207 case 3: return offsetofPPCGuestState(guest_GPR3
);
1208 case 4: return offsetofPPCGuestState(guest_GPR4
);
1209 case 5: return offsetofPPCGuestState(guest_GPR5
);
1210 case 6: return offsetofPPCGuestState(guest_GPR6
);
1211 case 7: return offsetofPPCGuestState(guest_GPR7
);
1212 case 8: return offsetofPPCGuestState(guest_GPR8
);
1213 case 9: return offsetofPPCGuestState(guest_GPR9
);
1214 case 10: return offsetofPPCGuestState(guest_GPR10
);
1215 case 11: return offsetofPPCGuestState(guest_GPR11
);
1216 case 12: return offsetofPPCGuestState(guest_GPR12
);
1217 case 13: return offsetofPPCGuestState(guest_GPR13
);
1218 case 14: return offsetofPPCGuestState(guest_GPR14
);
1219 case 15: return offsetofPPCGuestState(guest_GPR15
);
1220 case 16: return offsetofPPCGuestState(guest_GPR16
);
1221 case 17: return offsetofPPCGuestState(guest_GPR17
);
1222 case 18: return offsetofPPCGuestState(guest_GPR18
);
1223 case 19: return offsetofPPCGuestState(guest_GPR19
);
1224 case 20: return offsetofPPCGuestState(guest_GPR20
);
1225 case 21: return offsetofPPCGuestState(guest_GPR21
);
1226 case 22: return offsetofPPCGuestState(guest_GPR22
);
1227 case 23: return offsetofPPCGuestState(guest_GPR23
);
1228 case 24: return offsetofPPCGuestState(guest_GPR24
);
1229 case 25: return offsetofPPCGuestState(guest_GPR25
);
1230 case 26: return offsetofPPCGuestState(guest_GPR26
);
1231 case 27: return offsetofPPCGuestState(guest_GPR27
);
1232 case 28: return offsetofPPCGuestState(guest_GPR28
);
1233 case 29: return offsetofPPCGuestState(guest_GPR29
);
1234 case 30: return offsetofPPCGuestState(guest_GPR30
);
1235 case 31: return offsetofPPCGuestState(guest_GPR31
);
1238 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1241 static IRExpr
* getIReg ( UInt archreg
)
1243 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1244 vassert(archreg
< 32);
1245 return IRExpr_Get( integerGuestRegOffset(archreg
), ty
);
1248 /* Ditto, but write to a reg instead. */
1249 static void putIReg ( UInt archreg
, IRExpr
* e
)
1251 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1252 vassert(archreg
< 32);
1253 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == ty
);
1254 stmt( IRStmt_Put(integerGuestRegOffset(archreg
), e
) );
1258 /* Floating point egisters are mapped to VSX registers[0..31]. */
1259 static Int
floatGuestRegOffset ( UInt archreg
)
1261 vassert(archreg
< 32);
1263 if (host_endness
== VexEndnessLE
) {
1265 case 0: return offsetofPPCGuestState(guest_VSR0
) + 8;
1266 case 1: return offsetofPPCGuestState(guest_VSR1
) + 8;
1267 case 2: return offsetofPPCGuestState(guest_VSR2
) + 8;
1268 case 3: return offsetofPPCGuestState(guest_VSR3
) + 8;
1269 case 4: return offsetofPPCGuestState(guest_VSR4
) + 8;
1270 case 5: return offsetofPPCGuestState(guest_VSR5
) + 8;
1271 case 6: return offsetofPPCGuestState(guest_VSR6
) + 8;
1272 case 7: return offsetofPPCGuestState(guest_VSR7
) + 8;
1273 case 8: return offsetofPPCGuestState(guest_VSR8
) + 8;
1274 case 9: return offsetofPPCGuestState(guest_VSR9
) + 8;
1275 case 10: return offsetofPPCGuestState(guest_VSR10
) + 8;
1276 case 11: return offsetofPPCGuestState(guest_VSR11
) + 8;
1277 case 12: return offsetofPPCGuestState(guest_VSR12
) + 8;
1278 case 13: return offsetofPPCGuestState(guest_VSR13
) + 8;
1279 case 14: return offsetofPPCGuestState(guest_VSR14
) + 8;
1280 case 15: return offsetofPPCGuestState(guest_VSR15
) + 8;
1281 case 16: return offsetofPPCGuestState(guest_VSR16
) + 8;
1282 case 17: return offsetofPPCGuestState(guest_VSR17
) + 8;
1283 case 18: return offsetofPPCGuestState(guest_VSR18
) + 8;
1284 case 19: return offsetofPPCGuestState(guest_VSR19
) + 8;
1285 case 20: return offsetofPPCGuestState(guest_VSR20
) + 8;
1286 case 21: return offsetofPPCGuestState(guest_VSR21
) + 8;
1287 case 22: return offsetofPPCGuestState(guest_VSR22
) + 8;
1288 case 23: return offsetofPPCGuestState(guest_VSR23
) + 8;
1289 case 24: return offsetofPPCGuestState(guest_VSR24
) + 8;
1290 case 25: return offsetofPPCGuestState(guest_VSR25
) + 8;
1291 case 26: return offsetofPPCGuestState(guest_VSR26
) + 8;
1292 case 27: return offsetofPPCGuestState(guest_VSR27
) + 8;
1293 case 28: return offsetofPPCGuestState(guest_VSR28
) + 8;
1294 case 29: return offsetofPPCGuestState(guest_VSR29
) + 8;
1295 case 30: return offsetofPPCGuestState(guest_VSR30
) + 8;
1296 case 31: return offsetofPPCGuestState(guest_VSR31
) + 8;
1301 case 0: return offsetofPPCGuestState(guest_VSR0
);
1302 case 1: return offsetofPPCGuestState(guest_VSR1
);
1303 case 2: return offsetofPPCGuestState(guest_VSR2
);
1304 case 3: return offsetofPPCGuestState(guest_VSR3
);
1305 case 4: return offsetofPPCGuestState(guest_VSR4
);
1306 case 5: return offsetofPPCGuestState(guest_VSR5
);
1307 case 6: return offsetofPPCGuestState(guest_VSR6
);
1308 case 7: return offsetofPPCGuestState(guest_VSR7
);
1309 case 8: return offsetofPPCGuestState(guest_VSR8
);
1310 case 9: return offsetofPPCGuestState(guest_VSR9
);
1311 case 10: return offsetofPPCGuestState(guest_VSR10
);
1312 case 11: return offsetofPPCGuestState(guest_VSR11
);
1313 case 12: return offsetofPPCGuestState(guest_VSR12
);
1314 case 13: return offsetofPPCGuestState(guest_VSR13
);
1315 case 14: return offsetofPPCGuestState(guest_VSR14
);
1316 case 15: return offsetofPPCGuestState(guest_VSR15
);
1317 case 16: return offsetofPPCGuestState(guest_VSR16
);
1318 case 17: return offsetofPPCGuestState(guest_VSR17
);
1319 case 18: return offsetofPPCGuestState(guest_VSR18
);
1320 case 19: return offsetofPPCGuestState(guest_VSR19
);
1321 case 20: return offsetofPPCGuestState(guest_VSR20
);
1322 case 21: return offsetofPPCGuestState(guest_VSR21
);
1323 case 22: return offsetofPPCGuestState(guest_VSR22
);
1324 case 23: return offsetofPPCGuestState(guest_VSR23
);
1325 case 24: return offsetofPPCGuestState(guest_VSR24
);
1326 case 25: return offsetofPPCGuestState(guest_VSR25
);
1327 case 26: return offsetofPPCGuestState(guest_VSR26
);
1328 case 27: return offsetofPPCGuestState(guest_VSR27
);
1329 case 28: return offsetofPPCGuestState(guest_VSR28
);
1330 case 29: return offsetofPPCGuestState(guest_VSR29
);
1331 case 30: return offsetofPPCGuestState(guest_VSR30
);
1332 case 31: return offsetofPPCGuestState(guest_VSR31
);
1336 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1339 static IRExpr
* getFReg ( UInt archreg
)
1341 vassert(archreg
< 32);
1342 return IRExpr_Get( floatGuestRegOffset(archreg
), Ity_F64
);
1345 /* Ditto, but write to a reg instead. */
1346 static void putFReg ( UInt archreg
, IRExpr
* e
)
1348 vassert(archreg
< 32);
1349 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_F64
);
1350 stmt( IRStmt_Put(floatGuestRegOffset(archreg
), e
) );
1353 /* get Decimal float value. Note, they share floating point register file. */
1354 static IRExpr
* getDReg(UInt archreg
) {
1356 vassert( archreg
< 32 );
1357 e
= IRExpr_Get( floatGuestRegOffset( archreg
), Ity_D64
);
1360 static IRExpr
* getDReg32(UInt archreg
) {
1362 vassert( archreg
< 32 );
1363 e
= IRExpr_Get( floatGuestRegOffset( archreg
), Ity_D32
);
1367 /* Read a floating point register pair and combine their contents into a
1369 static IRExpr
*getDReg_pair(UInt archreg
) {
1370 IRExpr
*high
= getDReg( archreg
);
1371 IRExpr
*low
= getDReg( archreg
+ 1 );
1373 return binop( Iop_D64HLtoD128
, high
, low
);
1376 /* Ditto, but write to a reg instead. */
1377 static void putDReg32(UInt archreg
, IRExpr
* e
) {
1378 vassert( archreg
< 32 );
1379 vassert( typeOfIRExpr(irsb
->tyenv
, e
) == Ity_D32
);
1380 stmt( IRStmt_Put( floatGuestRegOffset( archreg
), e
) );
1383 static void putDReg(UInt archreg
, IRExpr
* e
) {
1384 vassert( archreg
< 32 );
1385 vassert( typeOfIRExpr(irsb
->tyenv
, e
) == Ity_D64
);
1386 stmt( IRStmt_Put( floatGuestRegOffset( archreg
), e
) );
1389 /* Write a 128-bit floating point value into a register pair. */
1390 static void putDReg_pair(UInt archreg
, IRExpr
*e
) {
1391 IRTemp low
= newTemp( Ity_D64
);
1392 IRTemp high
= newTemp( Ity_D64
);
1394 vassert( archreg
< 32 );
1395 vassert( typeOfIRExpr(irsb
->tyenv
, e
) == Ity_D128
);
1397 assign( low
, unop( Iop_D128LOtoD64
, e
) );
1398 assign( high
, unop( Iop_D128HItoD64
, e
) );
1400 stmt( IRStmt_Put( floatGuestRegOffset( archreg
), mkexpr( high
) ) );
1401 stmt( IRStmt_Put( floatGuestRegOffset( archreg
+ 1 ), mkexpr( low
) ) );
1404 static Int
vsxGuestRegOffset ( UInt archreg
)
1406 vassert(archreg
< 64);
1408 case 0: return offsetofPPCGuestState(guest_VSR0
);
1409 case 1: return offsetofPPCGuestState(guest_VSR1
);
1410 case 2: return offsetofPPCGuestState(guest_VSR2
);
1411 case 3: return offsetofPPCGuestState(guest_VSR3
);
1412 case 4: return offsetofPPCGuestState(guest_VSR4
);
1413 case 5: return offsetofPPCGuestState(guest_VSR5
);
1414 case 6: return offsetofPPCGuestState(guest_VSR6
);
1415 case 7: return offsetofPPCGuestState(guest_VSR7
);
1416 case 8: return offsetofPPCGuestState(guest_VSR8
);
1417 case 9: return offsetofPPCGuestState(guest_VSR9
);
1418 case 10: return offsetofPPCGuestState(guest_VSR10
);
1419 case 11: return offsetofPPCGuestState(guest_VSR11
);
1420 case 12: return offsetofPPCGuestState(guest_VSR12
);
1421 case 13: return offsetofPPCGuestState(guest_VSR13
);
1422 case 14: return offsetofPPCGuestState(guest_VSR14
);
1423 case 15: return offsetofPPCGuestState(guest_VSR15
);
1424 case 16: return offsetofPPCGuestState(guest_VSR16
);
1425 case 17: return offsetofPPCGuestState(guest_VSR17
);
1426 case 18: return offsetofPPCGuestState(guest_VSR18
);
1427 case 19: return offsetofPPCGuestState(guest_VSR19
);
1428 case 20: return offsetofPPCGuestState(guest_VSR20
);
1429 case 21: return offsetofPPCGuestState(guest_VSR21
);
1430 case 22: return offsetofPPCGuestState(guest_VSR22
);
1431 case 23: return offsetofPPCGuestState(guest_VSR23
);
1432 case 24: return offsetofPPCGuestState(guest_VSR24
);
1433 case 25: return offsetofPPCGuestState(guest_VSR25
);
1434 case 26: return offsetofPPCGuestState(guest_VSR26
);
1435 case 27: return offsetofPPCGuestState(guest_VSR27
);
1436 case 28: return offsetofPPCGuestState(guest_VSR28
);
1437 case 29: return offsetofPPCGuestState(guest_VSR29
);
1438 case 30: return offsetofPPCGuestState(guest_VSR30
);
1439 case 31: return offsetofPPCGuestState(guest_VSR31
);
1440 case 32: return offsetofPPCGuestState(guest_VSR32
);
1441 case 33: return offsetofPPCGuestState(guest_VSR33
);
1442 case 34: return offsetofPPCGuestState(guest_VSR34
);
1443 case 35: return offsetofPPCGuestState(guest_VSR35
);
1444 case 36: return offsetofPPCGuestState(guest_VSR36
);
1445 case 37: return offsetofPPCGuestState(guest_VSR37
);
1446 case 38: return offsetofPPCGuestState(guest_VSR38
);
1447 case 39: return offsetofPPCGuestState(guest_VSR39
);
1448 case 40: return offsetofPPCGuestState(guest_VSR40
);
1449 case 41: return offsetofPPCGuestState(guest_VSR41
);
1450 case 42: return offsetofPPCGuestState(guest_VSR42
);
1451 case 43: return offsetofPPCGuestState(guest_VSR43
);
1452 case 44: return offsetofPPCGuestState(guest_VSR44
);
1453 case 45: return offsetofPPCGuestState(guest_VSR45
);
1454 case 46: return offsetofPPCGuestState(guest_VSR46
);
1455 case 47: return offsetofPPCGuestState(guest_VSR47
);
1456 case 48: return offsetofPPCGuestState(guest_VSR48
);
1457 case 49: return offsetofPPCGuestState(guest_VSR49
);
1458 case 50: return offsetofPPCGuestState(guest_VSR50
);
1459 case 51: return offsetofPPCGuestState(guest_VSR51
);
1460 case 52: return offsetofPPCGuestState(guest_VSR52
);
1461 case 53: return offsetofPPCGuestState(guest_VSR53
);
1462 case 54: return offsetofPPCGuestState(guest_VSR54
);
1463 case 55: return offsetofPPCGuestState(guest_VSR55
);
1464 case 56: return offsetofPPCGuestState(guest_VSR56
);
1465 case 57: return offsetofPPCGuestState(guest_VSR57
);
1466 case 58: return offsetofPPCGuestState(guest_VSR58
);
1467 case 59: return offsetofPPCGuestState(guest_VSR59
);
1468 case 60: return offsetofPPCGuestState(guest_VSR60
);
1469 case 61: return offsetofPPCGuestState(guest_VSR61
);
1470 case 62: return offsetofPPCGuestState(guest_VSR62
);
1471 case 63: return offsetofPPCGuestState(guest_VSR63
);
1474 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1477 /* Vector registers are mapped to VSX registers[32..63]. */
1478 static Int
vectorGuestRegOffset ( UInt archreg
)
1480 vassert(archreg
< 32);
1483 case 0: return offsetofPPCGuestState(guest_VSR32
);
1484 case 1: return offsetofPPCGuestState(guest_VSR33
);
1485 case 2: return offsetofPPCGuestState(guest_VSR34
);
1486 case 3: return offsetofPPCGuestState(guest_VSR35
);
1487 case 4: return offsetofPPCGuestState(guest_VSR36
);
1488 case 5: return offsetofPPCGuestState(guest_VSR37
);
1489 case 6: return offsetofPPCGuestState(guest_VSR38
);
1490 case 7: return offsetofPPCGuestState(guest_VSR39
);
1491 case 8: return offsetofPPCGuestState(guest_VSR40
);
1492 case 9: return offsetofPPCGuestState(guest_VSR41
);
1493 case 10: return offsetofPPCGuestState(guest_VSR42
);
1494 case 11: return offsetofPPCGuestState(guest_VSR43
);
1495 case 12: return offsetofPPCGuestState(guest_VSR44
);
1496 case 13: return offsetofPPCGuestState(guest_VSR45
);
1497 case 14: return offsetofPPCGuestState(guest_VSR46
);
1498 case 15: return offsetofPPCGuestState(guest_VSR47
);
1499 case 16: return offsetofPPCGuestState(guest_VSR48
);
1500 case 17: return offsetofPPCGuestState(guest_VSR49
);
1501 case 18: return offsetofPPCGuestState(guest_VSR50
);
1502 case 19: return offsetofPPCGuestState(guest_VSR51
);
1503 case 20: return offsetofPPCGuestState(guest_VSR52
);
1504 case 21: return offsetofPPCGuestState(guest_VSR53
);
1505 case 22: return offsetofPPCGuestState(guest_VSR54
);
1506 case 23: return offsetofPPCGuestState(guest_VSR55
);
1507 case 24: return offsetofPPCGuestState(guest_VSR56
);
1508 case 25: return offsetofPPCGuestState(guest_VSR57
);
1509 case 26: return offsetofPPCGuestState(guest_VSR58
);
1510 case 27: return offsetofPPCGuestState(guest_VSR59
);
1511 case 28: return offsetofPPCGuestState(guest_VSR60
);
1512 case 29: return offsetofPPCGuestState(guest_VSR61
);
1513 case 30: return offsetofPPCGuestState(guest_VSR62
);
1514 case 31: return offsetofPPCGuestState(guest_VSR63
);
1517 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1520 static IRExpr
* getVReg ( UInt archreg
)
1522 vassert(archreg
< 32);
1523 return IRExpr_Get( vectorGuestRegOffset(archreg
), Ity_V128
);
1526 /* Get contents of 128-bit reg guest register */
1527 static IRExpr
* getF128Reg ( UInt archreg
)
1529 vassert(archreg
< 64);
1530 return IRExpr_Get( vectorGuestRegOffset(archreg
), Ity_F128
);
1533 /* Ditto, but write to a reg instead. */
1534 static void putF128Reg ( UInt archreg
, IRExpr
* e
)
1536 vassert(archreg
< 64);
1537 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_F128
);
1538 stmt( IRStmt_Put(vectorGuestRegOffset(archreg
), e
) );
1541 /* Ditto, but write to a reg instead. */
1542 static void putVReg ( UInt archreg
, IRExpr
* e
)
1544 vassert(archreg
< 32);
1545 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_V128
);
1546 stmt( IRStmt_Put(vectorGuestRegOffset(archreg
), e
) );
1549 /* Get contents of VSX guest register */
1550 static IRExpr
* getVSReg ( UInt archreg
)
1552 vassert(archreg
< 64);
1553 return IRExpr_Get( vsxGuestRegOffset(archreg
), Ity_V128
);
1556 /* Ditto, but write to a VSX reg instead. */
1557 static void putVSReg ( UInt archreg
, IRExpr
* e
)
1559 vassert(archreg
< 64);
1560 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_V128
);
1561 stmt( IRStmt_Put(vsxGuestRegOffset(archreg
), e
) );
1565 static Int
guestCR321offset ( UInt cr
)
1568 case 0: return offsetofPPCGuestState(guest_CR0_321
);
1569 case 1: return offsetofPPCGuestState(guest_CR1_321
);
1570 case 2: return offsetofPPCGuestState(guest_CR2_321
);
1571 case 3: return offsetofPPCGuestState(guest_CR3_321
);
1572 case 4: return offsetofPPCGuestState(guest_CR4_321
);
1573 case 5: return offsetofPPCGuestState(guest_CR5_321
);
1574 case 6: return offsetofPPCGuestState(guest_CR6_321
);
1575 case 7: return offsetofPPCGuestState(guest_CR7_321
);
1576 default: vpanic("guestCR321offset(ppc)");
1580 static Int
guestCR0offset ( UInt cr
)
1583 case 0: return offsetofPPCGuestState(guest_CR0_0
);
1584 case 1: return offsetofPPCGuestState(guest_CR1_0
);
1585 case 2: return offsetofPPCGuestState(guest_CR2_0
);
1586 case 3: return offsetofPPCGuestState(guest_CR3_0
);
1587 case 4: return offsetofPPCGuestState(guest_CR4_0
);
1588 case 5: return offsetofPPCGuestState(guest_CR5_0
);
1589 case 6: return offsetofPPCGuestState(guest_CR6_0
);
1590 case 7: return offsetofPPCGuestState(guest_CR7_0
);
1591 default: vpanic("guestCR3offset(ppc)");
1603 } _popcount_data_type
;
1605 /* Generate an IR sequence to do a popcount operation on the supplied
1606 IRTemp, and return a new IRTemp holding the result. 'ty' may be
1607 Ity_I32 or Ity_I64 only. */
1608 static IRTemp
gen_POPCOUNT ( IRType ty
, IRTemp src
,
1609 _popcount_data_type data_type
)
1611 /* Do count across 2^data_type bits,
1613 half word: data_type = 4
1615 double word: data_type = 6 (not supported for 32-bit type)
1618 _popcount_data_type idx
, i
;
1620 IRTemp old
= IRTemp_INVALID
;
1621 IRTemp nyu
= IRTemp_INVALID
;
1623 vassert(ty
== Ity_I64
|| ty
== Ity_I32
);
1625 // Use a single IROp in cases where we can.
1627 if (ty
== Ity_I64
&& data_type
== DWORD
) {
1628 IRTemp res
= newTemp(Ity_I64
);
1629 assign(res
, unop(Iop_PopCount64
, mkexpr(src
)));
1633 if (ty
== Ity_I32
&& data_type
== WORD
) {
1634 IRTemp res
= newTemp(Ity_I32
);
1635 assign(res
, unop(Iop_PopCount32
, mkexpr(src
)));
1639 // For the rest, we have to do it the slow way.
1641 if (ty
== Ity_I32
) {
1643 for (idx
= 0; idx
< WORD
; idx
++) {
1644 mask
[idx
] = newTemp(ty
);
1645 shift
[idx
] = 1 << idx
;
1647 assign(mask
[0], mkU32(0x55555555));
1648 assign(mask
[1], mkU32(0x33333333));
1649 assign(mask
[2], mkU32(0x0F0F0F0F));
1650 assign(mask
[3], mkU32(0x00FF00FF));
1651 assign(mask
[4], mkU32(0x0000FFFF));
1653 for (i
= 0; i
< data_type
; i
++) {
1661 binop(Iop_Shr32
, mkexpr(old
), mkU8(shift
[i
])),
1668 // else, ty == Ity_I64
1671 for (i
= 0; i
< DWORD
; i
++) {
1672 mask
[i
] = newTemp( Ity_I64
);
1675 assign( mask
[0], mkU64( 0x5555555555555555ULL
) );
1676 assign( mask
[1], mkU64( 0x3333333333333333ULL
) );
1677 assign( mask
[2], mkU64( 0x0F0F0F0F0F0F0F0FULL
) );
1678 assign( mask
[3], mkU64( 0x00FF00FF00FF00FFULL
) );
1679 assign( mask
[4], mkU64( 0x0000FFFF0000FFFFULL
) );
1680 assign( mask
[5], mkU64( 0x00000000FFFFFFFFULL
) );
1682 for (i
= 0; i
< data_type
; i
++) {
1683 nyu
= newTemp( Ity_I64
);
1686 binop( Iop_And64
, mkexpr( old
), mkexpr( mask
[i
] ) ),
1688 binop( Iop_Shr64
, mkexpr( old
), mkU8( shift
[i
] ) ),
1689 mkexpr( mask
[i
] ) ) ) );
1695 /* Special purpose population count function for
1696 * vpopcntd in 32-bit mode.
1698 static IRTemp
gen_vpopcntd_mode32 ( IRTemp src1
, IRTemp src2
)
1700 IRTemp retval
= newTemp(Ity_I64
);
1707 unop(Iop_PopCount32
, mkexpr(src1
)),
1708 unop(Iop_PopCount32
, mkexpr(src2
)))));
1713 // ROTL(src32/64, rot_amt5/6)
1714 static IRExpr
* /* :: Ity_I32/64 */ ROTL ( IRExpr
* src
,
1718 vassert(typeOfIRExpr(irsb
->tyenv
,rot_amt
) == Ity_I8
);
1720 if (typeOfIRExpr(irsb
->tyenv
,src
) == Ity_I64
) {
1721 // rot = (src << rot_amt) | (src >> (64-rot_amt))
1722 mask
= binop(Iop_And8
, rot_amt
, mkU8(63));
1723 rot
= binop(Iop_Or64
,
1724 binop(Iop_Shl64
, src
, mask
),
1725 binop(Iop_Shr64
, src
, binop(Iop_Sub8
, mkU8(64), mask
)));
1727 // rot = (src << rot_amt) | (src >> (32-rot_amt))
1728 mask
= binop(Iop_And8
, rot_amt
, mkU8(31));
1729 rot
= binop(Iop_Or32
,
1730 binop(Iop_Shl32
, src
, mask
),
1731 binop(Iop_Shr32
, src
, binop(Iop_Sub8
, mkU8(32), mask
)));
1733 /* Note: the ITE not merely an optimisation; it's needed
1734 because otherwise the Shr is a shift by the word size when
1735 mask denotes zero. For rotates by immediates, a lot of
1736 this junk gets folded out. */
1737 return IRExpr_ITE( binop(Iop_CmpNE8
, mask
, mkU8(0)),
1738 /* non-zero rotate */ rot
,
1739 /* zero rotate */ src
);
1742 /* Standard effective address calc: (rA + rB) */
1743 static IRExpr
* ea_rA_idxd ( UInt rA
, UInt rB
)
1745 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1748 return binop(mkSzOp(ty
, Iop_Add8
), getIReg(rA
), getIReg(rB
));
1751 /* Standard effective address calc: (rA + simm) */
1752 static IRExpr
* ea_rA_simm ( UInt rA
, UInt simm16
)
1754 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1756 return binop(mkSzOp(ty
, Iop_Add8
), getIReg(rA
),
1757 mkSzExtendS16(ty
, simm16
));
1760 /* Standard effective address calc: (rA|0) */
1761 static IRExpr
* ea_rAor0 ( UInt rA
)
1763 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1766 return mkSzImm(ty
, 0);
1772 /* Standard effective address calc: (rA|0) + rB */
1773 static IRExpr
* ea_rAor0_idxd ( UInt rA
, UInt rB
)
1777 return (rA
== 0) ? getIReg(rB
) : ea_rA_idxd( rA
, rB
);
1780 /* Standard effective address calc: (rA|0) + simm16 */
1781 static IRExpr
* ea_rAor0_simm ( UInt rA
, UInt simm16
)
1783 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1786 return mkSzExtendS16(ty
, simm16
);
1788 return ea_rA_simm( rA
, simm16
);
1793 /* Align effective address */
1794 static IRExpr
* addr_align( IRExpr
* addr
, UChar align
)
1796 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1799 case 1: return addr
; // byte aligned
1800 case 2: mask
= ~0ULL << 1; break; // half-word aligned
1801 case 4: mask
= ~0ULL << 2; break; // word aligned
1802 case 16: mask
= ~0ULL << 4; break; // quad-word aligned
1804 vex_printf("addr_align: align = %u\n", align
);
1805 vpanic("addr_align(ppc)");
1808 vassert(typeOfIRExpr(irsb
->tyenv
,addr
) == ty
);
1809 return binop( mkSzOp(ty
, Iop_And8
), addr
, mkSzImm(ty
, mask
) );
1813 /* Exit the trace if ADDR (intended to be a guest memory address) is
1814 not ALIGN-aligned, generating a request for a SIGBUS followed by a
1815 restart of the current insn. */
1816 static void gen_SIGBUS_if_misaligned ( IRTemp addr
, UChar align
)
1818 vassert(align
== 2 || align
== 4 || align
== 8 || align
== 16);
1820 vassert(typeOfIRTemp(irsb
->tyenv
, addr
) == Ity_I64
);
1824 binop(Iop_And64
, mkexpr(addr
), mkU64(align
-1)),
1827 IRConst_U64( guest_CIA_curr_instr
), OFFB_CIA
1831 vassert(typeOfIRTemp(irsb
->tyenv
, addr
) == Ity_I32
);
1835 binop(Iop_And32
, mkexpr(addr
), mkU32(align
-1)),
1838 IRConst_U32( guest_CIA_curr_instr
), OFFB_CIA
1845 /* Generate AbiHints which mark points at which the ELF or PowerOpen
1846 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1847 N) becomes undefined. That is at function calls and returns. ELF
1848 ppc32 doesn't have this "feature" (how fortunate for it). nia is
1849 the address of the next instruction to be executed.
1851 static void make_redzone_AbiHint ( const VexAbiInfo
* vbi
,
1852 IRTemp nia
, const HChar
* who
)
1854 Int szB
= vbi
->guest_stack_redzone_size
;
1855 if (0) vex_printf("AbiHint: %s\n", who
);
1859 vassert(typeOfIRTemp(irsb
->tyenv
, nia
) == Ity_I64
);
1860 stmt( IRStmt_AbiHint(
1861 binop(Iop_Sub64
, getIReg(1), mkU64(szB
)),
1866 vassert(typeOfIRTemp(irsb
->tyenv
, nia
) == Ity_I32
);
1867 stmt( IRStmt_AbiHint(
1868 binop(Iop_Sub32
, getIReg(1), mkU32(szB
)),
1877 /*------------------------------------------------------------*/
1878 /*--- Helpers for condition codes. ---*/
1879 /*------------------------------------------------------------*/
1881 /* Condition register layout.
1883 In the hardware, CR is laid out like this. The leftmost end is the
1884 most significant bit in the register; however the IBM documentation
1885 numbers the bits backwards for some reason.
1887 CR0 CR1 .......... CR6 CR7
1888 0 .. 3 ....................... 28 .. 31 (IBM bit numbering)
1889 31 28 3 0 (normal bit numbering)
1891 Each CR field is 4 bits: [<,>,==,SO]
1893 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1895 Indexing from BI to guest state:
1899 this references CR n:
1901 off==0 -> guest_CRn_321 >> 3
1902 off==1 -> guest_CRn_321 >> 2
1903 off==2 -> guest_CRn_321 >> 1
1904 off==3 -> guest_CRn_SO
1906 Bear in mind the only significant bit in guest_CRn_SO is bit 0
1907 (normal notation) and in guest_CRn_321 the significant bits are
1908 3, 2 and 1 (normal notation).
1911 static void putCR321 ( UInt cr
, IRExpr
* e
)
1914 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
1915 stmt( IRStmt_Put(guestCR321offset(cr
), e
) );
1918 static void putCR0 ( UInt cr
, IRExpr
* e
)
1921 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
1922 stmt( IRStmt_Put(guestCR0offset(cr
), e
) );
1925 static void putC ( IRExpr
* e
)
1927 /* The assumption is that the value of the Floating-Point Result
1928 * Class Descriptor bit (C) is passed in the lower four bits of a
1931 * Note, the C and FPCC bits which are fields in the FPSCR
1932 * register are stored in their own memory location of
1933 * memory. The FPCC bits are in the lower 4 bits. The C bit needs
1934 * to be shifted to bit 4 in the memory location that holds C and FPCC.
1935 * Note not all of the FPSCR register bits are supported. We are
1936 * only writing C bit.
1940 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I32
);
1942 /* Get the FPCC bit field */
1943 tmp
= binop( Iop_And32
,
1945 unop( Iop_8Uto32
, IRExpr_Get( OFFB_C_FPCC
, Ity_I8
) ) );
1947 stmt( IRStmt_Put( OFFB_C_FPCC
,
1949 binop( Iop_Or32
, tmp
,
1951 binop( Iop_And32
, mkU32( 0x1 ), e
),
1952 mkU8( 4 ) ) ) ) ) );
1955 static IRExpr
* /* :: Ity_I8 */ getCR0 ( UInt cr
)
1958 return IRExpr_Get(guestCR0offset(cr
), Ity_I8
);
1961 static IRExpr
* /* :: Ity_I8 */ getCR321 ( UInt cr
)
1964 return IRExpr_Get(guestCR321offset(cr
), Ity_I8
);
1967 /* Fetch the specified CR bit (as per IBM/hardware notation) and
1968 return it at the bottom of an I32; the top 31 bits are guaranteed
1970 static IRExpr
* /* :: Ity_I32 */ getCRbit ( UInt bi
)
1976 /* Fetch the SO bit for this CR field */
1977 /* Note: And32 is redundant paranoia iff guest state only has 0
1978 or 1 in that slot. */
1979 return binop(Iop_And32
, unop(Iop_8Uto32
, getCR0(n
)), mkU32(1));
1981 /* Fetch the <, > or == bit for this CR field */
1982 return binop( Iop_And32
,
1984 unop(Iop_8Uto32
, getCR321(n
)),
1985 mkU8(toUChar(3-off
)) ),
1990 /* Dually, write the least significant bit of BIT to the specified CR
1991 bit. Indexing as per getCRbit. */
1992 static void putCRbit ( UInt bi
, IRExpr
* bit
)
1996 vassert(typeOfIRExpr(irsb
->tyenv
,bit
) == Ity_I32
);
1997 safe
= binop(Iop_And32
, bit
, mkU32(1));
2002 /* This is the SO bit for this CR field */
2003 putCR0(n
, unop(Iop_32to8
, safe
));
2006 vassert(off
== 1 || off
== 2 || off
== 3);
2011 /* old value with field masked out */
2012 binop(Iop_And32
, unop(Iop_8Uto32
, getCR321(n
)),
2013 mkU32(~(1 << off
))),
2014 /* new value in the right place */
2015 binop(Iop_Shl32
, safe
, mkU8(toUChar(off
)))
2022 /* Fetch the specified CR bit (as per IBM/hardware notation) and
2023 return it somewhere in an I32; it does not matter where, but
2024 whichever bit it is, all other bits are guaranteed to be zero. In
2025 other words, the I32-typed expression will be zero if the bit is
2026 zero and nonzero if the bit is 1. Write into *where the index
2027 of where the bit will be. */
2030 IRExpr
* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi
, Int
* where
)
2036 /* Fetch the SO bit for this CR field */
2037 /* Note: And32 is redundant paranoia iff guest state only has 0
2038 or 1 in that slot. */
2040 return binop(Iop_And32
, unop(Iop_8Uto32
, getCR0(n
)), mkU32(1));
2042 /* Fetch the <, > or == bit for this CR field */
2044 return binop( Iop_And32
,
2045 unop(Iop_8Uto32
, getCR321(n
)),
2046 mkU32(1 << (3-off
)) );
2050 /* Set the CR0 flags following an arithmetic operation.
2051 (Condition Register CR0 Field Definition, PPC32 p60)
2053 static IRExpr
* getXER_SO ( void );
2054 static void set_CR0 ( IRExpr
* result
)
2056 vassert(typeOfIRExpr(irsb
->tyenv
,result
) == Ity_I32
||
2057 typeOfIRExpr(irsb
->tyenv
,result
) == Ity_I64
);
2059 putCR321( 0, unop(Iop_64to8
,
2060 binop(Iop_CmpORD64S
, result
, mkU64(0))) );
2062 putCR321( 0, unop(Iop_32to8
,
2063 binop(Iop_CmpORD32S
, result
, mkU32(0))) );
2065 putCR0( 0, getXER_SO() );
2069 /* Set the CR6 flags following an AltiVec compare operation.
2070 * NOTE: This also works for VSX single-precision compares.
2072 static void set_AV_CR6 ( IRExpr
* result
, Bool test_all_ones
)
2074 /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
2075 32 bit: all_zeros = (v[0] || v[1] || v[2] || v[3]) == 0x0000'0000
2076 all_ones = ~(v[0] && v[1] && v[2] && v[3]) == 0x0000'0000
2077 where v[] denotes 32-bit lanes
2079 64 bit: all_zeros = (v[0] || v[1]) == 0x0000'0000'0000'0000
2080 all_ones = ~(v[0] && v[1]) == 0x0000'0000'0000'0000
2081 where v[] denotes 64-bit lanes
2083 The 32- and 64-bit versions compute the same thing, but the 64-bit one
2084 tries to be a bit more efficient.
2086 vassert(typeOfIRExpr(irsb
->tyenv
,result
) == Ity_V128
);
2088 IRTemp overlappedOred
= newTemp(Ity_V128
);
2089 IRTemp overlappedAnded
= newTemp(Ity_V128
);
2092 IRTemp v0
= newTemp(Ity_V128
);
2093 IRTemp v1
= newTemp(Ity_V128
);
2094 assign( v0
, result
);
2095 assign( v1
, binop(Iop_ShrV128
, result
, mkU8(64)) );
2096 assign(overlappedOred
,
2097 binop(Iop_OrV128
, mkexpr(v0
), mkexpr(v1
)));
2098 assign(overlappedAnded
,
2099 binop(Iop_AndV128
, mkexpr(v0
), mkexpr(v1
)));
2101 IRTemp v0
= newTemp(Ity_V128
);
2102 IRTemp v1
= newTemp(Ity_V128
);
2103 IRTemp v2
= newTemp(Ity_V128
);
2104 IRTemp v3
= newTemp(Ity_V128
);
2105 assign( v0
, result
);
2106 assign( v1
, binop(Iop_ShrV128
, result
, mkU8(32)) );
2107 assign( v2
, binop(Iop_ShrV128
, result
, mkU8(64)) );
2108 assign( v3
, binop(Iop_ShrV128
, result
, mkU8(96)) );
2109 assign(overlappedOred
,
2111 binop(Iop_OrV128
, mkexpr(v0
), mkexpr(v1
)),
2112 binop(Iop_OrV128
, mkexpr(v2
), mkexpr(v3
))));
2113 assign(overlappedAnded
,
2115 binop(Iop_AndV128
, mkexpr(v0
), mkexpr(v1
)),
2116 binop(Iop_AndV128
, mkexpr(v2
), mkexpr(v3
))));
2119 IRTemp rOnes
= newTemp(Ity_I8
);
2120 IRTemp rZeroes
= newTemp(Ity_I8
);
2127 unop(Iop_V128to64
, mkexpr(overlappedOred
)))));
2133 unop(Iop_V128to64
, mkexpr(overlappedAnded
))))));
2139 unop(Iop_V128to32
, mkexpr(overlappedOred
)))));
2145 unop(Iop_V128to32
, mkexpr(overlappedAnded
))))));
2148 // rOnes might not be used below. But iropt will remove it, so there's no
2149 // inefficiency as a result.
2151 if (test_all_ones
) {
2152 putCR321( 6, binop(Iop_Or8
,
2153 binop(Iop_Shl8
, mkexpr(rOnes
), mkU8(3)),
2154 binop(Iop_Shl8
, mkexpr(rZeroes
), mkU8(1))) );
2156 putCR321( 6, binop(Iop_Shl8
, mkexpr(rZeroes
), mkU8(1)) );
2158 putCR0( 6, mkU8(0) );
2162 static IRExpr
* create_DCM ( IRType size
, IRTemp NaN
, IRTemp inf
, IRTemp zero
,
2163 IRTemp dnorm
, IRTemp pos
)
2165 /* This is a general function for creating the DCM for a 32-bit or
2166 64-bit expression based on the passes size.
2169 IROp opAND
, opOR
, opSHL
, opXto1
, op1UtoX
;
2171 vassert( ( size
== Ity_I32
) || ( size
== Ity_I64
) );
2173 if ( size
== Ity_I32
) {
2178 op1UtoX
= Iop_1Uto32
;
2179 neg
= newTemp( Ity_I32
);
2186 op1UtoX
= Iop_1Uto64
;
2187 neg
= newTemp( Ity_I64
);
2190 assign( neg
, unop( op1UtoX
, mkNOT1( unop( opXto1
,
2191 mkexpr ( pos
) ) ) ) );
2194 binop( opSHL
, mkexpr( NaN
), mkU8( 6 ) ),
2227 mkexpr( dnorm
) ) ) ) );
2230 /*------------------------------------------------------------*/
2231 /*--- Helpers for XER flags. ---*/
2232 /*------------------------------------------------------------*/
2234 static void putXER_SO ( IRExpr
* e
)
2237 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2238 so
= binop(Iop_And8
, e
, mkU8(1));
2239 stmt( IRStmt_Put( OFFB_XER_SO
, so
) );
2242 static void putXER_OV ( IRExpr
* e
)
2244 /* Interface to write XER[OV] */
2246 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2247 ov
= binop(Iop_And8
, e
, mkU8(1));
2248 stmt( IRStmt_Put( OFFB_XER_OV
, ov
) );
2251 static void putXER_OV32 ( IRExpr
* e
)
2253 /*Interface to write XER[OV32] */
2255 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2256 ov
= binop(Iop_And8
, e
, mkU8(1));
2258 /* The OV32 bit was added to XER in ISA 3.0. Do not write unless we
2259 * ISA 3.0 or beyond is supported. */
2260 if( OV32_CA32_supported
)
2261 stmt( IRStmt_Put( OFFB_XER_OV32
, ov
) );
2264 static void putXER_CA ( IRExpr
* e
)
2266 /* Interface to write XER[CA] */
2268 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2269 ca
= binop(Iop_And8
, e
, mkU8(1));
2270 stmt( IRStmt_Put( OFFB_XER_CA
, ca
) );
2273 static void putXER_CA32 ( IRExpr
* e
)
2275 /* Interface to write XER[CA32] */
2277 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2278 ca
= binop(Iop_And8
, e
, mkU8(1));
2280 /* The CA32 bit was added to XER in ISA 3.0. Do not write unless we
2281 * ISA 3.0 or beyond is supported. */
2282 if( OV32_CA32_supported
)
2283 stmt( IRStmt_Put( OFFB_XER_CA32
, ca
) );
2286 static void putXER_BC ( IRExpr
* e
)
2289 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2290 bc
= binop(Iop_And8
, e
, mkU8(0x7F));
2291 stmt( IRStmt_Put( OFFB_XER_BC
, bc
) );
2294 static IRExpr
* /* :: Ity_I8 */ getXER_SO ( void )
2296 return IRExpr_Get( OFFB_XER_SO
, Ity_I8
);
2299 static IRExpr
* /* :: Ity_I32 */ getXER_SO_32 ( void )
2301 return binop( Iop_And32
, unop(Iop_8Uto32
, getXER_SO()), mkU32(1) );
2304 static IRExpr
* /* :: Ity_I8 */ getXER_OV ( void )
2306 return IRExpr_Get( OFFB_XER_OV
, Ity_I8
);
2309 static IRExpr
* /* :: Ity_I8 */ getXER_OV32 ( void )
2311 return IRExpr_Get( OFFB_XER_OV32
, Ity_I8
);
2314 static IRExpr
* /* :: Ity_I32 */ getXER_OV_32 ( void )
2316 /* get XER[OV], 32-bit interface */
2317 return binop( Iop_And32
, unop(Iop_8Uto32
, getXER_OV()), mkU32(1) );
2320 static IRExpr
* /* :: Ity_I32 */ getXER_OV32_32 ( void )
2322 /* get XER[OV32], 32-bit interface */
2323 return binop( Iop_And32
, unop(Iop_8Uto32
, getXER_OV32()), mkU32(1) );
2326 static IRExpr
* /* :: Ity_I32 */ getXER_CA_32 ( void )
2328 /* get XER[CA], 32-bit interface */
2329 IRExpr
* ca
= IRExpr_Get( OFFB_XER_CA
, Ity_I8
);
2330 return binop( Iop_And32
, unop(Iop_8Uto32
, ca
), mkU32(1) );
2333 static IRExpr
* /* :: Ity_I32 */ getXER_CA32_32 ( void )
2335 /* get XER[CA32], 32-bit interface */
2336 IRExpr
* ca
= IRExpr_Get( OFFB_XER_CA32
, Ity_I8
);
2337 return binop( Iop_And32
, unop(Iop_8Uto32
, ca
), mkU32(1) );
2340 static IRExpr
* /* :: Ity_I8 */ getXER_BC ( void )
2342 return IRExpr_Get( OFFB_XER_BC
, Ity_I8
);
2345 static IRExpr
* /* :: Ity_I32 */ getXER_BC_32 ( void )
2347 IRExpr
* bc
= IRExpr_Get( OFFB_XER_BC
, Ity_I8
);
2348 return binop( Iop_And32
, unop(Iop_8Uto32
, bc
), mkU32(0x7F) );
2352 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and
2353 %XER.SO accordingly. */
2355 static IRExpr
* calculate_XER_OV_32( UInt op
, IRExpr
* res
,
2356 IRExpr
* argL
, IRExpr
* argR
)
2361 # define INT32_MIN 0x80000000
2363 # define XOR2(_aa,_bb) \
2364 binop(Iop_Xor32,(_aa),(_bb))
2366 # define XOR3(_cc,_dd,_ee) \
2367 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
2369 # define AND3(_ff,_gg,_hh) \
2370 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
2373 unop(Iop_Not32, (_jj))
2376 case /* 0 */ PPCG_FLAG_OP_ADD
:
2377 case /* 1 */ PPCG_FLAG_OP_ADDE
:
2378 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */
2379 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2381 = AND3( XOR3(argL
,argR
,mkU32(-1)),
2384 /* xer_ov can only be 0 or 1<<31 */
2386 = binop(Iop_Shr32
, xer_ov
, mkU8(31) );
2389 case /* 2 */ PPCG_FLAG_OP_DIVW
:
2390 /* (argL == INT32_MIN && argR == -1) || argR == 0 */
2394 binop(Iop_CmpEQ32
, argL
, mkU32(INT32_MIN
)),
2395 binop(Iop_CmpEQ32
, argR
, mkU32(-1))
2397 binop(Iop_CmpEQ32
, argR
, mkU32(0) )
2400 = unop(Iop_1Uto32
, xer_ov
);
2403 case /* 3 */ PPCG_FLAG_OP_DIVWU
:
2406 = unop(Iop_1Uto32
, binop(Iop_CmpEQ32
, argR
, mkU32(0)));
2409 case /* 4 */ PPCG_FLAG_OP_MULLW
:
2410 /* OV true if result can't be represented in 32 bits
2411 i.e sHi != sign extension of sLo */
2412 t64
= newTemp(Ity_I64
);
2413 assign( t64
, binop(Iop_MullS32
, argL
, argR
) );
2415 = binop( Iop_CmpNE32
,
2416 unop(Iop_64HIto32
, mkexpr(t64
)),
2418 unop(Iop_64to32
, mkexpr(t64
)),
2422 = unop(Iop_1Uto32
, xer_ov
);
2425 case /* 5 */ PPCG_FLAG_OP_NEG
:
2426 /* argL == INT32_MIN */
2429 binop(Iop_CmpEQ32
, argL
, mkU32(INT32_MIN
)) );
2432 case /* 6 */ PPCG_FLAG_OP_SUBF
:
2433 case /* 7 */ PPCG_FLAG_OP_SUBFC
:
2434 case /* 8 */ PPCG_FLAG_OP_SUBFE
:
2435 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
2437 = AND3( XOR3(NOT(argL
),argR
,mkU32(-1)),
2438 XOR2(NOT(argL
),res
),
2440 /* xer_ov can only be 0 or 1<<31 */
2442 = binop(Iop_Shr32
, xer_ov
, mkU8(31) );
2445 case PPCG_FLAG_OP_DIVWEU
:
2448 unop( Iop_1Uto32
, binop( Iop_CmpEQ32
, argR
, mkU32( 0 ) ) ),
2449 unop( Iop_1Uto32
, binop( Iop_CmpLT32U
, argR
, argL
) ) );
2452 case PPCG_FLAG_OP_DIVWE
:
2454 /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
2455 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero,
2456 * an overflow is implied.
2458 xer_ov
= binop( Iop_Or32
,
2459 unop( Iop_1Uto32
, binop( Iop_CmpEQ32
, argR
, mkU32( 0 ) ) ),
2460 unop( Iop_1Uto32
, mkAND1( binop( Iop_CmpEQ32
, res
, mkU32( 0 ) ),
2461 mkAND1( binop( Iop_CmpNE32
, argL
, mkU32( 0 ) ),
2462 binop( Iop_CmpNE32
, argR
, mkU32( 0 ) ) ) ) ) );
2468 vex_printf("calculate_XER_OV_32: op = %u\n", op
);
2469 vpanic("calculate_XER_OV_32(ppc)");
2481 static void set_XER_OV_OV32_32( UInt op
, IRExpr
* res
,
2482 IRExpr
* argL
, IRExpr
* argR
)
2486 vassert(op
< PPCG_FLAG_OP_NUMBER
);
2487 vassert(typeOfIRExpr(irsb
->tyenv
,res
) == Ity_I32
);
2488 vassert(typeOfIRExpr(irsb
->tyenv
,argL
) == Ity_I32
);
2489 vassert(typeOfIRExpr(irsb
->tyenv
,argR
) == Ity_I32
);
2491 xer_ov
= calculate_XER_OV_32( op
, res
, argL
, argR
);
2493 /* xer_ov MUST denote either 0 or 1, no other value allowed */
2494 putXER_OV( unop(Iop_32to8
, xer_ov
) );
2495 putXER_OV32( unop(Iop_32to8
, xer_ov
) );
2498 static IRExpr
* calculate_XER_OV_64( UInt op
, IRExpr
* res
,
2499 IRExpr
* argL
, IRExpr
* argR
)
2503 # define INT64_MIN 0x8000000000000000ULL
2505 # define XOR2(_aa,_bb) \
2506 binop(Iop_Xor64,(_aa),(_bb))
2508 # define XOR3(_cc,_dd,_ee) \
2509 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
2511 # define AND3(_ff,_gg,_hh) \
2512 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
2515 unop(Iop_Not64, (_jj))
2518 case /* 0 */ PPCG_FLAG_OP_ADD
:
2519 case /* 1 */ PPCG_FLAG_OP_ADDE
:
2520 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */
2521 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2523 = AND3( XOR3(argL
,argR
,mkU64(-1)),
2526 /* xer_ov can only be 0 or 1<<63 */
2528 = unop(Iop_64to1
, binop(Iop_Shr64
, xer_ov
, mkU8(63)));
2531 case /* 2 */ PPCG_FLAG_OP_DIVW
:
2532 /* (argL == INT64_MIN && argR == -1) || argR == 0 */
2536 binop(Iop_CmpEQ64
, argL
, mkU64(INT64_MIN
)),
2537 binop(Iop_CmpEQ64
, argR
, mkU64(-1))
2539 binop(Iop_CmpEQ64
, argR
, mkU64(0) )
2543 case /* 3 */ PPCG_FLAG_OP_DIVWU
:
2546 = binop(Iop_CmpEQ64
, argR
, mkU64(0));
2549 case /* 4 */ PPCG_FLAG_OP_MULLW
: {
2550 /* OV true if result can't be represented in 64 bits
2551 i.e sHi != sign extension of sLo */
2553 = binop( Iop_CmpNE32
,
2554 unop(Iop_64HIto32
, res
),
2556 unop(Iop_64to32
, res
),
2562 case /* 5 */ PPCG_FLAG_OP_NEG
:
2563 /* argL == INT64_MIN */
2565 = binop(Iop_CmpEQ64
, argL
, mkU64(INT64_MIN
));
2568 case /* 6 */ PPCG_FLAG_OP_SUBF
:
2569 case /* 7 */ PPCG_FLAG_OP_SUBFC
:
2570 case /* 8 */ PPCG_FLAG_OP_SUBFE
:
2571 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2573 = AND3( XOR3(NOT(argL
),argR
,mkU64(-1)),
2574 XOR2(NOT(argL
),res
),
2576 /* xer_ov can only be 0 or 1<<63 */
2578 = unop(Iop_64to1
, binop(Iop_Shr64
, xer_ov
, mkU8(63)));
2581 case /* 14 */ PPCG_FLAG_OP_DIVDE
:
2583 /* If argR == 0, we must set the OV bit. But there's another condition
2584 * where we can get overflow set for divde . . . when the
2585 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND
2586 * both dividend and divisor are non-zero, it implies an overflow.
2589 = mkOR1( binop( Iop_CmpEQ64
, argR
, mkU64( 0 ) ),
2590 mkAND1( binop( Iop_CmpEQ64
, res
, mkU64( 0 ) ),
2591 mkAND1( binop( Iop_CmpNE64
, argL
, mkU64( 0 ) ),
2592 binop( Iop_CmpNE64
, argR
, mkU64( 0 ) ) ) ) );
2595 case /* 17 */ PPCG_FLAG_OP_DIVDEU
:
2596 /* If argR == 0 or if argL >= argR, set OV. */
2597 xer_ov
= mkOR1( binop( Iop_CmpEQ64
, argR
, mkU64( 0 ) ),
2598 binop( Iop_CmpLE64U
, argR
, argL
) );
2601 case /* 18 */ PPCG_FLAG_OP_MULLD
: {
2603 /* OV true if result can't be represented in 64 bits
2604 i.e sHi != sign extension of sLo */
2605 t128
= newTemp(Ity_I128
);
2606 assign( t128
, binop(Iop_MullS64
, argL
, argR
) );
2608 = binop( Iop_CmpNE64
,
2609 unop(Iop_128HIto64
, mkexpr(t128
)),
2611 unop(Iop_128to64
, mkexpr(t128
)),
2618 vex_printf("calculate_XER_OV_64: op = %u\n", op
);
2619 vpanic("calculate_XER_OV_64(ppc64)");
2631 static void set_XER_OV_64( UInt op
, IRExpr
* res
,
2632 IRExpr
* argL
, IRExpr
* argR
)
2635 vassert(op
< PPCG_FLAG_OP_NUMBER
);
2636 vassert(typeOfIRExpr(irsb
->tyenv
,res
) == Ity_I64
);
2637 vassert(typeOfIRExpr(irsb
->tyenv
,argL
) == Ity_I64
);
2638 vassert(typeOfIRExpr(irsb
->tyenv
,argR
) == Ity_I64
);
2640 /* xer_ov MUST denote either 0 or 1, no other value allowed */
2641 xer_ov
= calculate_XER_OV_64( op
, res
, argL
, argR
);
2642 putXER_OV( unop(Iop_1Uto8
, xer_ov
) );
2644 /* Update the summary overflow */
2645 putXER_SO( binop(Iop_Or8
, getXER_SO(), getXER_OV()) );
2648 static void update_SO( void ) {
2649 /* Update the summary overflow bit */
2650 putXER_SO( binop(Iop_Or8
, getXER_SO(), getXER_OV()) );
2653 static void copy_OV_to_OV32( void ) {
2654 /* Update the OV32 to match OV */
2655 putXER_OV32( getXER_OV() );
2658 static void set_XER_OV_OV32_SO ( IRType ty
, UInt op
, IRExpr
* res
,
2659 IRExpr
* argL
, IRExpr
* argR
)
2661 if (ty
== Ity_I32
) {
2662 set_XER_OV_OV32_32( op
, res
, argL
, argR
);
2665 set_XER_OV_64( op
, res
, argL
, argR
);
2666 xer_ov_32
= calculate_XER_OV_32( op
, unop(Iop_64to32
, res
),
2667 unop(Iop_64to32
, argL
),
2668 unop(Iop_64to32
, argR
));
2669 putXER_OV32( unop(Iop_32to8
, xer_ov_32
) );
2676 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2677 value being OLDCA. Set %XER.CA accordingly. */
2679 static IRExpr
* calculate_XER_CA_32 ( UInt op
, IRExpr
* res
,
2680 IRExpr
* argL
, IRExpr
* argR
, IRExpr
* oldca
)
2685 case /* 0 */ PPCG_FLAG_OP_ADD
:
2688 = unop(Iop_1Uto32
, binop(Iop_CmpLT32U
, res
, argL
));
2691 case /* 1 */ PPCG_FLAG_OP_ADDE
:
2692 /* res <u argL || (old_ca==1 && res==argL) */
2695 binop(Iop_CmpLT32U
, res
, argL
),
2697 binop(Iop_CmpEQ32
, oldca
, mkU32(1)),
2698 binop(Iop_CmpEQ32
, res
, argL
)
2702 = unop(Iop_1Uto32
, xer_ca
);
2705 case /* 8 */ PPCG_FLAG_OP_SUBFE
:
2706 /* res <u argR || (old_ca==1 && res==argR) */
2709 binop(Iop_CmpLT32U
, res
, argR
),
2711 binop(Iop_CmpEQ32
, oldca
, mkU32(1)),
2712 binop(Iop_CmpEQ32
, res
, argR
)
2716 = unop(Iop_1Uto32
, xer_ca
);
2719 case /* 7 */ PPCG_FLAG_OP_SUBFC
:
2720 case /* 9 */ PPCG_FLAG_OP_SUBFI
:
2723 = unop(Iop_1Uto32
, binop(Iop_CmpLE32U
, res
, argR
));
2726 case /* 10 */ PPCG_FLAG_OP_SRAW
:
2727 /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2728 If it is <= 31, behave like SRAWI; else XER.CA is the sign
2730 /* This term valid for shift amount < 32 only */
2734 binop(Iop_Sar32
, argL
, mkU8(31)),
2738 binop(Iop_Shl32
, mkU32(1),
2739 unop(Iop_32to8
,argR
)),
2745 /* shift amt > 31 ? */
2746 binop(Iop_CmpLT32U
, mkU32(31), argR
),
2747 /* yes -- get sign bit of argL */
2748 binop(Iop_Shr32
, argL
, mkU8(31)),
2749 /* no -- be like srawi */
2750 unop(Iop_1Uto32
, binop(Iop_CmpNE32
, xer_ca
, mkU32(0)))
2754 case /* 11 */ PPCG_FLAG_OP_SRAWI
:
2755 /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2756 0. Since the shift amount is known to be in the range
2757 0 .. 31 inclusive the following seems viable:
2758 xer.ca == 1 iff the following is nonzero:
2759 (argL >>s 31) -- either all 0s or all 1s
2760 & (argL & (1<<argR)-1) -- the stuff shifted out */
2764 binop(Iop_Sar32
, argL
, mkU8(31)),
2768 binop(Iop_Shl32
, mkU32(1),
2769 unop(Iop_32to8
,argR
)),
2774 = unop(Iop_1Uto32
, binop(Iop_CmpNE32
, xer_ca
, mkU32(0)));
2778 vex_printf("set_XER_CA: op = %u\n", op
);
2779 vpanic("set_XER_CA(ppc)");
2785 static void set_XER_CA_32 ( UInt op
, IRExpr
* res
,
2786 IRExpr
* argL
, IRExpr
* argR
, IRExpr
* oldca
)
2789 vassert(op
< PPCG_FLAG_OP_NUMBER
);
2790 vassert(typeOfIRExpr(irsb
->tyenv
,res
) == Ity_I32
);
2791 vassert(typeOfIRExpr(irsb
->tyenv
,argL
) == Ity_I32
);
2792 vassert(typeOfIRExpr(irsb
->tyenv
,argR
) == Ity_I32
);
2793 vassert(typeOfIRExpr(irsb
->tyenv
,oldca
) == Ity_I32
);
2795 /* Incoming oldca is assumed to hold the values 0 or 1 only. This
2796 seems reasonable given that it's always generated by
2797 getXER_CA_32(), which masks it accordingly. In any case it being
2798 0 or 1 is an invariant of the ppc guest state representation;
2799 if it has any other value, that invariant has been violated. */
2801 xer_ca
= calculate_XER_CA_32( op
, res
, argL
, argR
, oldca
);
2803 /* xer_ca MUST denote either 0 or 1, no other value allowed */
2804 putXER_CA( unop(Iop_32to8
, xer_ca
) );
2807 static IRExpr
* calculate_XER_CA_64 ( UInt op
, IRExpr
* res
,
2808 IRExpr
* argL
, IRExpr
* argR
, IRExpr
* oldca
)
2813 case /* 0 */ PPCG_FLAG_OP_ADD
:
2816 = unop(Iop_1Uto32
, binop(Iop_CmpLT64U
, res
, argL
));
2819 case /* 1 */ PPCG_FLAG_OP_ADDE
:
2820 /* res <u argL || (old_ca==1 && res==argL) */
2823 binop(Iop_CmpLT64U
, res
, argL
),
2825 binop(Iop_CmpEQ64
, oldca
, mkU64(1)),
2826 binop(Iop_CmpEQ64
, res
, argL
)
2830 = unop(Iop_1Uto32
, xer_ca
);
2833 case /* 8 */ PPCG_FLAG_OP_SUBFE
:
2834 /* res <u argR || (old_ca==1 && res==argR) */
2837 binop(Iop_CmpLT64U
, res
, argR
),
2839 binop(Iop_CmpEQ64
, oldca
, mkU64(1)),
2840 binop(Iop_CmpEQ64
, res
, argR
)
2844 = unop(Iop_1Uto32
, xer_ca
);
2847 case /* 7 */ PPCG_FLAG_OP_SUBFC
:
2848 case /* 9 */ PPCG_FLAG_OP_SUBFI
:
2851 = unop(Iop_1Uto32
, binop(Iop_CmpLE64U
, res
, argR
));
2855 case /* 10 */ PPCG_FLAG_OP_SRAW
:
2856 /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2857 If it is <= 31, behave like SRAWI; else XER.CA is the sign
2859 /* This term valid for shift amount < 31 only */
2864 binop(Iop_Sar64
, argL
, mkU8(31)),
2868 binop(Iop_Shl64
, mkU64(1),
2869 unop(Iop_64to8
,argR
)),
2875 /* shift amt > 31 ? */
2876 binop(Iop_CmpLT64U
, mkU64(31), argR
),
2877 /* yes -- get sign bit of argL */
2878 unop(Iop_64to32
, binop(Iop_Shr64
, argL
, mkU8(63))),
2879 /* no -- be like srawi */
2880 unop(Iop_1Uto32
, binop(Iop_CmpNE64
, xer_ca
, mkU64(0)))
2884 case /* 11 */ PPCG_FLAG_OP_SRAWI
:
2885 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2886 Since the shift amount is known to be in the range 0 .. 31
2887 inclusive the following seems viable:
2888 xer.ca == 1 iff the following is nonzero:
2889 (argL >>s 31) -- either all 0s or all 1s
2890 & (argL & (1<<argR)-1) -- the stuff shifted out */
2895 binop(Iop_Sar64
, argL
, mkU8(31)),
2899 binop(Iop_Shl64
, mkU64(1),
2900 unop(Iop_64to8
,argR
)),
2905 = unop(Iop_1Uto32
, binop(Iop_CmpNE64
, xer_ca
, mkU64(0)));
2909 case /* 12 */ PPCG_FLAG_OP_SRAD
:
2910 /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2911 If it is <= 63, behave like SRADI; else XER.CA is the sign
2913 /* This term valid for shift amount < 63 only */
2918 binop(Iop_Sar64
, argL
, mkU8(63)),
2922 binop(Iop_Shl64
, mkU64(1),
2923 unop(Iop_64to8
,argR
)),
2929 /* shift amt > 63 ? */
2930 binop(Iop_CmpLT64U
, mkU64(63), argR
),
2931 /* yes -- get sign bit of argL */
2932 unop(Iop_64to32
, binop(Iop_Shr64
, argL
, mkU8(63))),
2933 /* no -- be like sradi */
2934 unop(Iop_1Uto32
, binop(Iop_CmpNE64
, xer_ca
, mkU64(0)))
2939 case /* 13 */ PPCG_FLAG_OP_SRADI
:
2940 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2941 Since the shift amount is known to be in the range 0 .. 63
2942 inclusive, the following seems viable:
2943 xer.ca == 1 iff the following is nonzero:
2944 (argL >>s 63) -- either all 0s or all 1s
2945 & (argL & (1<<argR)-1) -- the stuff shifted out */
2950 binop(Iop_Sar64
, argL
, mkU8(63)),
2954 binop(Iop_Shl64
, mkU64(1),
2955 unop(Iop_64to8
,argR
)),
2960 = unop(Iop_1Uto32
, binop(Iop_CmpNE64
, xer_ca
, mkU64(0)));
2964 vex_printf("set_XER_CA: op = %u\n", op
);
2965 vpanic("set_XER_CA(ppc64)");
2971 static void set_XER_CA_64 ( UInt op
, IRExpr
* res
,
2972 IRExpr
* argL
, IRExpr
* argR
, IRExpr
* oldca
)
2975 vassert(op
< PPCG_FLAG_OP_NUMBER
);
2976 vassert(typeOfIRExpr(irsb
->tyenv
,res
) == Ity_I64
);
2977 vassert(typeOfIRExpr(irsb
->tyenv
,argL
) == Ity_I64
);
2978 vassert(typeOfIRExpr(irsb
->tyenv
,argR
) == Ity_I64
);
2979 vassert(typeOfIRExpr(irsb
->tyenv
,oldca
) == Ity_I64
);
2981 /* Incoming oldca is assumed to hold the values 0 or 1 only. This
2982 seems reasonable given that it's always generated by
2983 getXER_CA_32(), which masks it accordingly. In any case it being
2984 0 or 1 is an invariant of the ppc guest state representation;
2985 if it has any other value, that invariant has been violated. */
2987 xer_ca
= calculate_XER_CA_64( op
, res
, argL
, argR
, oldca
);
2989 /* xer_ca MUST denote either 0 or 1, no other value allowed */
2990 putXER_CA( unop(Iop_32to8
, xer_ca
) );
2993 static void set_XER_CA_CA32 ( IRType ty
, UInt op
, IRExpr
* res
,
2994 IRExpr
* argL
, IRExpr
* argR
, IRExpr
* oldca
)
2996 if (ty
== Ity_I32
) {
2997 set_XER_CA_32( op
, res
, argL
, argR
, oldca
);
2999 set_XER_CA_64( op
, res
, argL
, argR
, oldca
);
3003 /* Used only by addex instruction, which uses and sets OV as carry. */
3004 static void set_XER_OV_OV32_ADDEX ( IRType ty
, IRExpr
* res
,
3005 IRExpr
* argL
, IRExpr
* argR
,
3008 if (ty
== Ity_I32
) {
3009 IRTemp xer_ov
= newTemp(Ity_I32
);
3010 assign ( xer_ov
, unop(Iop_32to8
,
3011 calculate_XER_CA_32( PPCG_FLAG_OP_ADDE
,
3012 res
, argL
, argR
, old_ov
) ) );
3013 putXER_OV( mkexpr (xer_ov
) );
3014 putXER_OV32( mkexpr (xer_ov
) );
3018 xer_ov
= calculate_XER_CA_64( PPCG_FLAG_OP_ADDE
,
3019 res
, argL
, argR
, old_ov
);
3020 putXER_OV( unop(Iop_32to8
, xer_ov
) );
3021 xer_ov_32
= calculate_XER_CA_32( PPCG_FLAG_OP_ADDE
,
3022 unop(Iop_64to32
, res
),
3023 unop(Iop_64to32
, argL
),
3024 unop(Iop_64to32
, argR
),
3025 unop(Iop_64to32
, old_ov
) );
3026 putXER_OV32( unop(Iop_32to8
, xer_ov_32
) );
3032 /*------------------------------------------------------------*/
3033 /*--- Read/write to guest-state --- */
3034 /*------------------------------------------------------------*/
3036 static IRExpr
* /* :: Ity_I32/64 */ getGST ( PPC_GST reg
)
3038 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
3040 case PPC_GST_SPRG3_RO
:
3041 return IRExpr_Get( OFFB_SPRG3_RO
, ty
);
3044 return IRExpr_Get( OFFB_CIA
, ty
);
3047 return IRExpr_Get( OFFB_LR
, ty
);
3050 return IRExpr_Get( OFFB_CTR
, ty
);
3052 case PPC_GST_VRSAVE
:
3053 return IRExpr_Get( OFFB_VRSAVE
, Ity_I32
);
3056 return binop(Iop_And32
, IRExpr_Get( OFFB_VSCR
,Ity_I32
),
3057 mkU32(MASK_VSCR_VALID
));
3060 /* Synthesise the entire CR into a single word. Expensive. */
3061 # define FIELD(_n) \
3065 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
3066 binop(Iop_And8, getCR0(_n), mkU8(1)) \
3069 mkU8(4 * (7-(_n))) \
3071 return binop(Iop_Or32
,
3073 binop(Iop_Or32
, FIELD(0), FIELD(1)),
3074 binop(Iop_Or32
, FIELD(2), FIELD(3))
3077 binop(Iop_Or32
, FIELD(4), FIELD(5)),
3078 binop(Iop_Or32
, FIELD(6), FIELD(7))
3085 return binop(Iop_Or32
,
3088 binop( Iop_Shl32
, getXER_SO_32(), mkU8(31)),
3089 binop( Iop_Shl32
, getXER_OV_32(), mkU8(30))),
3091 binop( Iop_Shl32
, getXER_CA_32(), mkU8(29)),
3094 binop( Iop_Shl32
, getXER_OV32_32(), mkU8(19)),
3095 binop( Iop_Shl32
, getXER_CA32_32(), mkU8(18))));
3098 return IRExpr_Get( OFFB_TFHAR
, ty
);
3100 case PPC_GST_TEXASR
:
3101 return IRExpr_Get( OFFB_TEXASR
, ty
);
3103 case PPC_GST_TEXASRU
:
3104 return IRExpr_Get( OFFB_TEXASRU
, ty
);
3107 return IRExpr_Get( OFFB_TFIAR
, ty
);
3110 return IRExpr_Get( OFFB_PPR
, ty
);
3113 return unop( Iop_64HIto32
, IRExpr_Get( OFFB_PPR
, ty
) );
3116 return IRExpr_Get( OFFB_PSPB
, ty
);
3119 return IRExpr_Get( OFFB_DSCR
, ty
);
3122 vex_printf("getGST(ppc): reg = %u", reg
);
3123 vpanic("getGST(ppc)");
3127 /* Get a masked word from the given reg */
3128 static IRExpr
* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg
, ULong mask
)
3130 IRTemp val
= newTemp(Ity_I32
);
3131 vassert( reg
< PPC_GST_MAX
);
3135 case PPC_GST_FPSCR
: {
3136 /* Vex-generated code expects the FPSCR to be set as follows:
3137 all exceptions masked, round-to-nearest.
3138 This corresponds to a FPSCR value of 0x0. */
3140 /* In the lower 32 bits of FPSCR, we're keeping track of the binary
3141 * floating point rounding mode and Floating-point Condition code, so
3142 * if the mask isn't asking for either of these, just return 0x0.
3144 if ( mask
& ( MASK_FPSCR_C_FPCC
| MASK_FPSCR_RN
) ) {
3145 assign( val
, binop( Iop_Or32
,
3146 unop( Iop_8Uto32
, IRExpr_Get( OFFB_FPROUND
, Ity_I8
) ),
3149 IRExpr_Get( OFFB_C_FPCC
, Ity_I8
) ),
3152 assign( val
, mkU32(0x0) );
3159 vex_printf("getGST_masked(ppc): reg = %u", reg
);
3160 vpanic("getGST_masked(ppc)");
3163 if ( mask
!= 0xFFFFFFFF ) {
3164 return binop(Iop_And32
, mkexpr(val
), mkU32(mask
));
3170 /* Get a masked word from the given reg */
3171 static IRExpr
* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg
, ULong mask
) {
3173 vassert( reg
< PPC_GST_MAX
);
3177 case PPC_GST_FPSCR
: {
3178 /* In the upper 32 bits of FPSCR, we're only keeping track
3179 * of the decimal floating point rounding mode, so if the mask
3180 * isn't asking for this, just return 0x0.
3182 if (mask
& MASK_FPSCR_DRN
) {
3183 val
= binop( Iop_And32
,
3184 unop( Iop_8Uto32
, IRExpr_Get( OFFB_DFPROUND
, Ity_I8
) ),
3185 unop( Iop_64HIto32
, mkU64( mask
) ) );
3187 val
= mkU32( 0x0ULL
);
3193 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg
);
3194 vpanic( "getGST_masked_upper(ppc)" );
3200 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
3201 and return it at the bottom of an I32; the top 27 bits are
3202 guaranteed to be zero. */
3203 static IRExpr
* /* ::Ity_I32 */ getGST_field ( PPC_GST reg
, UInt fld
)
3208 vassert( reg
< PPC_GST_MAX
);
3216 return binop(Iop_Or32
,
3218 binop(Iop_Shl32
, getXER_SO_32(), mkU8(3)),
3219 binop(Iop_Shl32
, getXER_OV_32(), mkU8(2))),
3220 binop( Iop_Shl32
, getXER_CA_32(), mkU8(1)));
3225 return getGST_masked( reg
, mask
);
3227 return binop(Iop_Shr32
,
3228 getGST_masked( reg
, mask
),
3229 mkU8(toUChar( shft
)));
3233 static void putGST ( PPC_GST reg
, IRExpr
* src
)
3235 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
3236 IRType ty_src
= typeOfIRExpr(irsb
->tyenv
,src
);
3237 vassert( reg
< PPC_GST_MAX
);
3239 case PPC_GST_IP_AT_SYSCALL
:
3240 vassert( ty_src
== ty
);
3241 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL
, src
) );
3244 vassert( ty_src
== ty
);
3245 stmt( IRStmt_Put( OFFB_CIA
, src
) );
3248 vassert( ty_src
== ty
);
3249 stmt( IRStmt_Put( OFFB_LR
, src
) );
3252 vassert( ty_src
== ty
);
3253 stmt( IRStmt_Put( OFFB_CTR
, src
) );
3255 case PPC_GST_VRSAVE
:
3256 vassert( ty_src
== Ity_I32
);
3257 stmt( IRStmt_Put( OFFB_VRSAVE
,src
));
3260 vassert( ty_src
== Ity_I32
);
3261 stmt( IRStmt_Put( OFFB_VSCR
,
3262 binop(Iop_And32
, src
,
3263 mkU32(MASK_VSCR_VALID
)) ) );
3266 vassert( ty_src
== Ity_I32
);
3267 putXER_SO( unop(Iop_32to8
, binop(Iop_Shr32
, src
, mkU8(31))) );
3268 putXER_OV( unop(Iop_32to8
, binop(Iop_Shr32
, src
, mkU8(30))) );
3269 putXER_CA( unop(Iop_32to8
, binop(Iop_Shr32
, src
, mkU8(29))) );
3270 putXER_OV32( unop(Iop_32to8
, binop(Iop_Shr32
, src
, mkU8(19))) );
3271 putXER_CA32( unop(Iop_32to8
, binop(Iop_Shr32
, src
, mkU8(18))) );
3272 putXER_BC( unop(Iop_32to8
, src
) );
3275 case PPC_GST_EMWARN
:
3276 vassert( ty_src
== Ity_I32
);
3277 stmt( IRStmt_Put( OFFB_EMNOTE
,src
) );
3280 case PPC_GST_CMSTART
:
3281 vassert( ty_src
== ty
);
3282 stmt( IRStmt_Put( OFFB_CMSTART
, src
) );
3286 vassert( ty_src
== ty
);
3287 stmt( IRStmt_Put( OFFB_CMLEN
, src
) );
3290 case PPC_GST_TEXASR
:
3291 vassert( ty_src
== Ity_I64
);
3292 stmt( IRStmt_Put( OFFB_TEXASR
, src
) );
3295 case PPC_GST_TEXASRU
:
3296 vassert( ty_src
== Ity_I32
);
3297 stmt( IRStmt_Put( OFFB_TEXASRU
, src
) );
3301 vassert( ty_src
== Ity_I64
);
3302 stmt( IRStmt_Put( OFFB_TFIAR
, src
) );
3305 vassert( ty_src
== Ity_I64
);
3306 stmt( IRStmt_Put( OFFB_TFHAR
, src
) );
3312 /* The Program Priority Register (PPR) stores the priority in
3313 * bits [52:50]. The user setable priorities are:
3321 * If the argument is not between 0b001 and 0b100 the priority is set
3322 * to 0b100. The priority can only be set to 0b101 if the the Problem
3323 * State Boost Register is non-zero. The value of the PPR is not
3324 * changed if the input is not valid.
3327 IRTemp not_valid
= newTemp(Ity_I64
);
3328 IRTemp has_perm
= newTemp(Ity_I64
);
3329 IRTemp new_src
= newTemp(Ity_I64
);
3330 IRTemp PSPB_val
= newTemp(Ity_I64
);
3331 IRTemp value
= newTemp(Ity_I64
);
3333 vassert(( ty_src
== Ity_I64
) || ( ty_src
== Ity_I32
));
3334 assign( PSPB_val
, binop( Iop_32HLto64
,
3336 IRExpr_Get( OFFB_PSPB
, Ity_I32
) ) );
3337 if( reg
== PPC_GST_PPR32
) {
3338 vassert( ty_src
== Ity_I32
);
3339 assign( value
, binop( Iop_32HLto64
,
3342 binop( Iop_Shr32
, src
, mkU8( 18 ) ),
3345 vassert( ty_src
== Ity_I64
);
3346 assign( value
, binop( Iop_And64
,
3347 binop( Iop_Shr64
, src
, mkU8( 50 ) ),
3359 mkexpr( value
) ) ) ) );
3367 binop( Iop_CmpLT64U
,
3369 mkexpr( value
) ) ) ) );
3374 mkexpr( not_valid
) ),
3377 mkexpr( not_valid
),
3385 IRExpr_Get( OFFB_PPR
, ty
),
3390 /* make sure we only set the valid bit field [52:50] */
3391 stmt( IRStmt_Put( OFFB_PPR
,
3394 mkU64( 0x1C000000000000) ) ) );
3398 vassert( ty_src
== Ity_I64
);
3399 stmt( IRStmt_Put( OFFB_DSCR
, src
) );
3403 vex_printf("putGST(ppc): reg = %u", reg
);
3404 vpanic("putGST(ppc)");
3408 /* Write masked src to the given reg */
3409 static void putGST_masked ( PPC_GST reg
, IRExpr
* src
, ULong mask
)
3411 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
3412 vassert( reg
< PPC_GST_MAX
);
3413 vassert( typeOfIRExpr( irsb
->tyenv
,src
) == Ity_I64
);
3416 case PPC_GST_FPSCR
: {
3417 /* Allow writes to either binary or decimal floating point
3420 /* If any part of |mask| covers FPSCR.RN, update the bits of
3421 FPSCR.RN by copying in |src| for locations where the
3422 corresponding bit in |mask| is 1, and leaving it unchanged
3423 for corresponding |mask| zero bits. */
3424 if (mask
& MASK_FPSCR_RN
) {
3434 unop(Iop_64to32
, src
),
3435 mkU32(MASK_FPSCR_RN
& mask
)
3439 unop(Iop_8Uto32
, IRExpr_Get(OFFB_FPROUND
,Ity_I8
)),
3440 mkU32(MASK_FPSCR_RN
& ~mask
)
3448 if (mask
& MASK_FPSCR_C_FPCC
) {
3449 /* FPCC bits are in [47:51] */
3460 unop(Iop_64to32
, src
),
3461 mkU32(MASK_FPSCR_C_FPCC
& mask
) ),
3465 IRExpr_Get(OFFB_C_FPCC
,Ity_I8
)),
3466 mkU32(MASK_FPSCR_C_FPCC
& ~mask
)
3472 /* Similarly, update FPSCR.DRN if any bits of |mask|
3473 corresponding to FPSCR.DRN are set. */
3474 if (mask
& MASK_FPSCR_DRN
) {
3484 unop(Iop_64HIto32
, src
),
3485 mkU32((MASK_FPSCR_DRN
& mask
) >> 32)
3489 unop(Iop_8Uto32
, IRExpr_Get(OFFB_DFPROUND
,Ity_I8
)),
3490 mkU32((MASK_FPSCR_DRN
& ~mask
) >> 32)
3498 /* Give EmNote for attempted writes to:
3499 - Exception Controls
3502 if (mask
& 0xFC) { // Exception Control, Non-IEE mode
3503 VexEmNote ew
= EmWarn_PPCexns
;
3505 /* If any of the src::exception_control bits are actually set,
3506 side-exit to the next insn, reporting the warning,
3507 so that Valgrind's dispatcher sees the warning. */
3508 putGST( PPC_GST_EMWARN
, mkU32(ew
) );
3511 binop(Iop_CmpNE32
, mkU32(ew
), mkU32(EmNote_NONE
)),
3513 mkSzConst( ty
, nextInsnAddr()), OFFB_CIA
));
3516 /* Ignore all other writes */
3521 vex_printf("putGST_masked(ppc): reg = %u", reg
);
3522 vpanic("putGST_masked(ppc)");
3526 /* Write the least significant nibble of src to the specified
3527 REG[FLD] (as per IBM/hardware notation). */
3528 static void putGST_field ( PPC_GST reg
, IRExpr
* src
, UInt fld
)
3533 vassert( typeOfIRExpr(irsb
->tyenv
,src
) == Ity_I32
);
3534 vassert( fld
< 16 );
3535 vassert( reg
< PPC_GST_MAX
);
3542 mask
= mask
<< shft
;
3546 putCR0 (fld
, binop(Iop_And8
, mkU8(1 ), unop(Iop_32to8
, src
)));
3547 putCR321(fld
, binop(Iop_And8
, mkU8(7<<1), unop(Iop_32to8
, src
)));
3552 IRExpr
* src64
= unop( Iop_32Uto64
, src
);
3555 putGST_masked( reg
, src64
, mask
);
3558 binop( Iop_Shl64
, src64
, mkU8( toUChar( shft
) ) ),
3565 static void putFPCC ( IRExpr
* e
)
3567 /* The assumption is that the value of the FPCC are passed in the lower
3568 * four bits of a 32 bit value.
3570 * Note, the C and FPCC bits which are a field of the FPSCR
3571 * register are stored in their own "register" in
3572 * memory. The FPCC bits are in the lower 4 bits. We don't need to
3573 * shift it to the bits to their location in the FPSCR register. Note,
3574 * not all of the FPSCR register bits are supported. We are writing all
3575 * of the bits in the FPCC field but not the C field.
3579 vassert( typeOfIRExpr( irsb
->tyenv
, e
) == Ity_I32
);
3580 /* Get the C bit field */
3581 tmp
= binop( Iop_And32
,
3583 unop( Iop_8Uto32
, IRExpr_Get( OFFB_C_FPCC
, Ity_I8
) ) );
3585 stmt( IRStmt_Put( OFFB_C_FPCC
,
3587 binop( Iop_Or32
, tmp
,
3588 binop( Iop_And32
, mkU32( 0xF ), e
) ) ) ) );
3592 static IRExpr
* /* ::Ity_I32 */ getC ( void )
3594 /* Note, the Floating-Point Result Class Descriptor (C) bit is a field of
3595 * the FPSCR registered are stored in its own "register" in guest state
3596 * with the FPCC bit field. C | FPCC
3598 IRTemp val
= newTemp(Ity_I32
);
3600 assign( val
, binop( Iop_Shr32
,
3601 unop( Iop_8Uto32
, IRExpr_Get( OFFB_C_FPCC
, Ity_I8
) ),
3606 static IRExpr
* /* ::Ity_I32 */ getFPCC ( void )
3608 /* Note, the FPCC bits are a field of the FPSCR
3609 * register are stored in their own "register" in
3610 * guest state with the C bit field. C | FPCC
3612 IRTemp val
= newTemp( Ity_I32
);
3614 assign( val
, binop( Iop_And32
, unop( Iop_8Uto32
,
3615 IRExpr_Get( OFFB_C_FPCC
, Ity_I8
) ),
3620 /*------------------------------------------------------------*/
3621 /* Helpers for VSX instructions that do floating point
3622 * operations and need to determine if a src contains a
3625 *------------------------------------------------------------*/
3627 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
3628 #define FP_FRAC_PART(x) binop( Iop_And64, \
3630 mkU64( NONZERO_FRAC_MASK ) )
3632 #define NONZERO_FRAC_MASK32 0x007fffffULL
3633 #define FP_FRAC_PART32(x) binop( Iop_And32, \
3635 mkU32( NONZERO_FRAC_MASK32 ) )
3637 // Returns exponent part of floating point src as I32
3638 static IRExpr
* fp_exp_part( IRType size
, IRTemp src
)
3640 IRExpr
*shift_by
, *mask
, *tsrc
;
3642 vassert( ( size
== Ity_I16
) || ( size
== Ity_I32
)
3643 || ( size
== Ity_I64
) );
3645 if( size
== Ity_I16
) {
3646 /* The 16-bit floating point value is in the lower 16-bits
3647 * of the 32-bit input value.
3649 tsrc
= mkexpr( src
);
3650 mask
= mkU32( 0x1F );
3651 shift_by
= mkU8( 10 );
3653 } else if( size
== Ity_I32
) {
3654 tsrc
= mkexpr( src
);
3655 mask
= mkU32( 0xFF );
3656 shift_by
= mkU8( 23 );
3658 } else if( size
== Ity_I64
) {
3659 tsrc
= unop( Iop_64HIto32
, mkexpr( src
) );
3660 mask
= mkU32( 0x7FF );
3661 shift_by
= mkU8( 52 - 32 );
3665 vassert(0); // Stops gcc complaining at "-Og"
3668 return binop( Iop_And32
, binop( Iop_Shr32
, tsrc
, shift_by
), mask
);
3671 /* The following functions check the floating point value to see if it
3672 is zero, infinity, NaN, Normalized, Denormalized.
3674 /* 16-bit floating point number is stored in the lower 16-bits of 32-bit value */
3675 #define I16_EXP_MASK 0x7C00
3676 #define I16_FRACTION_MASK 0x03FF
3677 #define I16_MSB_FRACTION_MASK 0x0200
3678 #define I32_EXP_MASK 0x7F800000
3679 #define I32_FRACTION_MASK 0x007FFFFF
3680 #define I32_MSB_FRACTION_MASK 0x00400000
3681 #define I32_SIGN_MASK 0x80000000
3682 #define I64_EXP_MASK 0x7FF0000000000000ULL
3683 #define I64_FRACTION_MASK 0x000FFFFFFFFFFFFFULL
3684 #define I64_MSB_FRACTION_MASK 0x0008000000000000ULL
3685 #define V128_EXP_MASK 0x7FFF000000000000ULL
3686 #define V128_FRACTION_MASK 0x0000FFFFFFFFFFFFULL /* upper 64-bit fractional mask */
3687 #define V128_MSB_FRACTION_MASK 0x0000800000000000ULL /* upper 64-bit fractional mask */
3689 void setup_value_check_args( IRType size
, IRTemp
*exp_mask
, IRTemp
*frac_mask
,
3690 IRTemp
*msb_frac_mask
, IRTemp
*zero
);
3692 void setup_value_check_args( IRType size
, IRTemp
*exp_mask
, IRTemp
*frac_mask
,
3693 IRTemp
*msb_frac_mask
, IRTemp
*zero
) {
3695 vassert( ( size
== Ity_I16
) || ( size
== Ity_I32
)
3696 || ( size
== Ity_I64
) || ( size
== Ity_V128
) );
3698 if( size
== Ity_I16
) {
3699 /* The 16-bit floating point value is in the lower 16-bits of
3700 the 32-bit input value */
3701 *frac_mask
= newTemp( Ity_I32
);
3702 *msb_frac_mask
= newTemp( Ity_I32
);
3703 *exp_mask
= newTemp( Ity_I32
);
3704 *zero
= newTemp( Ity_I32
);
3705 assign( *exp_mask
, mkU32( I16_EXP_MASK
) );
3706 assign( *frac_mask
, mkU32( I16_FRACTION_MASK
) );
3707 assign( *msb_frac_mask
, mkU32( I16_MSB_FRACTION_MASK
) );
3708 assign( *zero
, mkU32( 0 ) );
3710 } else if( size
== Ity_I32
) {
3711 *frac_mask
= newTemp( Ity_I32
);
3712 *msb_frac_mask
= newTemp( Ity_I32
);
3713 *exp_mask
= newTemp( Ity_I32
);
3714 *zero
= newTemp( Ity_I32
);
3715 assign( *exp_mask
, mkU32( I32_EXP_MASK
) );
3716 assign( *frac_mask
, mkU32( I32_FRACTION_MASK
) );
3717 assign( *msb_frac_mask
, mkU32( I32_MSB_FRACTION_MASK
) );
3718 assign( *zero
, mkU32( 0 ) );
3720 } else if( size
== Ity_I64
) {
3721 *frac_mask
= newTemp( Ity_I64
);
3722 *msb_frac_mask
= newTemp( Ity_I64
);
3723 *exp_mask
= newTemp( Ity_I64
);
3724 *zero
= newTemp( Ity_I64
);
3725 assign( *exp_mask
, mkU64( I64_EXP_MASK
) );
3726 assign( *frac_mask
, mkU64( I64_FRACTION_MASK
) );
3727 assign( *msb_frac_mask
, mkU64( I64_MSB_FRACTION_MASK
) );
3728 assign( *zero
, mkU64( 0 ) );
3731 /* V128 is converted to upper and lower 64 bit values, */
3732 /* uses 64-bit operators and temps */
3733 *frac_mask
= newTemp( Ity_I64
);
3734 *msb_frac_mask
= newTemp( Ity_I64
);
3735 *exp_mask
= newTemp( Ity_I64
);
3736 *zero
= newTemp( Ity_I64
);
3737 assign( *exp_mask
, mkU64( V128_EXP_MASK
) );
3738 /* upper 64-bit fractional mask */
3739 assign( *frac_mask
, mkU64( V128_FRACTION_MASK
) );
3740 assign( *msb_frac_mask
, mkU64( V128_MSB_FRACTION_MASK
) );
3741 assign( *zero
, mkU64( 0 ) );
3745 /* Helper function for the various function which check the value of
3746 the floating point value.
3748 static IRExpr
* exponent_compare( IRType size
, IRTemp src
,
3749 IRTemp exp_mask
, IRExpr
*exp_val
)
3751 IROp opAND
, opCmpEQ
;
3753 if( ( size
== Ity_I16
) || ( size
== Ity_I32
) ) {
3754 /* The 16-bit floating point value is in the lower 16-bits of
3755 the 32-bit input value */
3757 opCmpEQ
= Iop_CmpEQ32
;
3761 opCmpEQ
= Iop_CmpEQ64
;
3764 if( size
== Ity_V128
) {
3765 return binop( opCmpEQ
,
3767 unop( Iop_V128HIto64
, mkexpr( src
) ),
3768 mkexpr( exp_mask
) ),
3771 } else if( ( size
== Ity_I16
) || ( size
== Ity_I32
) ) {
3772 return binop( opCmpEQ
,
3773 binop ( opAND
, mkexpr( src
), mkexpr( exp_mask
) ),
3776 /* 64-bit operands */
3779 return binop( opCmpEQ
,
3780 binop ( opAND
, mkexpr( src
), mkexpr( exp_mask
) ),
3783 /* No support for 64-bit compares in 32-bit mode, need to do upper
3784 * and lower parts using 32-bit compare operators.
3787 mkAND1( binop( Iop_CmpEQ32
,
3789 unop(Iop_64HIto32
, mkexpr( src
) ),
3790 unop(Iop_64HIto32
, mkexpr( exp_mask
) ) ),
3791 unop(Iop_64HIto32
, exp_val
) ),
3794 unop(Iop_64to32
, mkexpr( src
) ),
3795 unop(Iop_64to32
, mkexpr( exp_mask
) ) ),
3796 unop(Iop_64to32
, exp_val
) ) );
3801 static IRExpr
*fractional_part_compare( IRType size
, IRTemp src
,
3802 IRTemp frac_mask
, IRExpr
*zero
)
3804 IROp opAND
, opCmpEQ
;
3806 if( ( size
== Ity_I16
) || ( size
== Ity_I32
) ) {
3807 /*The 16-bit floating point value is in the lower 16-bits of
3808 the 32-bit input value */
3810 opCmpEQ
= Iop_CmpEQ32
;
3814 opCmpEQ
= Iop_CmpEQ64
;
3817 if( size
== Ity_V128
) {
3818 /* 128-bit, note we only care if the fractional part is zero so take upper
3819 52-bits of fractional part and lower 64-bits and OR them together and test
3820 for zero. This keeps the temp variables and operators all 64-bit.
3822 return binop( opCmpEQ
,
3825 unop( Iop_V128HIto64
, mkexpr( src
) ),
3826 mkexpr( frac_mask
) ),
3827 unop( Iop_V128to64
, mkexpr( src
) ) ),
3830 } else if( ( size
== Ity_I16
) || ( size
== Ity_I32
) ) {
3831 return binop( opCmpEQ
,
3832 binop( opAND
, mkexpr( src
), mkexpr( frac_mask
) ),
3836 return binop( opCmpEQ
,
3837 binop( opAND
, mkexpr( src
), mkexpr( frac_mask
) ),
3840 /* No support for 64-bit compares in 32-bit mode, need to do upper
3841 * and lower parts using 32-bit compare operators.
3844 mkAND1( binop( Iop_CmpEQ32
,
3846 unop(Iop_64HIto32
, mkexpr( src
) ),
3847 unop(Iop_64HIto32
, mkexpr( frac_mask
) ) ),
3851 unop(Iop_64to32
, mkexpr( src
) ),
3852 unop(Iop_64to32
, mkexpr( frac_mask
) ) ),
3858 // Infinity: exp has all bits set, and fraction is zero; s = 0/1
3859 static IRExpr
* is_Inf( IRType size
, IRTemp src
)
3861 IRExpr
*max_exp
, *zero_frac
;
3862 IRTemp exp_mask
, frac_mask
, msb_frac_mask
, zero
;
3864 setup_value_check_args( size
, &exp_mask
, &frac_mask
, &msb_frac_mask
,
3867 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
3868 max_exp
= exponent_compare( size
, src
, exp_mask
, mkexpr( exp_mask
) );
3870 /* check fractional part is all zeros */
3871 zero_frac
= fractional_part_compare( size
, src
, frac_mask
, mkexpr( zero
) );
3873 return mkAND1( max_exp
, zero_frac
);
3876 // Zero: exp is zero and fraction is zero; s = 0/1
3877 static IRExpr
* is_Zero( IRType size
, IRTemp src
)
3879 IRExpr
*zero_exp
, *zero_frac
;
3880 IRTemp exp_mask
, frac_mask
, msb_frac_mask
, zero
;
3882 setup_value_check_args( size
, &exp_mask
, &frac_mask
, &msb_frac_mask
,
3885 /* check the exponent is all zeros, i.e. (exp AND exp_mask) = zero */
3886 zero_exp
= exponent_compare( size
, src
, exp_mask
, mkexpr( zero
) );
3888 /* check fractional part is all zeros */
3889 zero_frac
= fractional_part_compare( size
, src
, frac_mask
, mkexpr( zero
) );
3891 return mkAND1( zero_exp
, zero_frac
);
3894 /* SNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '1'
3895 * QNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '0'
3897 static IRExpr
* is_NaN( IRType size
, IRTemp src
)
3899 IRExpr
*max_exp
, *not_zero_frac
;
3900 IRTemp exp_mask
, frac_mask
, msb_frac_mask
, zero
;
3902 setup_value_check_args( size
, &exp_mask
, &frac_mask
, &msb_frac_mask
,
3905 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
3906 max_exp
= exponent_compare( size
, src
, exp_mask
, mkexpr( exp_mask
) );
3908 /* check fractional part is not zero */
3909 not_zero_frac
= unop( Iop_Not1
,
3910 fractional_part_compare( size
, src
, frac_mask
,
3913 return mkAND1( max_exp
, not_zero_frac
);
3916 static IRExpr
* is_sNaN( IRType size
, IRTemp src
)
3918 IRExpr
*max_exp
, *not_zero_frac
, *msb_zero
;
3919 IRTemp exp_mask
, frac_mask
, msb_frac_mask
, zero
;
3921 setup_value_check_args( size
, &exp_mask
, &frac_mask
, &msb_frac_mask
,
3924 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
3925 max_exp
= exponent_compare( size
, src
, exp_mask
, mkexpr( exp_mask
) );
3927 /* Most significant fractional bit is zero for sNaN */
3928 msb_zero
= fractional_part_compare ( size
, src
, msb_frac_mask
,
3931 /* check fractional part is not zero */
3932 not_zero_frac
= unop( Iop_Not1
,
3933 fractional_part_compare( size
, src
, frac_mask
,
3936 return mkAND1( msb_zero
, mkAND1( max_exp
, not_zero_frac
) );
3939 /* Denormalized number has a zero exponent and non zero fraction. */
3940 static IRExpr
* is_Denorm( IRType size
, IRTemp src
)
3942 IRExpr
*zero_exp
, *not_zero_frac
;
3943 IRTemp exp_mask
, frac_mask
, msb_frac_mask
, zero
;
3945 setup_value_check_args( size
, &exp_mask
, &frac_mask
, &msb_frac_mask
,
3948 /* check exponent is all zeros */
3949 zero_exp
= exponent_compare( size
, src
, exp_mask
, mkexpr( zero
) );
3951 /* check fractional part is not zero */
3952 not_zero_frac
= unop( Iop_Not1
,
3953 fractional_part_compare( size
, src
, frac_mask
,
3956 return mkAND1( zero_exp
, not_zero_frac
);
3959 static IRExpr
* is_Zero_Vector( IRType element_size
, IRExpr
*src
)
3961 /* Check elements of a 128-bit floating point vector, with element size
3962 element_size, are zero. Return 1's in the elements of the vector
3963 which are values. */
3964 IRTemp exp_maskV128
= newTemp( Ity_V128
);
3965 IRTemp exp_zeroV128
= newTemp( Ity_V128
);
3966 IRTemp frac_maskV128
= newTemp( Ity_V128
);
3967 IRTemp frac_zeroV128
= newTemp( Ity_V128
);
3968 IRTemp zeroV128
= newTemp( Ity_V128
);
3970 assign( zeroV128
, mkV128( 0 ) );
3972 if ( element_size
== Ity_I32
) {
3973 assign( exp_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_EXP_MASK
) ) );
3974 assign( frac_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_FRACTION_MASK
) ) );
3977 vpanic("ERROR, is_Zero_Vector: Unknown input size");
3979 /* CmpEQ32x4 returns all 1's in elements where comparison is true */
3980 assign( exp_zeroV128
,
3981 binop( Iop_CmpEQ32x4
,
3983 mkexpr( exp_maskV128
), src
),
3984 mkexpr( zeroV128
) ) );
3986 assign( frac_zeroV128
,
3987 binop( Iop_CmpEQ32x4
,
3989 mkexpr( frac_maskV128
), src
),
3990 mkexpr( zeroV128
) ) );
3992 return binop( Iop_AndV128
, mkexpr( exp_zeroV128
),
3993 mkexpr( frac_zeroV128
) );
3996 static IRExpr
* is_Denorm_Vector( IRType element_size
, IRExpr
*src
)
3998 /* Check elements of a 128-bit floating point vector, with element size
3999 element_size, are Denorm. Return 1's in the elements of the vector
4000 which are denormalized values. */
4001 IRTemp exp_maskV128
= newTemp( Ity_V128
);
4002 IRTemp exp_zeroV128
= newTemp( Ity_V128
);
4003 IRTemp frac_maskV128
= newTemp( Ity_V128
);
4004 IRTemp frac_nonzeroV128
= newTemp( Ity_V128
);
4005 IRTemp zeroV128
= newTemp( Ity_V128
);
4007 assign( zeroV128
, mkV128(0 ) );
4009 if ( element_size
== Ity_I32
) {
4010 assign( exp_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_EXP_MASK
) ) );
4011 assign( frac_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_FRACTION_MASK
) ) );
4014 vpanic("ERROR, is_Denorm_Vector: Unknown input size");
4016 /* CmpEQ32x4 returns all 1's in elements where comparison is true */
4017 assign( exp_zeroV128
,
4018 binop( Iop_CmpEQ32x4
,
4020 mkexpr( exp_maskV128
), src
),
4021 mkexpr( zeroV128
) ) );
4023 assign( frac_nonzeroV128
,
4025 binop( Iop_CmpEQ32x4
,
4027 mkexpr( frac_maskV128
), src
),
4028 mkexpr( zeroV128
) ) ) );
4030 return binop( Iop_AndV128
, mkexpr( exp_zeroV128
),
4031 mkexpr( frac_nonzeroV128
) );
4034 static IRExpr
* is_NaN_Vector( IRType element_size
, IRExpr
*src
)
4036 IRTemp max_expV128
= newTemp( Ity_V128
);
4037 IRTemp not_zero_fracV128
= newTemp( Ity_V128
);
4038 IRTemp zeroV128
= newTemp( Ity_V128
);
4039 IRTemp exp_maskV128
= newTemp( Ity_V128
);
4040 IRTemp frac_maskV128
= newTemp( Ity_V128
);
4043 assign( zeroV128
, mkV128( 0 ) );
4045 if ( element_size
== Ity_I32
) {
4046 assign( exp_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_EXP_MASK
) ) );
4047 assign( frac_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_FRACTION_MASK
) ) );
4048 opCmpEQ
= Iop_CmpEQ32x4
;
4051 vpanic("ERROR, is_NaN_Vector: Unknown input size");
4053 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
4054 assign( max_expV128
,
4056 binop( Iop_AndV128
, src
, mkexpr( exp_maskV128
) ),
4057 mkexpr( exp_maskV128
) ) );
4059 /* check fractional part is not zero */
4060 assign( not_zero_fracV128
,
4063 binop( Iop_AndV128
, src
, mkexpr( frac_maskV128
) ),
4064 mkexpr( zeroV128
) ) ) );
4066 return binop( Iop_AndV128
, mkexpr( max_expV128
),
4067 mkexpr( not_zero_fracV128
) );
4071 /* Normalized number has exponent between 1 and max_exp -1, or in other words
4072 the exponent is not zero and not equal to the max exponent value. */
4073 Currently
not needed since generate_C_FPCC is now done with a C helper
.
4074 Keep it around
, might be useful in the future
.
4075 static IRExpr
* is_Norm( IRType size
, IRTemp src
)
4077 IRExpr
*not_zero_exp
, *not_max_exp
;
4078 IRTemp exp_mask
, zero
;
4080 vassert( ( size
== Ity_I16
) || ( size
== Ity_I32
)
4081 || ( size
== Ity_I64
) || ( size
== Ity_V128
) );
4083 if( size
== Ity_I16
) {
4084 /* The 16-bit floating point value is in the lower 16-bits of
4085 the 32-bit input value */
4086 exp_mask
= newTemp( Ity_I32
);
4087 zero
= newTemp( Ity_I32
);
4088 assign( exp_mask
, mkU32( I16_EXP_MASK
) );
4089 assign( zero
, mkU32( 0 ) );
4091 } else if( size
== Ity_I32
) {
4092 exp_mask
= newTemp( Ity_I32
);
4093 zero
= newTemp( Ity_I32
);
4094 assign( exp_mask
, mkU32( I32_EXP_MASK
) );
4095 assign( zero
, mkU32( 0 ) );
4097 } else if( size
== Ity_I64
) {
4098 exp_mask
= newTemp( Ity_I64
);
4099 zero
= newTemp( Ity_I64
);
4100 assign( exp_mask
, mkU64( I64_EXP_MASK
) );
4101 assign( zero
, mkU64( 0 ) );
4104 /* V128 is converted to upper and lower 64 bit values, */
4105 /* uses 64-bit operators and temps */
4106 exp_mask
= newTemp( Ity_I64
);
4107 zero
= newTemp( Ity_I64
);
4108 assign( exp_mask
, mkU64( V128_EXP_MASK
) );
4109 assign( zero
, mkU64( 0 ) );
4112 not_zero_exp
= unop( Iop_Not1
,
4113 exponent_compare( size
, src
,
4114 exp_mask
, mkexpr( zero
) ) );
4115 not_max_exp
= unop( Iop_Not1
,
4116 exponent_compare( size
, src
,
4117 exp_mask
, mkexpr( exp_mask
) ) );
4119 return mkAND1( not_zero_exp
, not_max_exp
);
4123 static void generate_store_FPRF( IRType size
, IRTemp src
,
4124 const VexAbiInfo
* vbi
)
4127 /* This function was originally written using IR code. It has been
4128 * replaced with a clean helper due to the large amount of IR code
4129 * needed by this function.
4132 IRTemp tmp
= newTemp( Ity_I64
);
4133 vassert( ( size
== Ity_I16
) || ( size
== Ity_I32
)
4134 || ( size
== Ity_I64
) || ( size
== Ity_F128
) );
4136 vassert( ( typeOfIRExpr(irsb
->tyenv
, mkexpr( src
) ) == Ity_I32
)
4137 || ( typeOfIRExpr(irsb
->tyenv
, mkexpr( src
) ) == Ity_I64
)
4138 || ( typeOfIRExpr(irsb
->tyenv
, mkexpr( src
) ) == Ity_F128
) );
4140 if( size
== Ity_I16
) {
4142 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4143 "generate_store_C_FPCC_helper",
4144 fnptr_to_fnentry( vbi
, &generate_C_FPCC_helper
),
4145 mkIRExprVec_3( mkU64( size
), mkU64( 0 ),
4146 mkexpr( src
) ) ) );
4147 } else if( size
== Ity_I32
) {
4149 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4150 "generate_store_C_FPCC_helper",
4151 fnptr_to_fnentry( vbi
, &generate_C_FPCC_helper
),
4152 mkIRExprVec_3( mkU64( size
), mkU64( 0 ),
4153 mkexpr( src
) ) ) );
4154 } else if( size
== Ity_I64
) {
4156 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4157 "generate_store_C_FPCC_helper",
4158 fnptr_to_fnentry( vbi
, &generate_C_FPCC_helper
),
4159 mkIRExprVec_3( mkU64( size
), mkU64( 0 ),
4160 mkexpr( src
) ) ) );
4161 } else if( size
== Ity_F128
) {
4163 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4164 "generate_store_C_FPCC_helper",
4165 fnptr_to_fnentry( vbi
, &generate_C_FPCC_helper
),
4166 mkIRExprVec_3( mkU64( size
),
4167 unop( Iop_ReinterpF64asI64
,
4168 unop( Iop_F128HItoF64
,
4170 unop( Iop_ReinterpF64asI64
,
4171 unop( Iop_F128LOtoF64
,
4172 mkexpr( src
) ) ) ) ) );
4175 /* C is in the upper 32-bits, FPCC is in the lower 32-bits of the
4176 * value returned by the helper function
4178 putC( unop( Iop_64HIto32
, mkexpr( tmp
) ) );
4179 putFPCC( unop( Iop_64to32
, mkexpr( tmp
) ) );
4182 /* This function takes an Ity_I32 input argument interpreted
4183 as a single-precision floating point value. If src is a
4184 SNaN, it is changed to a QNaN and returned; otherwise,
4185 the original value is returned. */
4186 static IRExpr
* handle_SNaN_to_QNaN_32(IRExpr
* src
)
4188 #define SNAN_MASK32 0x00400000
4189 IRTemp tmp
= newTemp(Ity_I32
);
4190 IRTemp mask
= newTemp(Ity_I32
);
4191 IRTemp is_SNAN
= newTemp(Ity_I1
);
4193 vassert( typeOfIRExpr(irsb
->tyenv
, src
) == Ity_I32
);
4196 /* check if input is SNaN, if it is convert to QNaN */
4198 mkAND1( is_NaN( Ity_I32
, tmp
),
4200 binop( Iop_And32
, mkexpr( tmp
),
4201 mkU32( SNAN_MASK32
) ),
4203 /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
4204 assign ( mask
, binop( Iop_And32
,
4205 unop( Iop_1Sto32
, mkexpr( is_SNAN
) ),
4206 mkU32( SNAN_MASK32
) ) );
4207 return binop( Iop_Or32
, mkexpr( mask
), mkexpr( tmp
) );
4211 /* This helper function performs the negation part of operations of the form:
4212 * "Negate Multiply-<op>"
4213 * where "<op>" is either "Add" or "Sub".
4215 * This function takes one argument -- the floating point intermediate result (converted to
4216 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
4217 * the operation described above.
4219 static IRTemp
getNegatedResult(IRTemp intermediateResult
)
4221 ULong signbit_mask
= 0x8000000000000000ULL
;
4222 IRTemp signbit_32
= newTemp(Ity_I32
);
4223 IRTemp resultantSignbit
= newTemp(Ity_I1
);
4224 IRTemp negatedResult
= newTemp(Ity_I64
);
4225 assign( signbit_32
, binop( Iop_Shr32
,
4227 binop( Iop_And64
, mkexpr( intermediateResult
),
4228 mkU64( signbit_mask
) ) ),
4230 /* We negate the signbit if and only if the intermediate result from the
4231 * multiply-<op> was NOT a NaN. This is an XNOR predicate.
4233 assign( resultantSignbit
,
4237 mkexpr( signbit_32
),
4238 unop( Iop_1Uto32
, is_NaN( Ity_I64
,
4239 intermediateResult
) ) ),
4242 assign( negatedResult
,
4245 mkexpr( intermediateResult
),
4246 mkU64( ~signbit_mask
) ),
4247 binop( Iop_32HLto64
,
4249 unop( Iop_1Uto32
, mkexpr( resultantSignbit
) ),
4253 return negatedResult
;
4256 /* This helper function performs the negation part of operations of the form:
4257 * "Negate Multiply-<op>"
4258 * where "<op>" is either "Add" or "Sub".
4260 * This function takes one argument -- the floating point intermediate result (converted to
4261 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
4262 * the operation described above.
4264 static IRTemp
getNegatedResult_32(IRTemp intermediateResult
)
4266 UInt signbit_mask
= 0x80000000;
4267 IRTemp signbit_32
= newTemp(Ity_I32
);
4268 IRTemp resultantSignbit
= newTemp(Ity_I1
);
4269 IRTemp negatedResult
= newTemp(Ity_I32
);
4270 assign( signbit_32
, binop( Iop_Shr32
,
4271 binop( Iop_And32
, mkexpr( intermediateResult
),
4272 mkU32( signbit_mask
) ),
4274 /* We negate the signbit if and only if the intermediate result from the
4275 * multiply-<op> was NOT a NaN. This is an XNOR predicate.
4277 assign( resultantSignbit
,
4281 mkexpr( signbit_32
),
4282 unop( Iop_1Uto32
, is_NaN( Ity_I32
,
4283 intermediateResult
) ) ),
4286 assign( negatedResult
,
4289 mkexpr( intermediateResult
),
4290 mkU32( ~signbit_mask
) ),
4292 unop( Iop_1Uto32
, mkexpr( resultantSignbit
) ),
4295 return negatedResult
;
4298 static IRExpr
* negate_Vector ( IRType element_size
, IRExpr
* value
)
4300 /* This function takes a vector of floats. If the value is
4301 not a NaN, the value is negated. */
4303 IRTemp not_nan_mask
= newTemp( Ity_V128
);
4304 IRTemp sign_maskV128
= newTemp( Ity_V128
);
4306 if ( element_size
== Ity_I32
) {
4307 assign( sign_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_SIGN_MASK
) ) );
4310 vpanic("ERROR, negate_Vector: Unknown input size");
4312 /* Determine if vector elementes are not a NaN, negate sign bit
4313 for non NaN elements */
4314 assign ( not_nan_mask
,
4315 unop( Iop_NotV128
, is_NaN_Vector( element_size
, value
) ) );
4317 return binop( Iop_XorV128
,
4319 mkexpr( sign_maskV128
), mkexpr( not_nan_mask
) ),
4323 /* This function takes two quad_precision floating point numbers of type
4324 V128 and return 1 if src_A > src_B, 0 otherwise. */
4325 static IRExpr
* Quad_precision_gt ( IRTemp src_A
, IRTemp src_B
)
4327 #define FRAC_MASK64Hi 0x0000ffffffffffffULL
4328 #define MASK 0x7FFFFFFFFFFFFFFFULL /* exclude sign bit in upper 64 bits */
4329 #define EXP_MASK 0x7fff
4331 IRType ty
= Ity_I64
;
4332 IRTemp sign_A
= newTemp( ty
);
4333 IRTemp sign_B
= newTemp( ty
);
4334 IRTemp exp_A
= newTemp( ty
);
4335 IRTemp exp_B
= newTemp( ty
);
4336 IRTemp frac_A_hi
= newTemp( ty
);
4337 IRTemp frac_B_hi
= newTemp( ty
);
4338 IRTemp frac_A_lo
= newTemp( ty
);
4339 IRTemp frac_B_lo
= newTemp( ty
);
4342 /* extract exponents, and fractional parts so they can be compared */
4343 assign( sign_A
, binop( Iop_Shr64
,
4344 unop( Iop_V128HIto64
, mkexpr( src_A
) ),
4346 assign( sign_B
, binop( Iop_Shr64
,
4347 unop( Iop_V128HIto64
, mkexpr( src_B
) ),
4349 assign( exp_A
, binop( Iop_And64
,
4351 unop( Iop_V128HIto64
, mkexpr( src_A
) ),
4353 mkU64( EXP_MASK
) ) );
4354 assign( exp_B
, binop( Iop_And64
,
4356 unop( Iop_V128HIto64
, mkexpr( src_B
) ),
4358 mkU64( EXP_MASK
) ) );
4359 assign( frac_A_hi
, binop( Iop_And64
,
4360 unop( Iop_V128HIto64
, mkexpr( src_A
) ),
4361 mkU64( FRAC_MASK64Hi
) ) );
4362 assign( frac_B_hi
, binop( Iop_And64
,
4363 unop( Iop_V128HIto64
, mkexpr( src_B
) ),
4364 mkU64( FRAC_MASK64Hi
) ) );
4365 assign( frac_A_lo
, unop( Iop_V128to64
, mkexpr( src_A
) ) );
4366 assign( frac_B_lo
, unop( Iop_V128to64
, mkexpr( src_B
) ) );
4368 IRExpr
* A_zero
= mkAND1( binop( Iop_CmpEQ64
,
4370 unop( Iop_V128HIto64
,
4375 unop( Iop_V128to64
, mkexpr( src_A
) ),
4377 IRExpr
* B_zero
= mkAND1( binop( Iop_CmpEQ64
,
4379 unop( Iop_V128HIto64
,
4384 unop( Iop_V128to64
, mkexpr( src_B
) ),
4386 IRExpr
* A_B_zero
= mkAND1( A_zero
, B_zero
);
4388 /* Compare numbers */
4389 IRExpr
* both_pos
= mkAND1( binop( Iop_CmpEQ64
, mkexpr( sign_A
),
4391 binop( Iop_CmpEQ64
, mkexpr( sign_B
),
4393 IRExpr
* both_neg
= mkAND1( binop( Iop_CmpEQ64
, mkexpr( sign_A
),
4395 binop( Iop_CmpEQ64
, mkexpr( sign_B
),
4397 IRExpr
* sign_eq
= binop( Iop_CmpEQ64
, mkexpr( sign_A
), mkexpr( sign_B
) );
4398 IRExpr
* sign_gt
= binop( Iop_CmpLT64U
, mkexpr( sign_A
),
4399 mkexpr( sign_B
) ); /* A pos, B neg */
4401 IRExpr
* exp_eq
= binop( Iop_CmpEQ64
, mkexpr( exp_A
), mkexpr( exp_B
) );
4402 IRExpr
* exp_gt
= binop( Iop_CmpLT64U
, mkexpr( exp_B
), mkexpr( exp_A
) );
4403 IRExpr
* exp_lt
= binop( Iop_CmpLT64U
, mkexpr( exp_A
), mkexpr( exp_B
) );
4405 IRExpr
* frac_hi_eq
= binop( Iop_CmpEQ64
, mkexpr( frac_A_hi
),
4406 mkexpr( frac_B_hi
) );
4407 IRExpr
* frac_hi_gt
= binop( Iop_CmpLT64U
, mkexpr( frac_B_hi
),
4408 mkexpr( frac_A_hi
) );
4409 IRExpr
* frac_hi_lt
= binop( Iop_CmpLT64U
, mkexpr( frac_A_hi
),
4410 mkexpr( frac_B_hi
) );
4412 IRExpr
* frac_lo_gt
= binop( Iop_CmpLT64U
, mkexpr( frac_B_lo
),
4413 mkexpr( frac_A_lo
) );
4414 IRExpr
* frac_lo_lt
= binop( Iop_CmpLT64U
, mkexpr( frac_A_lo
),
4415 mkexpr( frac_B_lo
) );
4417 /* src_A and src_B both positive */
4418 IRExpr
*pos_cmp
= mkOR1( exp_gt
,
4421 mkAND1( frac_hi_eq
, frac_lo_gt
) )
4424 /* src_A and src_B both negative */
4425 IRExpr
*neg_cmp
= mkOR1( exp_lt
,
4428 mkAND1( frac_hi_eq
, frac_lo_lt
) )
4431 /* Need to check the case where one value is a positive
4432 * zero and the other value is a negative zero
4434 return mkAND1( mkNOT1( A_B_zero
),
4437 mkOR1( mkAND1( both_pos
, pos_cmp
),
4438 mkAND1( both_neg
, neg_cmp
) ) ) ) );
4441 /*-----------------------------------------------------------
4442 * Helpers for VX instructions that work on National decimal values,
4443 * Zoned decimal values and BCD values.
4445 *------------------------------------------------------------*/
4446 static IRExpr
* is_National_decimal (IRTemp src
)
4448 /* The src is a 128-bit value containing a sign code in half word 7
4449 * and seven digits in halfwords 0 to 6 (IBM numbering). A valid
4450 * national decimal value has the following:
4451 * - the sign code must be 0x002B (positive) or 0x002D (negative)
4452 * - the digits must be in the range 0x0030 to 0x0039
4455 IRExpr
* valid_pos_sign
;
4456 IRExpr
* valid_neg_sign
;
4457 IRTemp valid_num
[8];
4460 valid_pos_sign
= binop( Iop_CmpEQ64
,
4463 unop( Iop_V128to64
, mkexpr( src
) ) ),
4466 valid_neg_sign
= binop( Iop_CmpEQ64
,
4469 unop( Iop_V128to64
, mkexpr( src
) ) ),
4472 valid_num
[0] = newTemp( Ity_I1
);
4473 digit
[0] = newTemp( Ity_I64
);
4474 assign( valid_num
[0], mkU1( 1 ) ); // Assume true to start
4476 for(i
= 0; i
< 7; i
++) {
4477 valid_num
[i
+1] = newTemp( Ity_I1
);
4478 digit
[i
] = newTemp( Ity_I64
);
4479 assign( digit
[i
], binop( Iop_And64
,
4483 mkU8( (7-i
)*16 ) ) ),
4484 mkU64( 0xFFFF ) ) );
4486 assign( valid_num
[i
+1],
4487 mkAND1( mkexpr( valid_num
[i
] ),
4488 mkAND1( binop( Iop_CmpLE64U
,
4491 binop( Iop_CmpLE64U
,
4493 mkexpr( digit
[i
] ) ) ) ) );
4496 return mkAND1( mkOR1( valid_pos_sign
, valid_neg_sign
),
4497 mkexpr( valid_num
[7] ) );
4500 static IRExpr
* is_Zoned_decimal (IRTemp src
, UChar ps
)
4502 /* The src is a 128-bit value containing a sign code the least significant
4503 * two bytes. The upper pairs of bytes contain digits. A valid Zoned
4504 * decimal value has the following:
4505 * - the sign code must be between 0x0X to 0xFX inclusive (X - don't care)
4506 * - bits [0:3] of each digit must be equal to 0x3
4507 * - bits [4:7] of each digit must be between 0x0 and 0x9
4510 * Positive sign codes are: 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xA, 0xB
4511 * (note 0bX0XX XXXX is positive)
4513 * Negative sign codes are 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF
4514 * (note 0bX1XX XXXX is negative)
4516 * If ps = 1, then the sign code must be in the range 0xA to 0xF
4517 * Positive sign codes are: 0xA, 0xC, 0xE, 0xF
4519 * Negative sign codes are 0xB, 0xD
4521 Int i
, mask_hi
, mask_lo
;
4522 IRExpr
*valid_range
;
4523 IRTemp valid_num
[16];
4526 /* check the range of the sign value based on the value of ps */
4527 valid_range
= mkOR1(
4528 mkAND1( binop( Iop_CmpEQ64
,
4531 mkAND1( binop( Iop_CmpLE64U
,
4538 binop( Iop_CmpLE64U
,
4543 mkexpr( src
) ))))),
4548 valid_num
[0] = newTemp( Ity_I1
);
4549 assign( valid_num
[0], mkU1( 1) ); // Assume true to start
4559 for(i
= 0; i
< 15; i
++) {
4560 valid_num
[i
+1] = newTemp( Ity_I1
);
4561 digit
[i
] = newTemp( Ity_I64
);
4562 assign( digit
[i
], binop( Iop_And64
,
4566 mkU8( (15-i
)*8 ) ) ),
4569 assign( valid_num
[i
+1],
4570 mkAND1( mkexpr( valid_num
[i
] ),
4571 mkAND1( binop( Iop_CmpLE64U
,
4574 binop( Iop_CmpLE64U
,
4576 mkexpr( digit
[i
] ) ) ) ) );
4579 return mkAND1( valid_range
, mkexpr( valid_num
[15] ) );
4582 static IRExpr
* CmpGT128U ( IRExpr
*src1
, IRExpr
*src2
)
4584 /* Unsigend compare of two 128-bit values */
4585 IRExpr
*pos_upper_gt
, *pos_upper_eq
, *pos_lower_gt
;
4587 pos_upper_gt
= binop( Iop_CmpLT64U
,
4588 unop( Iop_V128HIto64
, src2
),
4589 unop( Iop_V128HIto64
, src1
) );
4590 pos_upper_eq
= binop( Iop_CmpEQ64
,
4591 unop( Iop_V128HIto64
, src1
),
4592 unop( Iop_V128HIto64
, src2
) );
4593 pos_lower_gt
= binop( Iop_CmpLT64U
,
4594 unop( Iop_V128to64
, src2
),
4595 unop( Iop_V128to64
, src1
) );
4596 return mkOR1( pos_upper_gt
,
4597 mkAND1( pos_upper_eq
,
4602 static IRExpr
* is_BCDstring128 ( const VexAbiInfo
* vbi
,
4603 UInt Signed
, IRExpr
*src
)
4606 IRTemp valid
= newTemp( Ity_I64
);
4608 /* The src is a 128-bit value containing a MAX_DIGITS BCD digits and
4609 * a sign. The upper bytes are BCD values between 0x0 and 0x9. The sign
4610 * byte is the least significant byte. This function returns 64-bit 1
4611 * value if sign and digits are valid, 0 otherwise.
4613 * This function was originally written using IR code. It has been
4614 * replaced with a clean helper due to the large amount of IR code
4615 * needed by this function.
4618 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4619 "is_BCDstring128_helper",
4620 fnptr_to_fnentry( vbi
, &is_BCDstring128_helper
),
4621 mkIRExprVec_3( mkU64( Signed
),
4622 unop( Iop_V128HIto64
, src
),
4623 unop( Iop_V128to64
, src
) ) ) );
4624 return mkexpr( valid
);
4627 static IRExpr
* BCDstring_zero (IRExpr
*src
)
4629 /* The src is a 128-bit value containing a BCD string. The function
4630 * returns a 1 if the BCD string values are all zero, 0 otherwise.
4632 IRTemp tsrc
= newTemp( Ity_V128
);
4636 return mkAND1( binop( Iop_CmpEQ64
,
4638 unop( Iop_V128HIto64
,
4643 mkexpr( tsrc
) ) ) );
4645 /* make this work in 32-bit mode */
4647 mkAND1( binop( Iop_CmpEQ32
,
4650 unop( Iop_V128HIto64
,
4651 mkexpr( tsrc
) ) ) ),
4655 unop( Iop_V128HIto64
,
4656 mkexpr( tsrc
) ) ) ) ),
4657 mkAND1( binop( Iop_CmpEQ32
,
4661 mkexpr( tsrc
) ) ) ),
4666 mkexpr( tsrc
) ) ) ) ) );
4670 static IRExpr
* check_BCD_round (IRExpr
*src
, IRTemp shift
)
4672 /* The src is a 128-bit value containing 31 BCD digits with the sign in
4673 * the least significant byte. The bytes are BCD values between 0x0 and 0x9.
4674 * This routine checks the BCD digit in position shift (counting from
4675 * the least significant digit). If the digit is greater then five,
4676 * a 1 is returned indicating the string needs to be rounded up,
4677 * otherwise, 0 is returned. The value of shift (I64) is the index of
4678 * the BCD digit times four bits.
4680 return binop( Iop_CmpLE64U
,
4686 unop( Iop_64to8
, mkexpr( shift
) ) ) ),
4690 static IRTemp
increment_BCDstring ( const VexAbiInfo
* vbi
,
4691 IRExpr
*src
, IRExpr
*carry_in
)
4693 /* The src is a 128-bit value containing 31 BCD digits with the sign in
4694 * the least significant byte. The bytes are BCD values between 0x0 and 0x9.
4695 * This function returns the BCD string incremented by 1.
4697 * Call a clean helper to do the computation as it requires a lot of
4698 * IR code to do this.
4700 * The helper function takes a 32-bit BCD string, in a 64-bit value, and
4701 * increments the string by the 32-bi carry in value.
4703 * The incremented value is returned in the lower 32-bits of the result.
4704 * The carry out is returned in bits [35:32] of the result. The
4705 * helper function will be called for each of the four 32-bit strings
4706 * that make up the src string passing the returned carry out to the
4709 IRTemp bcd_result
= newTemp( Ity_V128
);
4710 IRTemp bcd_result0
= newTemp( Ity_I64
);
4711 IRTemp bcd_result1
= newTemp( Ity_I64
);
4712 IRTemp bcd_result2
= newTemp( Ity_I64
);
4713 IRTemp bcd_result3
= newTemp( Ity_I64
);
4714 IRExpr
*bcd_string0
, *bcd_string1
, *bcd_string2
, *bcd_string3
;
4716 bcd_string0
= binop( Iop_And64
,
4717 mkU64( 0xFFFFFFFF ), unop( Iop_V128to64
, src
) );
4718 bcd_string1
= binop( Iop_Shr64
, unop( Iop_V128to64
, src
), mkU8( 32 ) );
4719 bcd_string2
= binop( Iop_And64
,
4720 mkU64( 0xFFFFFFFF ), unop( Iop_V128HIto64
, src
) );
4721 bcd_string3
= binop( Iop_Shr64
, unop( Iop_V128HIto64
, src
), mkU8( 32 ) );
4723 assign( bcd_result0
,
4724 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4725 "increment_BCDstring32_helper",
4726 fnptr_to_fnentry( vbi
,
4727 &increment_BCDstring32_helper
),
4728 mkIRExprVec_3( mkU64( True
/*Signed*/ ),
4730 binop( Iop_32HLto64
, mkU32( 0 ),
4733 assign( bcd_result1
,
4734 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4735 "increment_BCDstring32_helper",
4736 fnptr_to_fnentry( vbi
,
4737 &increment_BCDstring32_helper
),
4738 mkIRExprVec_3( mkU64( False
/*Unsigned*/ ),
4741 mkexpr( bcd_result0
),
4743 assign( bcd_result2
,
4744 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4745 "increment_BCDstring32_helper",
4746 fnptr_to_fnentry( vbi
,
4747 &increment_BCDstring32_helper
),
4748 mkIRExprVec_3( mkU64( False
/*Unsigned*/ ),
4751 mkexpr( bcd_result1
),
4753 assign( bcd_result3
,
4754 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4755 "increment_BCDstring32_helper",
4756 fnptr_to_fnentry( vbi
,
4757 &increment_BCDstring32_helper
),
4758 mkIRExprVec_3( mkU64( False
/*Unsigned*/ ),
4761 mkexpr( bcd_result2
),
4764 /* Put the 128-bit result together from the intermediate results. Remember
4765 * to mask out the carry out from the upper 32 bits of the results.
4768 binop( Iop_64HLtoV128
,
4771 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result2
) ),
4773 mkexpr (bcd_result3
), mkU8( 32 ) ) ),
4776 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result0
) ),
4778 mkexpr (bcd_result1
), mkU8( 32 ) ) ) ) );
4782 static IRExpr
* convert_to_zoned ( const VexAbiInfo
* vbi
,
4783 IRExpr
*src
, IRExpr
*upper_byte
)
4785 /* The function takes a V128 packed decimal value and returns
4786 * the value in zoned format. Note, the sign of the value is ignored.
4788 IRTemp result_low
= newTemp( Ity_I64
);
4789 IRTemp result_hi
= newTemp( Ity_I64
);
4790 IRTemp result
= newTemp( Ity_V128
);
4792 /* Since we can only return 64-bits from a clean helper, we will
4793 * have to get the lower and upper 64-bits separately.
4797 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4798 "convert_to_zoned_helper",
4799 fnptr_to_fnentry( vbi
, &convert_to_zoned_helper
),
4800 mkIRExprVec_4( unop( Iop_V128HIto64
, src
),
4801 unop( Iop_V128to64
, src
),
4806 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4807 "convert_to_zoned_helper",
4808 fnptr_to_fnentry( vbi
, &convert_to_zoned_helper
),
4809 mkIRExprVec_4( unop( Iop_V128HIto64
, src
),
4810 unop( Iop_V128to64
, src
),
4816 binop( Iop_64HLtoV128
, mkexpr( result_hi
), mkexpr( result_low
) ) );
4818 return mkexpr( result
);
4821 static IRExpr
* convert_to_national ( const VexAbiInfo
* vbi
, IRExpr
*src
) {
4822 /* The function takes 128-bit value which has a 64-bit packed decimal
4823 * value in the lower 64-bits of the source. The packed decimal is
4824 * converted to the national format via a clean helper. The clean
4825 * helper is used to to the large amount of IR code needed to do the
4826 * conversion. The helper returns the upper 64-bits of the 128-bit
4827 * result if return_upper != 0. Otherwise, the lower 64-bits of the
4828 * result is returned.
4830 IRTemp result_low
= newTemp( Ity_I64
);
4831 IRTemp result_hi
= newTemp( Ity_I64
);
4832 IRTemp result
= newTemp( Ity_V128
);
4834 /* Since we can only return 64-bits from a clean helper, we will
4835 * have to get the lower and upper 64-bits separately.
4839 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4840 "convert_to_national_helper",
4841 fnptr_to_fnentry( vbi
, &convert_to_national_helper
),
4842 mkIRExprVec_2( unop( Iop_V128to64
, src
),
4846 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4847 "convert_to_national_helper",
4848 fnptr_to_fnentry( vbi
, &convert_to_national_helper
),
4849 mkIRExprVec_2( unop( Iop_V128to64
, src
),
4853 binop( Iop_64HLtoV128
, mkexpr( result_hi
), mkexpr( result_low
) ) );
4855 return mkexpr( result
);
4858 static IRExpr
* convert_from_zoned ( const VexAbiInfo
* vbi
, IRExpr
*src
) {
4859 /* The function takes 128-bit zoned value and returns a signless 64-bit
4860 * packed decimal value in the lower 64-bits of the 128-bit result.
4862 IRTemp result
= newTemp( Ity_V128
);
4866 binop( Iop_64HLtoV128
,
4868 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4869 "convert_from_zoned_helper",
4870 fnptr_to_fnentry( vbi
,
4871 &convert_from_zoned_helper
),
4872 mkIRExprVec_2( unop( Iop_V128HIto64
,
4878 return mkexpr( result
);
4881 static IRExpr
* convert_from_national ( const VexAbiInfo
* vbi
, IRExpr
*src
) {
4882 /* The function takes 128-bit national value and returns a 64-bit
4883 * packed decimal value.
4885 IRTemp result
= newTemp( Ity_I64
);
4888 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4889 "convert_from_national_helper",
4890 fnptr_to_fnentry( vbi
,
4891 &convert_from_national_helper
),
4892 mkIRExprVec_2( unop( Iop_V128HIto64
,
4897 return mkexpr( result
);
4900 static IRExpr
* UNSIGNED_CMP_GT_V128 ( IRExpr
*vA
, IRExpr
*vB
) {
4901 /* This function does an unsigned compare of two V128 values. The
4902 * function is for use in 32-bit mode only as it is expensive. The
4903 * issue is that compares (GT, LT, EQ) are not supported for operands
4904 * larger then 32-bits when running in 32-bit mode. The function returns
4905 * a 1-bit expression, 1 for TRUE and 0 for FALSE.
4907 IRTemp vA_word0
= newTemp( Ity_I32
);
4908 IRTemp vA_word1
= newTemp( Ity_I32
);
4909 IRTemp vA_word2
= newTemp( Ity_I32
);
4910 IRTemp vA_word3
= newTemp( Ity_I32
);
4911 IRTemp vB_word0
= newTemp( Ity_I32
);
4912 IRTemp vB_word1
= newTemp( Ity_I32
);
4913 IRTemp vB_word2
= newTemp( Ity_I32
);
4914 IRTemp vB_word3
= newTemp( Ity_I32
);
4916 IRTemp eq_word1
= newTemp( Ity_I1
);
4917 IRTemp eq_word2
= newTemp( Ity_I1
);
4918 IRTemp eq_word3
= newTemp( Ity_I1
);
4921 IRExpr
*gt_word0
, *gt_word1
, *gt_word2
, *gt_word3
;
4922 IRExpr
*eq_word3_2
, *eq_word3_2_1
;
4923 IRTemp result
= newTemp( Ity_I1
);
4925 assign( vA_word0
, unop( Iop_64to32
, unop( Iop_V128to64
, vA
) ) );
4926 assign( vA_word1
, unop( Iop_64HIto32
, unop( Iop_V128to64
, vA
) ) );
4927 assign( vA_word2
, unop( Iop_64to32
, unop( Iop_V128HIto64
, vA
) ) );
4928 assign( vA_word3
, unop( Iop_64HIto32
, unop( Iop_V128HIto64
, vA
) ) );
4930 assign( vB_word0
, unop( Iop_64to32
, unop( Iop_V128to64
, vB
) ) );
4931 assign( vB_word1
, unop( Iop_64HIto32
, unop( Iop_V128to64
, vB
) ) );
4932 assign( vB_word2
, unop( Iop_64to32
, unop( Iop_V128HIto64
, vB
) ) );
4933 assign( vB_word3
, unop( Iop_64HIto32
, unop( Iop_V128HIto64
, vB
) ) );
4935 assign( eq_word3
, binop( Iop_CmpEQ32
, mkexpr( vA_word3
),
4936 mkexpr( vB_word3
) ) );
4937 assign( eq_word2
, binop( Iop_CmpEQ32
, mkexpr( vA_word2
),
4938 mkexpr( vB_word2
) ) );
4939 assign( eq_word1
, binop( Iop_CmpEQ32
, mkexpr( vA_word1
),
4940 mkexpr( vB_word1
) ) );
4942 gt_word3
= binop( Iop_CmpLT32U
, mkexpr( vB_word3
), mkexpr( vA_word3
) );
4943 gt_word2
= binop( Iop_CmpLT32U
, mkexpr( vB_word2
), mkexpr( vA_word2
) );
4944 gt_word1
= binop( Iop_CmpLT32U
, mkexpr( vB_word1
), mkexpr( vA_word1
) );
4945 gt_word0
= binop( Iop_CmpLT32U
, mkexpr( vB_word0
), mkexpr( vA_word0
) );
4947 eq_word3_2
= mkAND1( mkexpr( eq_word3
), mkexpr( eq_word2
) );
4948 eq_word3_2_1
= mkAND1( mkexpr( eq_word1
), eq_word3_2
);
4950 assign( result
, mkOR1(
4952 mkAND1( mkexpr( eq_word3
), gt_word2
) ),
4953 mkOR1( mkAND1( eq_word3_2
, gt_word1
),
4954 mkAND1( eq_word3_2_1
, gt_word0
) ) ) );
4955 return mkexpr( result
);
4958 /*------------------------------------------------------------*/
4959 /*--- FP Helpers ---*/
4960 /*------------------------------------------------------------*/
4962 /* Produce the 32-bit pattern corresponding to the supplied
4964 static UInt
float_to_bits ( Float f
)
4966 union { UInt i
; Float f
; } u
;
4967 vassert(4 == sizeof(UInt
));
4968 vassert(4 == sizeof(Float
));
4969 vassert(4 == sizeof(u
));
4974 static IRExpr
* dnorm_adj_Vector ( IRExpr
* src
)
4976 /* This function takes a vector of 32-bit floats. It does the required
4977 adjustment on denormalized values based on the setting of the
4980 The VSCR[NJ] bit controlls how subnormal (denormalized) results for
4981 vector floating point operations are handled. VSCR[NJ] is bit 17
4982 (bit 111 IBM numbering).
4984 VSCR[NJ] = 0 Denormalized values are handled as
4985 specified by Java and the IEEE standard.
4987 VSCR[NJ] = 1 If an element in a source VR contains a denormalized
4988 value, the value 0 is used instead. If an instruction
4989 causes an Underflow Exception, the corresponding element
4990 in the target VR is set to 0. In both cases the 0 has
4991 the same sign as the denormalized or underflowing value.
4992 Convert negative zero to positive zero.
4994 The ABI for LE requires VSCR[NJ] = 0. For BE mode, VSCR[NJ] = 1 by
4995 default. The PPC guest state is initialized to match the HW setup.
4997 IRTemp sign_bit_maskV128
= newTemp( Ity_V128
);
4998 IRTemp ones_maskV128
= newTemp( Ity_V128
);
4999 IRTemp clear_dnorm_maskV128
= newTemp( Ity_V128
);
5000 IRTemp adj_valueV128
= newTemp( Ity_V128
);
5001 IRTemp dnormV128
= newTemp( Ity_V128
);
5002 IRTemp zeroV128
= newTemp( Ity_V128
);
5003 IRTemp VSCR_NJ
= newTemp( Ity_I64
);
5004 IRTemp VSCR_NJ_mask
= newTemp( Ity_V128
);
5005 IRTemp resultV128
= newTemp( Ity_V128
);
5007 /* get the VSCR[NJ] bit */
5012 getGST( PPC_GST_VSCR
),
5015 assign ( VSCR_NJ_mask
, binop( Iop_64HLtoV128
,
5017 mkexpr( VSCR_NJ
) ) );
5019 /* Create the masks to do the rounding of dnorm values and absolute
5021 assign( dnormV128
, is_Denorm_Vector( Ity_I32
, src
) );
5022 assign( zeroV128
, is_Zero_Vector( Ity_I32
, src
) );
5024 /* If the value is dnorm, then we need to clear the significand and
5025 exponent but leave the sign bit. Put 1'x in elements that are not
5026 denormalized values. */
5027 assign( sign_bit_maskV128
, unop( Iop_Dup32x4
, mkU32( 0x80000000 ) ) );
5029 assign( clear_dnorm_maskV128
,
5032 mkexpr( dnormV128
),
5033 mkexpr( sign_bit_maskV128
) ),
5034 unop( Iop_NotV128
, mkexpr( dnormV128
) ) ) );
5036 assign( ones_maskV128
, mkV128( 0xFFFF ) );
5038 assign( adj_valueV128
, binop( Iop_AndV128
,
5039 mkexpr( clear_dnorm_maskV128
),
5042 mkexpr( ones_maskV128
) ) ) );
5044 /* If the VSCR[NJ] bit is 1, then clear the denormalized values,
5045 otherwise just return the input unchanged. */
5049 mkexpr( VSCR_NJ_mask
),
5050 mkexpr( adj_valueV128
) ),
5052 unop( Iop_NotV128
, mkexpr( VSCR_NJ_mask
) ),
5055 return mkexpr(resultV128
);
5058 /*------------------------------------------------------------*/
5059 /* Transactional memory helpers
5061 *------------------------------------------------------------*/
5063 static ULong
generate_TMreason( UInt failure_code
,
5069 ( (ULong
) 0) << (63-6) /* Failure code */
5070 | ( (ULong
) persistant
) << (63-7) /* Failure persistant */
5071 | ( (ULong
) 0) << (63-8) /* Disallowed */
5072 | ( (ULong
) nest_overflow
) << (63-9) /* Nesting Overflow */
5073 | ( (ULong
) 0) << (63-10) /* Footprint Overflow */
5074 | ( (ULong
) 0) << (63-11) /* Self-Induced Conflict */
5075 | ( (ULong
) 0) << (63-12) /* Non-Transactional Conflict */
5076 | ( (ULong
) 0) << (63-13) /* Transactional Conflict */
5077 | ( (ULong
) 0) << (63-14) /* Translation Invalidation Conflict */
5078 | ( (ULong
) 0) << (63-15) /* Implementation-specific */
5079 | ( (ULong
) 0) << (63-16) /* Instruction Fetch Conflict */
5080 | ( (ULong
) 0) << (63-30) /* Reserved */
5081 | ( (ULong
) 0) << (63-31) /* Abort */
5082 | ( (ULong
) 0) << (63-32) /* Suspend */
5083 | ( (ULong
) 0) << (63-33) /* Reserved */
5084 | ( (ULong
) 0) << (63-35) /* Privilege */
5085 | ( (ULong
) 0) << (63-36) /* Failure Summary */
5086 | ( (ULong
) tm_exact
) << (63-37) /* TFIAR Exact */
5087 | ( (ULong
) 0) << (63-38) /* ROT */
5088 | ( (ULong
) 0) << (63-51) /* Reserved */
5089 | ( (ULong
) 0) << (63-63); /* Transaction Level */
5094 static void storeTMfailure( Addr64 err_address
, ULong tm_reason
,
5095 Addr64 handler_address
)
5097 putGST( PPC_GST_TFIAR
, mkU64( err_address
) );
5098 putGST( PPC_GST_TEXASR
, mkU64( tm_reason
) );
5099 putGST( PPC_GST_TEXASRU
, mkU32( 0 ) );
5100 putGST( PPC_GST_TFHAR
, mkU64( handler_address
) );
5103 /*------------------------------------------------------------*/
5104 /*--- Integer Instruction Translation --- */
5105 /*------------------------------------------------------------*/
5108 Integer Arithmetic Instructions
5110 static Bool
dis_int_mult_add ( UInt theInstr
)
5113 UChar rD_addr
= ifieldRegDS( theInstr
);
5114 UChar rA_addr
= ifieldRegA( theInstr
);
5115 UChar rB_addr
= ifieldRegB( theInstr
);
5116 UChar rC_addr
= ifieldRegC( theInstr
);
5117 UInt opc2
= IFIELD( theInstr
, 0, 6 );
5118 IRType ty
= Ity_I64
;
5119 IRTemp rA
= newTemp( ty
);
5120 IRTemp rB
= newTemp( ty
);
5121 IRTemp rC
= newTemp( ty
);
5122 IRTemp rD
= newTemp( ty
);
5123 IRTemp tmpLo
= newTemp( Ity_I64
);
5124 IRTemp tmpHi
= newTemp( Ity_I64
);
5125 IRTemp tmp2Hi
= newTemp( Ity_I64
);
5126 IRTemp result
= newTemp( Ity_I128
);
5127 IRTemp resultLo
= newTemp( Ity_I64
);
5130 assign( rA
, getIReg( rA_addr
) );
5131 assign( rB
, getIReg( rB_addr
) );
5132 assign( rC
, getIReg( rC_addr
) );
5135 case 0x30: // maddhd multiply-add High doubleword signed
5136 DIP("maddhd r%u,r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
, rC_addr
);
5138 assign( result
, binop( Iop_MullS64
, mkexpr( rA
), mkexpr( rB
) ) );
5139 assign( tmpLo
, unop( Iop_128to64
, mkexpr( result
) ) );
5140 assign( tmpHi
, unop( Iop_128HIto64
, mkexpr( result
) ) );
5142 /* Multiply rA and rB then add rC. If the lower 32-bits of the result
5143 * is less then rC and the result rA * rB, a carry out of the lower 32
5144 * bits occurred and the upper 32 bits must be incremented by 1. Sign
5145 * extend rC and do the add to the upper 64 bits to handle the
5146 * negative case for rC.
5148 assign( resultLo
, binop( Iop_Add64
, mkexpr( tmpLo
), mkexpr( rC
) ) );
5149 assign( tmp2Hi
, binop( Iop_Add64
,
5155 mkU8( 63 ) ) ) ) ) );
5157 /* need to do calculation for the upper 32 bit result */
5158 carryout
= mkAND1( binop( Iop_CmpLT64U
,
5159 mkexpr( resultLo
), mkexpr( rC
) ),
5160 binop( Iop_CmpLT64U
,
5161 mkexpr( resultLo
), mkexpr( tmpLo
) ) );
5162 assign( rD
, binop( Iop_Add64
,
5164 unop( Iop_1Uto64
, carryout
) ) );
5167 case 0x31: // maddhdu multiply-add High doubleword unsigned
5168 DIP("maddhdu r%u,r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
, rC_addr
);
5170 assign( result
, binop( Iop_MullU64
, mkexpr( rA
), mkexpr( rB
) ) );
5171 assign( tmpLo
, unop( Iop_128to64
, mkexpr( result
) ) );
5172 assign( tmpHi
, unop( Iop_128HIto64
, mkexpr( result
) ) );
5174 /* Add rC, if the lower 32-bits of the result is less then rC and
5175 * tmpLo, a carry out of the lower 32 bits occurred. Upper 32 bits
5176 * must be incremented by 1.
5178 assign( resultLo
, binop( Iop_Add64
, mkexpr( tmpLo
), mkexpr( rC
) ) );
5180 /* need to do calculation for the upper 32 bit result */
5181 carryout
= mkAND1( binop( Iop_CmpLT64U
,
5182 mkexpr(resultLo
), mkexpr( rC
) ),
5183 binop( Iop_CmpLT64U
,
5184 mkexpr(resultLo
), mkexpr( tmpLo
) ) );
5185 assign( rD
, binop( Iop_Add64
,
5187 unop( Iop_1Uto64
, carryout
) ) );
5190 case 0x33: // maddld multiply-add Low doubleword
5191 DIP("maddld r%u,r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
, rC_addr
);
5193 assign( result
, binop( Iop_MullS64
, mkexpr( rA
), mkexpr( rB
) ) );
5194 assign( tmpLo
, unop( Iop_128to64
, mkexpr( result
) ) );
5195 assign( tmpHi
, unop( Iop_128HIto64
, mkexpr( result
) ) );
5197 assign( rD
, binop( Iop_Add64
, mkexpr( tmpLo
), mkexpr( rC
) ) );
5201 vex_printf("dis_int_mult(ppc): unrecognized instruction\n");
5205 putIReg( rD_addr
, mkexpr(rD
) );
5210 static Bool
dis_int_arith ( UInt theInstr
)
5212 /* D-Form, XO-Form */
5213 UChar opc1
= ifieldOPC(theInstr
);
5214 UChar rD_addr
= ifieldRegDS(theInstr
);
5215 UChar rA_addr
= ifieldRegA(theInstr
);
5216 UInt uimm16
= ifieldUIMM16(theInstr
);
5217 UChar rB_addr
= ifieldRegB(theInstr
);
5218 UChar flag_OE
= ifieldBIT10(theInstr
);
5219 UInt opc2
= ifieldOPClo9(theInstr
);
5220 UChar flag_rC
= ifieldBIT0(theInstr
);
5222 Long simm16
= extend_s_16to64(uimm16
);
5223 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
5224 IRTemp rA
= newTemp(ty
);
5225 IRTemp rB
= newTemp(ty
);
5226 IRTemp rD
= newTemp(ty
);
5230 assign( rA
, getIReg(rA_addr
) );
5231 assign( rB
, getIReg(rB_addr
) ); // XO-Form: rD, rA, rB
5235 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351
5236 DIP("addic r%u,r%u,%d\n", rD_addr
, rA_addr
, (Int
)simm16
);
5237 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
5238 mkSzExtendS16(ty
, uimm16
) ) );
5239 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADD
,
5240 mkexpr(rD
), mkexpr(rA
), mkSzExtendS16(ty
, uimm16
),
5241 mkSzImm(ty
, 0)/*old xer.ca, which is ignored*/ );
5244 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
5245 DIP("addic. r%u,r%u,%d\n", rD_addr
, rA_addr
, (Int
)simm16
);
5246 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
5247 mkSzExtendS16(ty
, uimm16
) ) );
5248 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADD
,
5249 mkexpr(rD
), mkexpr(rA
), mkSzExtendS16(ty
, uimm16
),
5250 mkSzImm(ty
, 0)/*old xer.ca, which is ignored*/ );
5251 do_rc
= True
; // Always record to CR
5255 case 0x0E: // addi (Add Immediate, PPC32 p350)
5256 // li rD,val == addi rD,0,val
5257 // la disp(rA) == addi rD,rA,disp
5258 if ( rA_addr
== 0 ) {
5259 DIP("li r%u,%d\n", rD_addr
, (Int
)simm16
);
5260 assign( rD
, mkSzExtendS16(ty
, uimm16
) );
5262 DIP("addi r%u,r%u,%d\n", rD_addr
, rA_addr
, (Int
)simm16
);
5263 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
5264 mkSzExtendS16(ty
, uimm16
) ) );
5268 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353)
5269 // lis rD,val == addis rD,0,val
5270 if ( rA_addr
== 0 ) {
5271 DIP("lis r%u,%d\n", rD_addr
, (Int
)simm16
);
5272 assign( rD
, mkSzExtendS32(ty
, uimm16
<< 16) );
5274 DIP("addis r%u,r%u,0x%x\n", rD_addr
, rA_addr
, (UInt
)simm16
);
5275 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
5276 mkSzExtendS32(ty
, uimm16
<< 16) ) );
5280 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490)
5281 DIP("mulli r%u,r%u,%d\n", rD_addr
, rA_addr
, (Int
)simm16
);
5283 assign( rD
, unop(Iop_128to64
,
5284 binop(Iop_MullS64
, mkexpr(rA
),
5285 mkSzExtendS16(ty
, uimm16
))) );
5287 assign( rD
, unop(Iop_64to32
,
5288 binop(Iop_MullS32
, mkexpr(rA
),
5289 mkSzExtendS16(ty
, uimm16
))) );
5292 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540)
5293 DIP("subfic r%u,r%u,%d\n", rD_addr
, rA_addr
, (Int
)simm16
);
5295 assign( rD
, binop( mkSzOp(ty
, Iop_Sub8
),
5296 mkSzExtendS16(ty
, uimm16
),
5298 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SUBFI
,
5299 mkexpr(rD
), mkexpr(rA
), mkSzExtendS16(ty
, uimm16
),
5300 mkSzImm(ty
, 0)/*old xer.ca, which is ignored*/ );
5305 do_rc
= True
; // All below record to CR
5308 case 0x10A: // add (Add, PPC32 p347)
5309 DIP("add%s%s r%u,r%u,r%u\n",
5310 flag_OE
? "o" : "", flag_rC
? ".":"",
5311 rD_addr
, rA_addr
, rB_addr
);
5312 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
5313 mkexpr(rA
), mkexpr(rB
) ) );
5315 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_ADD
,
5316 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5320 case 0x00A: // addc (Add Carrying, PPC32 p348)
5321 DIP("addc%s%s r%u,r%u,r%u\n",
5322 flag_OE
? "o" : "", flag_rC
? ".":"",
5323 rD_addr
, rA_addr
, rB_addr
);
5324 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
5325 mkexpr(rA
), mkexpr(rB
)) );
5326 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADD
,
5327 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
),
5328 mkSzImm(ty
, 0)/*old xer.ca, which is ignored*/ );
5330 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_ADD
,
5331 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5335 case 0x08A: { // adde (Add Extended, PPC32 p349)
5336 IRTemp old_xer_ca
= newTemp(ty
);
5337 DIP("adde%s%s r%u,r%u,r%u\n",
5338 flag_OE
? "o" : "", flag_rC
? ".":"",
5339 rD_addr
, rA_addr
, rB_addr
);
5340 // rD = rA + rB + XER[CA]
5341 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
5342 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
5343 binop( mkSzOp(ty
, Iop_Add8
),
5344 mkexpr(rB
), mkexpr(old_xer_ca
))) );
5345 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADDE
,
5346 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
),
5347 mkexpr(old_xer_ca
) );
5349 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_ADDE
,
5350 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5355 case 0xAA: {// addex (Add Extended alternate carry bit Z23-form)
5356 IRTemp old_xer_ov
= newTemp(ty
);
5357 DIP("addex r%u,r%u,r%u,%d\n", rD_addr
, rA_addr
, rB_addr
, (Int
)flag_OE
);
5358 assign( old_xer_ov
, mkWidenFrom32(ty
, getXER_OV_32(), False
) );
5359 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
5360 binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rB
),
5361 mkexpr(old_xer_ov
) ) ) );
5363 /* CY bit is same as OE bit */
5365 /* Exception, do not set SO bit and set OV from carry. */
5366 set_XER_OV_OV32_ADDEX( ty
, mkexpr(rD
), mkexpr(rA
), mkexpr(rB
),
5367 mkexpr(old_xer_ov
) );
5369 /* CY=1, 2 and 3 (AKA flag_OE) are reserved */
5370 vex_printf("addex instruction, CY = %d is reserved.\n", flag_OE
);
5371 vpanic("addex instruction\n");
5376 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354)
5377 IRTemp old_xer_ca
= newTemp(ty
);
5380 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
5383 DIP("addme%s%s r%u,r%u,r%u\n",
5384 flag_OE
? "o" : "", flag_rC
? ".":"",
5385 rD_addr
, rA_addr
, rB_addr
);
5386 // rD = rA + (-1) + XER[CA]
5387 // => Just another form of adde
5388 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
5389 min_one
= mkSzImm(ty
, (Long
)-1);
5390 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
5391 binop( mkSzOp(ty
, Iop_Add8
),
5392 min_one
, mkexpr(old_xer_ca
)) ));
5393 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADDE
,
5394 mkexpr(rD
), mkexpr(rA
), min_one
,
5395 mkexpr(old_xer_ca
) );
5397 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_ADDE
,
5398 mkexpr(rD
), mkexpr(rA
), min_one
);
5403 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355)
5404 IRTemp old_xer_ca
= newTemp(ty
);
5406 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
5409 DIP("addze%s%s r%u,r%u,r%u\n",
5410 flag_OE
? "o" : "", flag_rC
? ".":"",
5411 rD_addr
, rA_addr
, rB_addr
);
5412 // rD = rA + (0) + XER[CA]
5413 // => Just another form of adde
5414 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
5415 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
5416 mkexpr(rA
), mkexpr(old_xer_ca
)) );
5417 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADDE
,
5418 mkexpr(rD
), mkexpr(rA
), mkSzImm(ty
, 0),
5419 mkexpr(old_xer_ca
) );
5421 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_ADDE
,
5422 mkexpr(rD
), mkexpr(rA
), mkSzImm(ty
, 0) );
5427 case 0x1EB: // divw (Divide Word, PPC32 p388)
5428 DIP("divw%s%s r%u,r%u,r%u\n",
5429 flag_OE
? "o" : "", flag_rC
? ".":"",
5430 rD_addr
, rA_addr
, rB_addr
);
5433 XER settings are mode independent, and reflect the
5434 overflow of the low-order 32bit result
5435 CR0[LT|GT|EQ] are undefined if flag_rC && mode64
5437 /* rD[hi32] are undefined: setting them to sign of lo32
5438 - makes set_CR0 happy */
5439 IRExpr
* dividend
= mk64lo32Sto64( mkexpr(rA
) );
5440 IRExpr
* divisor
= mk64lo32Sto64( mkexpr(rB
) );
5441 assign( rD
, mk64lo32Uto64( binop(Iop_DivS64
, dividend
,
5444 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVW
,
5445 mkexpr(rD
), dividend
, divisor
);
5448 assign( rD
, binop(Iop_DivS32
, mkexpr(rA
), mkexpr(rB
)) );
5450 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVW
,
5451 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5455 if (0x8000_0000 / -1) or (x / 0)
5456 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
5457 => But _no_ exception raised. */
5460 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389)
5461 DIP("divwu%s%s r%u,r%u,r%u\n",
5462 flag_OE
? "o" : "", flag_rC
? ".":"",
5463 rD_addr
, rA_addr
, rB_addr
);
5466 XER settings are mode independent, and reflect the
5467 overflow of the low-order 32bit result
5468 CR0[LT|GT|EQ] are undefined if flag_rC && mode64
5470 IRExpr
* dividend
= mk64lo32Uto64( mkexpr(rA
) );
5471 IRExpr
* divisor
= mk64lo32Uto64( mkexpr(rB
) );
5472 assign( rD
, mk64lo32Uto64( binop(Iop_DivU64
, dividend
,
5475 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVWU
,
5476 mkexpr(rD
), dividend
, divisor
);
5479 assign( rD
, binop(Iop_DivU32
, mkexpr(rA
), mkexpr(rB
)) );
5481 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVWU
,
5482 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5485 /* Note: ditto comment divw, for (x / 0) */
5488 case 0x04B: // mulhw (Multiply High Word, PPC32 p488)
5490 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
5493 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC
? ".":"",
5494 rD_addr
, rA_addr
, rB_addr
);
5496 /* rD[hi32] are undefined: setting them to sign of lo32
5497 - makes set_CR0 happy */
5498 assign( rD
, binop(Iop_Sar64
,
5500 mk64lo32Sto64( mkexpr(rA
) ),
5501 mk64lo32Sto64( mkexpr(rB
) )),
5504 assign( rD
, unop(Iop_64HIto32
,
5506 mkexpr(rA
), mkexpr(rB
))) );
5510 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489)
5512 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
5515 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC
? ".":"",
5516 rD_addr
, rA_addr
, rB_addr
);
5518 /* rD[hi32] are undefined: setting them to sign of lo32
5519 - makes set_CR0 happy */
5520 assign( rD
, binop(Iop_Sar64
,
5522 mk64lo32Uto64( mkexpr(rA
) ),
5523 mk64lo32Uto64( mkexpr(rB
) ) ),
5526 assign( rD
, unop(Iop_64HIto32
,
5528 mkexpr(rA
), mkexpr(rB
))) );
5532 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491)
5533 DIP("mullw%s%s r%u,r%u,r%u\n",
5534 flag_OE
? "o" : "", flag_rC
? ".":"",
5535 rD_addr
, rA_addr
, rB_addr
);
5537 /* rD[hi32] are undefined: setting them to sign of lo32
5538 - set_XER_OV() and set_CR0() depend on this */
5539 IRExpr
*a
= unop(Iop_64to32
, mkexpr(rA
) );
5540 IRExpr
*b
= unop(Iop_64to32
, mkexpr(rB
) );
5541 assign( rD
, binop(Iop_MullS32
, a
, b
) );
5543 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_MULLW
,
5545 unop(Iop_32Uto64
, a
), unop(Iop_32Uto64
, b
) );
5548 assign( rD
, unop(Iop_64to32
,
5550 mkexpr(rA
), mkexpr(rB
))) );
5552 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_MULLW
,
5553 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5558 case 0x068: // neg (Negate, PPC32 p493)
5560 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
5563 DIP("neg%s%s r%u,r%u\n",
5564 flag_OE
? "o" : "", flag_rC
? ".":"",
5567 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
5568 unop( mkSzOp(ty
, Iop_Not8
), mkexpr(rA
) ),
5571 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_NEG
,
5572 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5576 case 0x028: // subf (Subtract From, PPC32 p537)
5577 DIP("subf%s%s r%u,r%u,r%u\n",
5578 flag_OE
? "o" : "", flag_rC
? ".":"",
5579 rD_addr
, rA_addr
, rB_addr
);
5581 assign( rD
, binop( mkSzOp(ty
, Iop_Sub8
),
5582 mkexpr(rB
), mkexpr(rA
)) );
5584 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_SUBF
,
5585 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5589 case 0x008: // subfc (Subtract from Carrying, PPC32 p538)
5590 DIP("subfc%s%s r%u,r%u,r%u\n",
5591 flag_OE
? "o" : "", flag_rC
? ".":"",
5592 rD_addr
, rA_addr
, rB_addr
);
5594 assign( rD
, binop( mkSzOp(ty
, Iop_Sub8
),
5595 mkexpr(rB
), mkexpr(rA
)) );
5596 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SUBFC
,
5597 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
),
5598 mkSzImm(ty
, 0)/*old xer.ca, which is ignored*/ );
5600 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_SUBFC
,
5601 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5605 case 0x088: {// subfe (Subtract from Extended, PPC32 p539)
5606 IRTemp old_xer_ca
= newTemp(ty
);
5607 DIP("subfe%s%s r%u,r%u,r%u\n",
5608 flag_OE
? "o" : "", flag_rC
? ".":"",
5609 rD_addr
, rA_addr
, rB_addr
);
5610 // rD = (log not)rA + rB + XER[CA]
5612 // rD = rB - rA - (XER[CA] ^ 1)
5613 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
5614 assign( rD
, binop( mkSzOp(ty
, Iop_Sub8
),
5615 binop( mkSzOp(ty
, Iop_Sub8
),
5616 mkexpr(rB
), mkexpr(rA
)),
5617 binop(mkSzOp(ty
, Iop_Xor8
),
5620 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SUBFE
,
5621 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
),
5622 mkexpr(old_xer_ca
) );
5624 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_SUBFE
,
5625 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5630 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541)
5631 IRTemp old_xer_ca
= newTemp(ty
);
5634 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
5637 DIP("subfme%s%s r%u,r%u\n",
5638 flag_OE
? "o" : "", flag_rC
? ".":"",
5640 // rD = (log not)rA + (-1) + XER[CA]
5641 // => Just another form of subfe
5642 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
5643 min_one
= mkSzImm(ty
, (Long
)-1);
5644 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
5645 unop( mkSzOp(ty
, Iop_Not8
), mkexpr(rA
)),
5646 binop( mkSzOp(ty
, Iop_Add8
),
5647 min_one
, mkexpr(old_xer_ca
))) );
5648 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SUBFE
,
5649 mkexpr(rD
), mkexpr(rA
), min_one
,
5650 mkexpr(old_xer_ca
) );
5652 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_SUBFE
,
5653 mkexpr(rD
), mkexpr(rA
), min_one
);
5658 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542)
5659 IRTemp old_xer_ca
= newTemp(ty
);
5661 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
5664 DIP("subfze%s%s r%u,r%u\n",
5665 flag_OE
? "o" : "", flag_rC
? ".":"",
5667 // rD = (log not)rA + (0) + XER[CA]
5668 // => Just another form of subfe
5669 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
5670 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
5671 unop( mkSzOp(ty
, Iop_Not8
),
5672 mkexpr(rA
)), mkexpr(old_xer_ca
)) );
5673 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SUBFE
,
5674 mkexpr(rD
), mkexpr(rA
), mkSzImm(ty
, 0),
5675 mkexpr(old_xer_ca
) );
5677 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_SUBFE
,
5678 mkexpr(rD
), mkexpr(rA
), mkSzImm(ty
, 0) );
5684 /* 64bit Arithmetic */
5685 case 0x49: // mulhd (Multiply High DWord, PPC64 p539)
5687 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
5690 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC
? ".":"",
5691 rD_addr
, rA_addr
, rB_addr
);
5692 assign( rD
, unop(Iop_128HIto64
,
5694 mkexpr(rA
), mkexpr(rB
))) );
5698 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540)
5700 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
5703 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC
? ".":"",
5704 rD_addr
, rA_addr
, rB_addr
);
5705 assign( rD
, unop(Iop_128HIto64
,
5707 mkexpr(rA
), mkexpr(rB
))) );
5710 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543)
5711 DIP("mulld%s%s r%u,r%u,r%u\n",
5712 flag_OE
? "o" : "", flag_rC
? ".":"",
5713 rD_addr
, rA_addr
, rB_addr
);
5714 assign( rD
, binop(Iop_Mul64
, mkexpr(rA
), mkexpr(rB
)) );
5716 set_XER_OV_64( PPCG_FLAG_OP_MULLD
,
5717 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5718 /* OV is set to 1 if product isn't representable.
5719 * In this case also need to set OV32 and SO to 1,
5720 * i.e. copy OV to OV32 and SO.
5727 case 0x1E9: // divd (Divide DWord, PPC64 p419)
5728 DIP("divd%s%s r%u,r%u,r%u\n",
5729 flag_OE
? "o" : "", flag_rC
? ".":"",
5730 rD_addr
, rA_addr
, rB_addr
);
5731 assign( rD
, binop(Iop_DivS64
, mkexpr(rA
), mkexpr(rB
)) );
5733 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVW
,
5734 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5738 if (0x8000_0000_0000_0000 / -1) or (x / 0)
5739 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
5740 => But _no_ exception raised. */
5742 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
5743 DIP("divdu%s%s r%u,r%u,r%u\n",
5744 flag_OE
? "o" : "", flag_rC
? ".":"",
5745 rD_addr
, rA_addr
, rB_addr
);
5746 assign( rD
, binop(Iop_DivU64
, mkexpr(rA
), mkexpr(rB
)) );
5748 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVWU
,
5749 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
5752 /* Note: ditto comment divd, for (x / 0) */
5754 case 0x18B: // divweu (Divide Word Extended Unsigned)
5757 * If (RA) >= (RB), or if an attempt is made to perform the division
5759 * then the contents of register RD are undefined as are (if Rc=1) the contents of
5760 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
5763 IRTemp res
= newTemp(Ity_I32
);
5764 IRExpr
* dividend
, * divisor
;
5765 DIP("divweu%s%s r%u,r%u,r%u\n",
5766 flag_OE
? "o" : "", flag_rC
? ".":"",
5767 rD_addr
, rA_addr
, rB_addr
);
5769 dividend
= unop( Iop_64to32
, mkexpr( rA
) );
5770 divisor
= unop( Iop_64to32
, mkexpr( rB
) );
5771 assign( res
, binop( Iop_DivU32E
, dividend
, divisor
) );
5772 assign( rD
, binop( Iop_32HLto64
, mkU32( 0 ), mkexpr( res
) ) );
5774 dividend
= mkexpr( rA
);
5775 divisor
= mkexpr( rB
);
5776 assign( res
, binop( Iop_DivU32E
, dividend
, divisor
) );
5777 assign( rD
, mkexpr( res
) );
5781 set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWEU
,
5782 mkexpr(res
), dividend
, divisor
);
5788 case 0x1AB: // divwe (Divide Word Extended)
5791 * If the quotient cannot be represented in 32 bits, or if an
5792 * attempt is made to perform the division
5794 * then the contents of register RD are undefined as are (if
5795 * Rc=1) the contents of the LT, GT, and EQ bits of CR
5796 * Field 0. In these cases, if OE=1 then OV is set to 1.
5799 IRTemp res
= newTemp(Ity_I32
);
5800 IRExpr
* dividend
, * divisor
;
5801 DIP("divwe%s%s r%u,r%u,r%u\n",
5802 flag_OE
? "o" : "", flag_rC
? ".":"",
5803 rD_addr
, rA_addr
, rB_addr
);
5805 dividend
= unop( Iop_64to32
, mkexpr( rA
) );
5806 divisor
= unop( Iop_64to32
, mkexpr( rB
) );
5807 assign( res
, binop( Iop_DivS32E
, dividend
, divisor
) );
5808 assign( rD
, binop( Iop_32HLto64
, mkU32( 0 ), mkexpr( res
) ) );
5810 dividend
= mkexpr( rA
);
5811 divisor
= mkexpr( rB
);
5812 assign( res
, binop( Iop_DivS32E
, dividend
, divisor
) );
5813 assign( rD
, mkexpr( res
) );
5817 set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWE
,
5818 mkexpr(res
), dividend
, divisor
);
5825 case 0x1A9: // divde (Divide Doubleword Extended)
5827 * If the quotient cannot be represented in 64 bits, or if an
5828 * attempt is made to perform the division
5830 * then the contents of register RD are undefined as are (if
5831 * Rc=1) the contents of the LT, GT, and EQ bits of CR
5832 * Field 0. In these cases, if OE=1 then OV is set to 1.
5834 DIP("divde%s%s r%u,r%u,r%u\n",
5835 flag_OE
? "o" : "", flag_rC
? ".":"",
5836 rD_addr
, rA_addr
, rB_addr
);
5837 assign( rD
, binop(Iop_DivS64E
, mkexpr(rA
), mkexpr(rB
)) );
5839 set_XER_OV_64( PPCG_FLAG_OP_DIVDE
, mkexpr( rD
),
5840 mkexpr( rA
), mkexpr( rB
) );
5846 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned)
5847 // Same CR and OV rules as given for divweu above
5848 DIP("divdeu%s%s r%u,r%u,r%u\n",
5849 flag_OE
? "o" : "", flag_rC
? ".":"",
5850 rD_addr
, rA_addr
, rB_addr
);
5851 assign( rD
, binop(Iop_DivU64E
, mkexpr(rA
), mkexpr(rB
)) );
5853 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU
, mkexpr( rD
),
5854 mkexpr( rA
), mkexpr( rB
) );
5861 vex_printf("dis_int_arith(ppc)(opc2)\n");
5867 vex_printf("dis_int_arith(ppc)(opc1)\n");
5871 putIReg( rD_addr
, mkexpr(rD
) );
5873 if (do_rc
&& flag_rC
) {
5874 set_CR0( mkexpr(rD
) );
5879 static Bool
dis_modulo_int ( UInt theInstr
)
5882 UChar opc1
= ifieldOPC( theInstr
);
5883 UInt opc2
= ifieldOPClo10( theInstr
);
5884 UChar rA_addr
= ifieldRegA( theInstr
);
5885 UChar rB_addr
= ifieldRegB( theInstr
);
5886 UChar rD_addr
= ifieldRegDS( theInstr
);
5887 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
5888 IRTemp rD
= newTemp( ty
);
5894 case 0x109: // modud Modulo Unsigned Double Word
5896 IRTemp rA
= newTemp( Ity_I64
);
5897 IRTemp rB
= newTemp( Ity_I64
);
5898 IRTemp quotient
= newTemp( Ity_I64
);
5899 IRTemp quotientTimesDivisor
= newTemp( Ity_I64
);
5900 IRTemp remainder
= newTemp( Ity_I64
);
5901 IRTemp rB_0
= newTemp( Ity_I64
); /* all 1's if rB = 0 */
5903 DIP("modud r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
5905 assign( rA
, getIReg( rA_addr
) );
5906 assign( rB
, getIReg( rB_addr
) );
5909 binop( Iop_DivU64
, mkexpr( rA
), mkexpr( rB
) ) );
5911 assign( quotientTimesDivisor
,
5919 mkexpr( quotientTimesDivisor
) ) );
5921 /* Need to match the HW for these special cases
5922 * rB = 0 result all zeros
5924 assign( rB_0
, unop( Iop_1Sto64
,
5929 assign (rD
, binop( Iop_And64
,
5930 unop( Iop_Not64
, mkexpr( rB_0
) ),
5931 mkexpr( remainder
) ) );
5935 case 0x10B: // moduw Modulo Unsigned Word
5937 IRTemp quotient
= newTemp( Ity_I32
);
5938 IRTemp quotientTimesDivisor
= newTemp( Ity_I32
);
5939 IRTemp remainder
= newTemp( Ity_I32
);
5941 IRTemp rA
= newTemp( Ity_I32
);
5942 IRTemp rB
= newTemp( Ity_I32
);
5943 IRTemp rB_0
= newTemp( Ity_I32
); /* all 1's if rB = 0 */
5945 DIP("moduw r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
5947 if ( ty
== Ity_I64
) {
5948 /* rA and rB are 32 bit values in bits 32:63 of the
5951 assign( rA
, unop( Iop_64to32
, getIReg( rA_addr
) ) );
5952 assign( rB
, unop( Iop_64to32
, getIReg( rB_addr
) ) );
5955 assign( rA
, getIReg( rA_addr
) );
5956 assign( rB
, getIReg( rB_addr
) );
5960 binop( Iop_DivU32
, mkexpr( rA
), mkexpr( rB
) ) );
5962 assign( quotientTimesDivisor
,
5971 mkexpr( quotientTimesDivisor
) ) );
5973 /* Need to match the HW for these special cases
5974 * rB = 0 result all zeros
5976 assign( rB_0
, unop( Iop_1Sto32
,
5981 assign (rD
, binop( Iop_32HLto64
,
5984 unop( Iop_Not32
, mkexpr( rB_0
) ),
5985 mkexpr( remainder
) ) ) );
5989 case 0x21A: // cnttzw, cnttzw. Count Trailing Zero Word
5991 /* Note cnttzw RA, RS - RA is dest, RS is source. But the
5992 * order of the operands in theInst is opc1 RS RA opc2 which has
5993 * the operand fields backwards to what the standard order.
5995 UChar rA_address
= ifieldRegA(theInstr
);
5996 UChar rS_address
= ifieldRegDS(theInstr
);
5997 IRTemp rA
= newTemp(Ity_I64
);
5998 IRTemp rS
= newTemp(Ity_I64
);
5999 UChar flag_rC
= ifieldBIT0(theInstr
);
6000 IRTemp result
= newTemp(Ity_I32
);
6002 DIP("cnttzw%s r%u,r%u\n", flag_rC
? "." : "",
6003 rA_address
, rS_address
);
6005 assign( rS
, getIReg( rS_address
) );
6006 assign( result
, unop( Iop_CtzNat32
,
6007 unop( Iop_64to32
, mkexpr( rS
) ) ) );
6008 assign( rA
, binop( Iop_32HLto64
, mkU32( 0 ), mkexpr( result
) ) );
6011 set_CR0( mkexpr( rA
) );
6013 putIReg( rA_address
, mkexpr( rA
) );
6015 return True
; /* Return here since this inst is not consistent
6016 * with the other instructions
6021 case 0x23A: // cnttzd, cnttzd. Count Trailing Zero Double word
6023 /* Note cnttzd RA, RS - RA is dest, RS is source. But the
6024 * order of the operands in theInst is opc1 RS RA opc2 which has
6025 * the operand order listed backwards to what is standard.
6027 UChar rA_address
= ifieldRegA(theInstr
);
6028 UChar rS_address
= ifieldRegDS(theInstr
);
6029 IRTemp rA
= newTemp(Ity_I64
);
6030 IRTemp rS
= newTemp(Ity_I64
);
6031 UChar flag_rC
= ifieldBIT0(theInstr
);
6033 DIP("cnttzd%s r%u,r%u\n", flag_rC
? "." : "",
6034 rA_address
, rS_address
);
6036 assign( rS
, getIReg( rS_address
) );
6037 assign( rA
, unop( Iop_CtzNat64
, mkexpr( rS
) ) );
6040 set_CR0( mkexpr( rA
) );
6042 putIReg( rA_address
, mkexpr( rA
) );
6044 return True
; /* Return here since this inst is not consistent
6045 * with the other instructions
6050 case 0x309: // modsd Modulo Signed Double Word
6052 IRTemp rA
= newTemp( Ity_I64
);
6053 IRTemp rB
= newTemp( Ity_I64
);
6054 IRTemp rA2_63
= newTemp( Ity_I64
); /* all 1's if rA != -2^63 */
6055 IRTemp rB_0
= newTemp( Ity_I1
); /* 1 if rB = 0 */
6056 IRTemp rB_1
= newTemp( Ity_I1
); /* 1 if rB = -1 */
6057 IRTemp rA_1
= newTemp( Ity_I1
); /* 1 if rA = -1 */
6058 IRTemp resultis0
= newTemp( Ity_I64
);
6059 IRTemp resultisF
= newTemp( Ity_I64
);
6060 IRTemp quotient
= newTemp( Ity_I64
);
6061 IRTemp quotientTimesDivisor
= newTemp( Ity_I64
);
6062 IRTemp remainder
= newTemp( Ity_I64
);
6063 IRTemp tmp
= newTemp( Ity_I64
);
6065 DIP("modsd r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
6067 assign( rA
, getIReg( rA_addr
) );
6068 assign( rB
, getIReg( rB_addr
) );
6070 assign( rA2_63
, unop ( Iop_1Sto64
,
6073 mkU64( 0x8000000000000000 ) ) ) );
6074 assign( rB_0
, binop( Iop_CmpEQ64
,
6078 assign( rB_1
, binop( Iop_CmpEQ64
,
6080 mkU64( 0xFFFFFFFFFFFFFFFF ) ) );
6082 assign( rA_1
, binop( Iop_CmpEQ64
,
6084 mkU64( 0xFFFFFFFFFFFFFFFF ) ) );
6086 /* Need to match the HW for these special cases
6087 * rA = -2^31 and rB = -1 result all zeros
6088 * rA = -1 and rB = -1 result all zeros
6089 * rA = -1 and (rB != -1 AND rB != 0) result all 1's
6094 unop ( Iop_1Sto64
, mkexpr( rB_1
) ) ) );
6097 unop( Iop_1Sto64
, mkexpr( rA_1
) ),
6100 unop( Iop_1Sto64
, mkexpr( rB_0
) ) ),
6102 unop( Iop_1Sto64
, mkexpr( rB_1
) ) )
6105 /* The following remainder computation works as long as
6106 * rA != -2^63 and rB != -1.
6109 binop( Iop_DivS64
, mkexpr( rA
), mkexpr( rB
) ) );
6111 assign( quotientTimesDivisor
,
6119 mkexpr( quotientTimesDivisor
) ) );
6121 assign( tmp
, binop( Iop_And64
,
6122 mkexpr( remainder
),
6124 mkexpr( resultis0
) ) ) );
6126 assign( rD
, binop( Iop_Or64
,
6129 mkexpr( resultisF
) ),
6131 mkexpr( resultisF
) ) );
6134 case 0x30B: // modsw Modulo Signed Word
6136 IRTemp rA
= newTemp( Ity_I32
);
6137 IRTemp rB
= newTemp( Ity_I32
);
6138 IRTemp rA2_32
= newTemp( Ity_I32
); /* all 1's if rA = -2^32 */
6139 IRTemp rB_0
= newTemp( Ity_I1
); /* 1 if rB = 0 */
6140 IRTemp rB_1
= newTemp( Ity_I1
); /* 1 if rB = -1 */
6141 IRTemp rA_1
= newTemp( Ity_I1
); /* 1 if rA = -1 */
6142 IRTemp resultis0
= newTemp( Ity_I32
);
6143 IRTemp resultisF
= newTemp( Ity_I64
);
6144 IRTemp quotient
= newTemp( Ity_I32
);
6145 IRTemp quotientTimesDivisor
= newTemp( Ity_I32
);
6146 IRTemp remainder
= newTemp( Ity_I32
);
6147 IRTemp tmp
= newTemp( Ity_I64
);
6149 DIP("modsw r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
6151 if ( ty
== Ity_I64
) {
6152 /* rA and rB are 32 bit values in bits 32:63 of the
6155 assign( rA
, unop(Iop_64to32
, getIReg(rA_addr
) ) );
6156 assign( rB
, unop(Iop_64to32
, getIReg(rB_addr
) ) );
6159 assign( rA
, getIReg(rA_addr
) );
6160 assign( rB
, getIReg(rB_addr
) );
6163 assign( rA2_32
, unop( Iop_1Sto32
,
6166 mkU32( 0x80000000 ) ) ) );
6167 /* If the divisor is zero, then the result is undefined.
6168 * However, we will make the result be zero to match what
6169 * the hardware does.
6171 assign( rB_0
, binop( Iop_CmpEQ32
,
6175 assign( rB_1
, binop( Iop_CmpEQ32
,
6177 mkU32( 0xFFFFFFFF ) ) );
6179 assign( rA_1
, binop( Iop_CmpEQ32
,
6181 mkU32( 0xFFFFFFFF ) ) );
6183 /* Need to match the HW for these special cases
6184 * rA = -2^31 and rB = -1 result all zeros
6185 * rA = -1 and rB = -1 result all zeros
6186 * rA = -1 and (rB != -1 AND rB != 0) result all 1's
6194 mkexpr( rB_1
) ) ) ),
6196 unop( Iop_1Sto32
, mkexpr( rA_1
) ),
6197 unop( Iop_1Sto32
, mkexpr( rB_1
) ) ) ) );
6200 unop( Iop_1Sto64
, mkexpr( rA_1
) ),
6203 unop( Iop_1Sto64
, mkexpr( rB_0
) ) ),
6205 unop( Iop_1Sto64
, mkexpr( rB_1
) ) )
6208 /* The following remainder computation works as long as
6209 * rA != -2^31 and rB != -1.
6212 binop( Iop_DivS32
, mkexpr( rA
), mkexpr( rB
) ) );
6214 assign( quotientTimesDivisor
,
6223 mkexpr( quotientTimesDivisor
) ) );
6225 assign( tmp
, binop( Iop_32HLto64
,
6228 mkexpr( remainder
),
6230 mkexpr( resultis0
) ) ) ) );
6232 assign( rD
, binop( Iop_Or64
,
6235 mkexpr( resultisF
) ),
6237 mkexpr( resultisF
) ) );
6242 vex_printf("dis_modulo_int(ppc)(opc2)\n");
6248 vex_printf("dis_modulo_int(ppc)(opc1)\n");
6252 putIReg( rD_addr
, mkexpr( rD
) );
6259 Byte Compare Instructions
6261 static Bool
dis_byte_cmp ( UInt theInstr
)
6264 UChar opc1
= ifieldOPC(theInstr
);
6265 UInt opc2
= ifieldOPClo10(theInstr
);
6266 UChar rA_addr
= ifieldRegA(theInstr
);
6267 UChar rB_addr
= ifieldRegB(theInstr
);
6268 IRTemp rA
= newTemp(Ity_I64
);
6269 IRTemp rB
= newTemp(Ity_I64
);
6270 UChar L
= toUChar( IFIELD( theInstr
, 21, 1 ) );
6271 UChar BF
= toUChar( IFIELD( theInstr
, 23, 3 ) );
6273 assign( rA
, getIReg(rA_addr
) );
6274 assign( rB
, getIReg(rB_addr
) );
6277 vex_printf("dis_byte_cmp(ppc)(opc1)\n");
6282 case 0xc0: // cmprb (Compare Ranged Byte)
6285 IRExpr
*hi_1
, *lo_1
, *hi_2
, *lo_2
;
6286 IRExpr
*inrange_1
, *inrange_2
;
6288 DIP("cmprb %u,%u,r%u,r%u\n", BF
, L
, rA_addr
, rB_addr
);
6290 hi_1
= binop( Iop_Shr64
,
6293 mkU64( 0xFF000000 ) ),
6295 lo_1
= binop( Iop_Shr64
,
6298 mkU64( 0xFF0000 ) ) ,
6300 hi_2
= binop( Iop_Shr64
,
6305 lo_2
= binop( Iop_And64
,
6308 value
= binop( Iop_And64
,
6312 inrange_1
= mkAND1( binop( Iop_CmpLE64U
, value
, hi_1
),
6313 mkNOT1( binop( Iop_CmpLT64U
, value
, lo_1
) ) );
6314 inrange_2
= mkAND1( binop( Iop_CmpLE64U
, value
, hi_2
),
6315 mkNOT1( binop( Iop_CmpLT64U
, value
, lo_2
) ) );
6317 putGST_field( PPC_GST_CR
,
6320 unop( Iop_1Uto32
, inrange_2
),
6323 unop( Iop_1Uto32
, inrange_1
) ) ),
6329 case 0xE0: // cmpeqb (Compare Equal Byte)
6335 DIP("cmpeqb %u,r%u,r%u\n", BF
, rA_addr
, rB_addr
);
6337 value
= binop( Iop_And64
,
6341 tmp
[0] = newTemp(Ity_I32
);
6342 assign( tmp
[0], mkU32( 0 ) );
6344 for(i
= 0; i
< 8; i
++) {
6345 tmp
[i
+1] = newTemp(Ity_I32
);
6346 assign( tmp
[i
+1], binop( Iop_Or32
,
6354 mkU64( 0xFF ) ) ) ),
6355 mkexpr( tmp
[i
] ) ) );
6358 putGST_field( PPC_GST_CR
,
6361 mkNOT1( binop( Iop_CmpEQ32
,
6370 vex_printf("dis_byte_cmp(ppc)(opc2)\n");
6377 * Integer Miscellaneous instructions
6379 static Bool
dis_int_misc ( UInt theInstr
)
6381 Int wc
= IFIELD(theInstr
, 21, 2);
6382 UChar opc1
= ifieldOPC(theInstr
);
6383 UInt opc2
= ifieldOPClo10(theInstr
);
6385 if ( opc1
!= 0x1F ) {
6386 vex_printf("dis_modulo_int(ppc)(opc1)\n");
6391 case 0x01E: // wait, (X-from)
6392 DIP("wait %d\n", wc
);
6394 /* The wait instruction causes instruction fetching and execution
6395 * to be suspended. Instruction fetching and execution are resumed
6396 * when the events specified by the WC field occur.
6398 * 0b00 Resume instruction fetching and execution when an
6399 * exception or an event-based branch exception occurs,
6400 * or a resume signal from the platform is recieved.
6404 * For our purposes, we will just assume the contition is always
6405 * immediately satisfied.
6409 vex_printf("dis_int_misc(ppc)(opc2)\n");
6417 Integer Compare Instructions
6419 static Bool
dis_int_cmp ( UInt theInstr
)
6421 /* D-Form, X-Form */
6422 UChar opc1
= ifieldOPC(theInstr
);
6423 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
6424 UChar b22
= toUChar( IFIELD( theInstr
, 22, 1 ) );
6425 UChar flag_L
= toUChar( IFIELD( theInstr
, 21, 1 ) );
6426 UChar rA_addr
= ifieldRegA(theInstr
);
6427 UInt uimm16
= ifieldUIMM16(theInstr
);
6428 UChar rB_addr
= ifieldRegB(theInstr
);
6429 UInt opc2
= ifieldOPClo10(theInstr
);
6430 UChar b0
= ifieldBIT0(theInstr
);
6432 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
6433 IRExpr
*a
= getIReg(rA_addr
);
6436 if (!mode64
&& flag_L
==1) { // L==1 invalid for 32 bit.
6437 vex_printf("dis_int_cmp(ppc)(flag_L)\n");
6441 if (( b22
!= 0 ) && ( opc2
!= 0x080 ) ) { // setb case exception
6442 vex_printf("dis_int_cmp(ppc)(b22)\n");
6447 case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
6448 DIP("cmpi cr%u,%u,r%u,%d\n", crfD
, flag_L
, rA_addr
,
6449 (Int
)extend_s_16to32(uimm16
));
6450 b
= mkSzExtendS16( ty
, uimm16
);
6452 putCR321(crfD
, unop(Iop_64to8
, binop(Iop_CmpORD64S
, a
, b
)));
6454 a
= mkNarrowTo32( ty
, a
);
6455 b
= mkNarrowTo32( ty
, b
);
6456 putCR321(crfD
, unop(Iop_32to8
, binop(Iop_CmpORD32S
, a
, b
)));
6458 putCR0( crfD
, getXER_SO() );
6461 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
6462 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD
, flag_L
, rA_addr
, uimm16
);
6463 b
= mkSzImm( ty
, uimm16
);
6465 putCR321(crfD
, unop(Iop_64to8
, binop(Iop_CmpORD64U
, a
, b
)));
6467 a
= mkNarrowTo32( ty
, a
);
6468 b
= mkNarrowTo32( ty
, b
);
6469 putCR321(crfD
, unop(Iop_32to8
, binop(Iop_CmpORD32U
, a
, b
)));
6471 putCR0( crfD
, getXER_SO() );
6477 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
6480 b
= getIReg(rB_addr
);
6483 case 0x000: // cmp (Compare, PPC32 p367)
6484 DIP("cmp cr%u,%u,r%u,r%u\n", crfD
, flag_L
, rA_addr
, rB_addr
);
6485 /* Comparing a reg with itself produces a result which
6486 doesn't depend on the contents of the reg. Therefore
6487 remove the false dependency, which has been known to cause
6488 memcheck to produce false errors. */
6489 if (rA_addr
== rB_addr
)
6490 a
= b
= typeOfIRExpr(irsb
->tyenv
,a
) == Ity_I64
6491 ? mkU64(0) : mkU32(0);
6493 putCR321(crfD
, unop(Iop_64to8
, binop(Iop_CmpORD64S
, a
, b
)));
6495 a
= mkNarrowTo32( ty
, a
);
6496 b
= mkNarrowTo32( ty
, b
);
6497 putCR321(crfD
, unop(Iop_32to8
,binop(Iop_CmpORD32S
, a
, b
)));
6499 putCR0( crfD
, getXER_SO() );
6502 case 0x020: // cmpl (Compare Logical, PPC32 p369)
6503 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD
, flag_L
, rA_addr
, rB_addr
);
6504 /* Comparing a reg with itself produces a result which
6505 doesn't depend on the contents of the reg. Therefore
6506 remove the false dependency, which has been known to cause
6507 memcheck to produce false errors. */
6508 if (rA_addr
== rB_addr
)
6509 a
= b
= typeOfIRExpr(irsb
->tyenv
,a
) == Ity_I64
6510 ? mkU64(0) : mkU32(0);
6512 putCR321(crfD
, unop(Iop_64to8
, binop(Iop_CmpORD64U
, a
, b
)));
6514 a
= mkNarrowTo32( ty
, a
);
6515 b
= mkNarrowTo32( ty
, b
);
6516 putCR321(crfD
, unop(Iop_32to8
, binop(Iop_CmpORD32U
, a
, b
)));
6518 putCR0( crfD
, getXER_SO() );
6521 case 0x080: // setb (Set Boolean)
6523 UChar rT_addr
= ifieldRegDS(theInstr
);
6524 Int bfa
= IFIELD(theInstr
, 18, 3);
6525 IRTemp cr
= newTemp(Ity_I32
);
6526 IRTemp cr0
= newTemp(Ity_I32
);
6527 IRTemp cr1
= newTemp(Ity_I32
);
6528 IRTemp result
= newTemp(Ity_I64
);
6530 DIP("setb r%u,%d\n", rT_addr
, bfa
);
6532 /* Fetch the entire condition code value */
6533 assign( cr
, getGST( PPC_GST_CR
) );
6535 /* Get bit zero (IBM numbering) of the CR field specified
6538 assign( cr0
, binop( Iop_And32
,
6541 mkU8( (7-bfa
)*4 ) ),
6543 assign( cr1
, binop( Iop_And32
,
6546 mkU8( (7-bfa
)*4 ) ),
6548 assign( result
, binop( Iop_Or64
,
6553 binop( Iop_32HLto64
,
6558 mkU32( 0x4 ) ) ) ) ) );
6559 if ( ty
== Ity_I64
)
6560 putIReg( rT_addr
, mkexpr( result
) );
6562 putIReg( rT_addr
, unop( Iop_64to32
, mkexpr(result
) ) );
6566 vex_printf("dis_int_cmp(ppc)(opc2)\n");
6572 vex_printf("dis_int_cmp(ppc)(opc1)\n");
6581 Integer Logical Instructions
6583 static Bool
dis_int_logic ( UInt theInstr
)
6585 /* D-Form, X-Form */
6586 UChar opc1
= ifieldOPC(theInstr
);
6587 UChar rS_addr
= ifieldRegDS(theInstr
);
6588 UChar rA_addr
= ifieldRegA(theInstr
);
6589 UInt uimm16
= ifieldUIMM16(theInstr
);
6590 UChar rB_addr
= ifieldRegB(theInstr
);
6591 UInt opc2
= ifieldOPClo10(theInstr
);
6592 UChar flag_rC
= ifieldBIT0(theInstr
);
6594 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
6595 IRTemp rS
= newTemp(ty
);
6596 IRTemp rA
= newTemp(ty
);
6597 IRTemp rB
= newTemp(ty
);
6600 assign( rS
, getIReg(rS_addr
) );
6601 assign( rB
, getIReg(rB_addr
) );
6604 case 0x1C: // andi. (AND Immediate, PPC32 p358)
6605 DIP("andi. r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
6606 assign( rA
, binop( mkSzOp(ty
, Iop_And8
), mkexpr(rS
),
6607 mkSzImm(ty
, uimm16
)) );
6608 do_rc
= True
; // Always record to CR
6612 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
6613 DIP("andis r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
6614 assign( rA
, binop( mkSzOp(ty
, Iop_And8
), mkexpr(rS
),
6615 mkSzImm(ty
, uimm16
<< 16)) );
6616 do_rc
= True
; // Always record to CR
6620 case 0x18: // ori (OR Immediate, PPC32 p497)
6621 DIP("ori r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
6622 assign( rA
, binop( mkSzOp(ty
, Iop_Or8
), mkexpr(rS
),
6623 mkSzImm(ty
, uimm16
)) );
6626 case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
6627 DIP("oris r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
6628 assign( rA
, binop( mkSzOp(ty
, Iop_Or8
), mkexpr(rS
),
6629 mkSzImm(ty
, uimm16
<< 16)) );
6632 case 0x1A: // xori (XOR Immediate, PPC32 p550)
6633 DIP("xori r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
6634 assign( rA
, binop( mkSzOp(ty
, Iop_Xor8
), mkexpr(rS
),
6635 mkSzImm(ty
, uimm16
)) );
6638 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
6639 DIP("xoris r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
6640 assign( rA
, binop( mkSzOp(ty
, Iop_Xor8
), mkexpr(rS
),
6641 mkSzImm(ty
, uimm16
<< 16)) );
6647 opc2
= IFIELD( theInstr
, 2, 9 );
6650 case 0x1BD: // extswsli (Extend Sign Word shift left)
6652 /* sh[5] is in bit 1, sh[0:4] is in bits [14:10] of theInstr */
6653 UChar sh
= IFIELD( theInstr
, 11, 5 ) | (IFIELD(theInstr
, 1, 1) << 5);
6654 IRTemp temp
= newTemp( ty
);
6656 DIP("extswsli%s r%u,r%u,%u\n", flag_rC
? ".":"",
6657 rA_addr
, rS_addr
, sh
);
6659 assign( temp
, unop( Iop_32Sto64
,
6660 unop( Iop_64to32
, mkexpr( rS
) ) ) );
6661 assign( rA
, binop( Iop_Shl64
, mkexpr( temp
), mkU8( sh
) ) );
6662 putIReg( rA_addr
, mkexpr( rA
) );
6665 set_CR0( mkexpr( rA
) );
6670 break; // drop to next opc2 check
6673 do_rc
= True
; // All below record to CR, except for where we return at case end.
6675 opc2
= ifieldOPClo10( theInstr
);
6678 case 0x01C: // and (AND, PPC32 p356)
6679 DIP("and%s r%u,r%u,r%u\n",
6680 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
6681 assign(rA
, binop( mkSzOp(ty
, Iop_And8
),
6682 mkexpr(rS
), mkexpr(rB
)));
6685 case 0x03C: // andc (AND with Complement, PPC32 p357)
6686 DIP("andc%s r%u,r%u,r%u\n",
6687 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
6688 assign(rA
, binop( mkSzOp(ty
, Iop_And8
), mkexpr(rS
),
6689 unop( mkSzOp(ty
, Iop_Not8
),
6693 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
6695 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
6698 DIP("cntlzw%s r%u,r%u\n", flag_rC
? ".":"", rA_addr
, rS_addr
);
6700 // mode64: count in low word only
6701 IRExpr
* lo32
= mode64
? unop(Iop_64to32
, mkexpr(rS
)) : mkexpr(rS
);
6702 IRExpr
* res32
= unop(Iop_ClzNat32
, lo32
);
6703 assign(rA
, mode64
? unop(Iop_32Uto64
, res32
) : res32
);
6707 case 0x11C: // eqv (Equivalent, PPC32 p396)
6708 DIP("eqv%s r%u,r%u,r%u\n",
6709 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
6710 assign( rA
, unop( mkSzOp(ty
, Iop_Not8
),
6711 binop( mkSzOp(ty
, Iop_Xor8
),
6712 mkexpr(rS
), mkexpr(rB
))) );
6715 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
6717 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
6720 DIP("extsb%s r%u,r%u\n",
6721 flag_rC
? ".":"", rA_addr
, rS_addr
);
6723 assign( rA
, unop(Iop_8Sto64
, unop(Iop_64to8
, mkexpr(rS
))) );
6725 assign( rA
, unop(Iop_8Sto32
, unop(Iop_32to8
, mkexpr(rS
))) );
6728 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
6730 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
6733 DIP("extsh%s r%u,r%u\n",
6734 flag_rC
? ".":"", rA_addr
, rS_addr
);
6736 assign( rA
, unop(Iop_16Sto64
,
6737 unop(Iop_64to16
, mkexpr(rS
))) );
6739 assign( rA
, unop(Iop_16Sto32
,
6740 unop(Iop_32to16
, mkexpr(rS
))) );
6743 case 0x1DC: // nand (NAND, PPC32 p492)
6744 DIP("nand%s r%u,r%u,r%u\n",
6745 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
6746 assign( rA
, unop( mkSzOp(ty
, Iop_Not8
),
6747 binop( mkSzOp(ty
, Iop_And8
),
6748 mkexpr(rS
), mkexpr(rB
))) );
6751 case 0x07C: // nor (NOR, PPC32 p494)
6752 DIP("nor%s r%u,r%u,r%u\n",
6753 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
6754 assign( rA
, unop( mkSzOp(ty
, Iop_Not8
),
6755 binop( mkSzOp(ty
, Iop_Or8
),
6756 mkexpr(rS
), mkexpr(rB
))) );
6759 case 0x1BC: // or (OR, PPC32 p495)
6760 if ((!flag_rC
) && rS_addr
== rB_addr
) {
6761 DIP("mr r%u,r%u\n", rA_addr
, rS_addr
);
6762 assign( rA
, mkexpr(rS
) );
6764 DIP("or%s r%u,r%u,r%u\n",
6765 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
6766 assign( rA
, binop( mkSzOp(ty
, Iop_Or8
),
6767 mkexpr(rS
), mkexpr(rB
)) );
6771 case 0x19C: // orc (OR with Complement, PPC32 p496)
6772 DIP("orc%s r%u,r%u,r%u\n",
6773 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
6774 assign( rA
, binop( mkSzOp(ty
, Iop_Or8
), mkexpr(rS
),
6775 unop(mkSzOp(ty
, Iop_Not8
), mkexpr(rB
))));
6778 case 0x13C: // xor (XOR, PPC32 p549)
6779 DIP("xor%s r%u,r%u,r%u\n",
6780 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
6781 assign( rA
, binop( mkSzOp(ty
, Iop_Xor8
),
6782 mkexpr(rS
), mkexpr(rB
)) );
6786 /* 64bit Integer Logical Instructions */
6787 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
6789 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
6792 DIP("extsw%s r%u,r%u\n", flag_rC
? ".":"", rA_addr
, rS_addr
);
6793 assign(rA
, unop(Iop_32Sto64
, unop(Iop_64to32
, mkexpr(rS
))));
6796 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
6798 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
6801 DIP("cntlzd%s r%u,r%u\n", flag_rC
? ".":"", rA_addr
, rS_addr
);
6802 assign(rA
, unop(Iop_ClzNat64
, mkexpr(rS
)));
6805 case 0x1FC: // cmpb (Power6: compare bytes)
6806 DIP("cmpb r%u,r%u,r%u\n", rA_addr
, rS_addr
, rB_addr
);
6809 assign( rA
, unop( Iop_V128to64
,
6810 binop( Iop_CmpEQ8x16
,
6811 binop( Iop_64HLtoV128
, mkU64(0), mkexpr(rS
) ),
6812 binop( Iop_64HLtoV128
, mkU64(0), mkexpr(rB
) )
6815 assign( rA
, unop( Iop_V128to32
,
6816 binop( Iop_CmpEQ8x16
,
6817 unop( Iop_32UtoV128
, mkexpr(rS
) ),
6818 unop( Iop_32UtoV128
, mkexpr(rB
) )
6822 case 0x2DF: { // mftgpr (move floating-point to general purpose register)
6823 IRTemp frB
= newTemp(Ity_F64
);
6824 DIP("mftgpr r%u,fr%u\n", rS_addr
, rB_addr
);
6826 assign( frB
, getFReg(rB_addr
)); // always F64
6828 assign( rA
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
)) );
6830 assign( rA
, unop( Iop_64to32
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
))) );
6832 putIReg( rS_addr
, mkexpr(rA
));
6836 case 0x25F: { // mffgpr (move floating-point from general purpose register)
6837 IRTemp frA
= newTemp(Ity_F64
);
6838 DIP("mffgpr fr%u,r%u\n", rS_addr
, rB_addr
);
6841 assign( frA
, unop( Iop_ReinterpI64asF64
, mkexpr(rB
)) );
6843 assign( frA
, unop( Iop_ReinterpI64asF64
, unop( Iop_32Uto64
, mkexpr(rB
))) );
6845 putFReg( rS_addr
, mkexpr(frA
));
6848 case 0x1FA: // popcntd (population count doubleword)
6851 DIP("popcntd r%u,r%u\n", rA_addr
, rS_addr
);
6852 IRTemp result
= gen_POPCOUNT(ty
, rS
, DWORD
);
6853 putIReg( rA_addr
, mkexpr(result
) );
6856 case 0x17A: // popcntw (Population Count Words)
6858 DIP("popcntw r%u,r%u\n", rA_addr
, rS_addr
);
6860 IRTemp resultHi
, resultLo
;
6861 IRTemp argLo
= newTemp(Ity_I32
);
6862 IRTemp argHi
= newTemp(Ity_I32
);
6863 assign(argLo
, unop(Iop_64to32
, mkexpr(rS
)));
6864 assign(argHi
, unop(Iop_64HIto32
, mkexpr(rS
)));
6865 resultLo
= gen_POPCOUNT(Ity_I32
, argLo
, WORD
);
6866 resultHi
= gen_POPCOUNT(Ity_I32
, argHi
, WORD
);
6867 putIReg( rA_addr
, binop(Iop_32HLto64
, mkexpr(resultHi
), mkexpr(resultLo
)));
6869 IRTemp result
= gen_POPCOUNT(ty
, rS
, WORD
);
6870 putIReg( rA_addr
, mkexpr(result
) );
6874 case 0x7A: // popcntb (Population Count Byte)
6876 DIP("popcntb r%u,r%u\n", rA_addr
, rS_addr
);
6879 IRTemp resultHi
, resultLo
;
6880 IRTemp argLo
= newTemp(Ity_I32
);
6881 IRTemp argHi
= newTemp(Ity_I32
);
6882 assign(argLo
, unop(Iop_64to32
, mkexpr(rS
)));
6883 assign(argHi
, unop(Iop_64HIto32
, mkexpr(rS
)));
6884 resultLo
= gen_POPCOUNT(Ity_I32
, argLo
, BYTE
);
6885 resultHi
= gen_POPCOUNT(Ity_I32
, argHi
, BYTE
);
6886 putIReg( rA_addr
, binop(Iop_32HLto64
, mkexpr(resultHi
),
6889 IRTemp result
= gen_POPCOUNT(ty
, rS
, BYTE
);
6890 putIReg( rA_addr
, mkexpr(result
) );
6894 case 0x0FC: // bpermd (Bit Permute Doubleword)
6896 /* This is a lot of rigmarole to emulate bpermd like this, as it
6897 * could be done much faster by implementing a call to the native
6898 * instruction. However, where possible I want to avoid using new
6899 * native instructions so that we can use valgrind to emulate those
6900 * instructions on older PPC64 hardware.
6902 #define BPERMD_IDX_MASK 0x00000000000000FFULL
6903 #define BPERMD_BIT_MASK 0x8000000000000000ULL
6905 IRExpr
* rS_expr
= mkexpr(rS
);
6906 IRExpr
* res
= binop(Iop_And64
, mkU64(0), mkU64(0));
6907 DIP("bpermd r%u,r%u,r%u\n", rA_addr
, rS_addr
, rB_addr
);
6908 for (i
= 0; i
< 8; i
++) {
6909 IRTemp idx_tmp
= newTemp( Ity_I64
);
6910 IRTemp perm_bit
= newTemp( Ity_I64
);
6911 IRTemp idx
= newTemp( Ity_I8
);
6912 IRTemp idx_LT64
= newTemp( Ity_I1
);
6913 IRTemp idx_LT64_ity64
= newTemp( Ity_I64
);
6916 binop( Iop_And64
, mkU64( BPERMD_IDX_MASK
), rS_expr
) );
6918 binop( Iop_CmpLT64U
, mkexpr( idx_tmp
), mkU64( 64 ) ) );
6923 unop( Iop_64to8
, mkexpr( idx_tmp
) ) ) );
6924 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
6925 * to determine which bit of rB to use for the perm bit, and then we shift
6926 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64
6927 * to set the final perm bit.
6929 assign( idx_LT64_ity64
,
6930 unop( Iop_32Uto64
, unop( Iop_1Uto32
, mkexpr(idx_LT64
) ) ) );
6933 mkexpr( idx_LT64_ity64
),
6936 mkU64( BPERMD_BIT_MASK
),
6941 res
= binop( Iop_Or64
,
6946 rS_expr
= binop( Iop_Shr64
, rS_expr
, mkU8( 8 ) );
6948 putIReg(rA_addr
, res
);
6953 vex_printf("dis_int_logic(ppc)(opc2)\n");
6959 vex_printf("dis_int_logic(ppc)(opc1)\n");
6963 putIReg( rA_addr
, mkexpr(rA
) );
6965 if (do_rc
&& flag_rC
) {
6966 set_CR0( mkexpr(rA
) );
6972 Integer Parity Instructions
6974 static Bool
dis_int_parity ( UInt theInstr
)
6977 UChar opc1
= ifieldOPC(theInstr
);
6978 UChar rS_addr
= ifieldRegDS(theInstr
);
6979 UChar rA_addr
= ifieldRegA(theInstr
);
6980 UChar rB_addr
= ifieldRegB(theInstr
);
6981 UInt opc2
= ifieldOPClo10(theInstr
);
6982 UChar b0
= ifieldBIT0(theInstr
);
6983 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
6985 IRTemp rS
= newTemp(ty
);
6986 IRTemp rA
= newTemp(ty
);
6987 IRTemp iTot1
= newTemp(Ity_I32
);
6988 IRTemp iTot2
= newTemp(Ity_I32
);
6989 IRTemp iTot3
= newTemp(Ity_I32
);
6990 IRTemp iTot4
= newTemp(Ity_I32
);
6991 IRTemp iTot5
= newTemp(Ity_I32
);
6992 IRTemp iTot6
= newTemp(Ity_I32
);
6993 IRTemp iTot7
= newTemp(Ity_I32
);
6994 IRTemp iTot8
= newTemp(Ity_I32
);
6995 IRTemp rS1
= newTemp(ty
);
6996 IRTemp rS2
= newTemp(ty
);
6997 IRTemp rS3
= newTemp(ty
);
6998 IRTemp rS4
= newTemp(ty
);
6999 IRTemp rS5
= newTemp(ty
);
7000 IRTemp rS6
= newTemp(ty
);
7001 IRTemp rS7
= newTemp(ty
);
7002 IRTemp iHi
= newTemp(Ity_I32
);
7003 IRTemp iLo
= newTemp(Ity_I32
);
7004 IROp to_bit
= (mode64
? Iop_64to1
: Iop_32to1
);
7005 IROp shr_op
= (mode64
? Iop_Shr64
: Iop_Shr32
);
7007 if (opc1
!= 0x1f || rB_addr
|| b0
) {
7008 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
7012 assign( rS
, getIReg(rS_addr
) );
7015 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320)
7016 DIP("prtyd r%u,r%u\n", rA_addr
, rS_addr
);
7017 assign( iTot1
, unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS
))) );
7018 assign( rS1
, binop(shr_op
, mkexpr(rS
), mkU8(8)) );
7019 assign( iTot2
, binop(Iop_Add32
,
7020 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS1
))),
7022 assign( rS2
, binop(shr_op
, mkexpr(rS1
), mkU8(8)) );
7023 assign( iTot3
, binop(Iop_Add32
,
7024 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS2
))),
7026 assign( rS3
, binop(shr_op
, mkexpr(rS2
), mkU8(8)) );
7027 assign( iTot4
, binop(Iop_Add32
,
7028 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS3
))),
7031 assign( rS4
, binop(shr_op
, mkexpr(rS3
), mkU8(8)) );
7032 assign( iTot5
, binop(Iop_Add32
,
7033 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS4
))),
7035 assign( rS5
, binop(shr_op
, mkexpr(rS4
), mkU8(8)) );
7036 assign( iTot6
, binop(Iop_Add32
,
7037 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS5
))),
7039 assign( rS6
, binop(shr_op
, mkexpr(rS5
), mkU8(8)) );
7040 assign( iTot7
, binop(Iop_Add32
,
7041 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS6
))),
7043 assign( rS7
, binop(shr_op
, mkexpr(rS6
), mkU8(8)) );
7044 assign( iTot8
, binop(Iop_Add32
,
7045 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS7
))),
7047 assign( rA
, unop(Iop_32Uto64
,
7048 binop(Iop_And32
, mkexpr(iTot8
), mkU32(1))) );
7050 assign( rA
, mkexpr(iTot4
) );
7053 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320)
7054 assign( iTot1
, unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS
))) );
7055 assign( rS1
, binop(shr_op
, mkexpr(rS
), mkU8(8)) );
7056 assign( iTot2
, binop(Iop_Add32
,
7057 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS1
))),
7059 assign( rS2
, binop(shr_op
, mkexpr(rS1
), mkU8(8)) );
7060 assign( iTot3
, binop(Iop_Add32
,
7061 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS2
))),
7063 assign( rS3
, binop(shr_op
, mkexpr(rS2
), mkU8(8)) );
7064 assign( iTot4
, binop(Iop_Add32
,
7065 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS3
))),
7067 assign( iLo
, unop(Iop_1Uto32
, unop(Iop_32to1
, mkexpr(iTot4
) )) );
7070 assign( rS4
, binop(shr_op
, mkexpr(rS3
), mkU8(8)) );
7071 assign( iTot5
, unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS4
))) );
7072 assign( rS5
, binop(shr_op
, mkexpr(rS4
), mkU8(8)) );
7073 assign( iTot6
, binop(Iop_Add32
,
7074 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS5
))),
7076 assign( rS6
, binop(shr_op
, mkexpr(rS5
), mkU8(8)) );
7077 assign( iTot7
, binop(Iop_Add32
,
7078 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS6
))),
7080 assign( rS7
, binop(shr_op
, mkexpr(rS6
), mkU8(8)));
7081 assign( iTot8
, binop(Iop_Add32
,
7082 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS7
))),
7084 assign( iHi
, binop(Iop_And32
, mkU32(1), mkexpr(iTot8
)) ),
7085 assign( rA
, binop(Iop_32HLto64
, mkexpr(iHi
), mkexpr(iLo
)) );
7087 assign( rA
, binop(Iop_Or32
, mkU32(0), mkexpr(iLo
)) );
7090 vex_printf("dis_int_parity(ppc)(opc2)\n");
7094 putIReg( rA_addr
, mkexpr(rA
) );
7101 Integer Rotate Instructions
7103 static Bool
dis_int_rot ( UInt theInstr
)
7105 /* M-Form, MDS-Form */
7106 UChar opc1
= ifieldOPC(theInstr
);
7107 UChar rS_addr
= ifieldRegDS(theInstr
);
7108 UChar rA_addr
= ifieldRegA(theInstr
);
7109 UChar rB_addr
= ifieldRegB(theInstr
);
7110 UChar sh_imm
= rB_addr
;
7111 UChar MaskBeg
= toUChar( IFIELD( theInstr
, 6, 5 ) );
7112 UChar MaskEnd
= toUChar( IFIELD( theInstr
, 1, 5 ) );
7113 UChar msk_imm
= toUChar( IFIELD( theInstr
, 5, 6 ) );
7114 UChar opc2
= toUChar( IFIELD( theInstr
, 2, 3 ) );
7115 UChar b1
= ifieldBIT1(theInstr
);
7116 UChar flag_rC
= ifieldBIT0(theInstr
);
7118 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
7119 IRTemp rS
= newTemp(ty
);
7120 IRTemp rA
= newTemp(ty
);
7121 IRTemp rB
= newTemp(ty
);
7122 IRTemp rot
= newTemp(ty
);
7127 assign( rS
, getIReg(rS_addr
) );
7128 assign( rB
, getIReg(rB_addr
) );
7132 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
7133 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC
? ".":"",
7134 rA_addr
, rS_addr
, sh_imm
, MaskBeg
, MaskEnd
);
7136 // tmp32 = (ROTL(rS_Lo32, Imm)
7137 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
7138 mask64
= MASK64(31-MaskEnd
, 31-MaskBeg
);
7139 r
= ROTL( unop(Iop_64to32
, mkexpr(rS
) ), mkU8(sh_imm
) );
7140 r
= unop(Iop_32Uto64
, r
);
7141 assign( rot
, binop(Iop_Or64
, r
,
7142 binop(Iop_Shl64
, r
, mkU8(32))) );
7145 binop(Iop_And64
, mkexpr(rot
), mkU64(mask64
)),
7146 binop(Iop_And64
, getIReg(rA_addr
), mkU64(~mask64
))) );
7149 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
7150 mask32
= MASK32(31-MaskEnd
, 31-MaskBeg
);
7151 r
= ROTL(mkexpr(rS
), mkU8(sh_imm
));
7154 binop(Iop_And32
, mkU32(mask32
), r
),
7155 binop(Iop_And32
, getIReg(rA_addr
), mkU32(~mask32
))) );
7161 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
7162 vassert(MaskBeg
< 32);
7163 vassert(MaskEnd
< 32);
7164 vassert(sh_imm
< 32);
7167 IRTemp rTmp
= newTemp(Ity_I64
);
7168 mask64
= MASK64(31-MaskEnd
, 31-MaskBeg
);
7169 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC
? ".":"",
7170 rA_addr
, rS_addr
, sh_imm
, MaskBeg
, MaskEnd
);
7171 // tmp32 = (ROTL(rS_Lo32, Imm)
7172 // rA = ((tmp32 || tmp32) & mask64)
7173 r
= ROTL( unop(Iop_64to32
, mkexpr(rS
) ), mkU8(sh_imm
) );
7174 r
= unop(Iop_32Uto64
, r
);
7177 assign( rot
, binop(Iop_Or64
, mkexpr(rTmp
),
7178 binop(Iop_Shl64
, mkexpr(rTmp
), mkU8(32))) );
7179 assign( rA
, binop(Iop_And64
, mkexpr(rot
), mkU64(mask64
)) );
7182 if (MaskBeg
== 0 && sh_imm
+MaskEnd
== 31) {
7183 /* Special-case the ,n,0,31-n form as that is just n-bit
7184 shift left, PPC32 p501 */
7185 DIP("slwi%s r%u,r%u,%d\n", flag_rC
? ".":"",
7186 rA_addr
, rS_addr
, sh_imm
);
7187 assign( rA
, binop(Iop_Shl32
, mkexpr(rS
), mkU8(sh_imm
)) );
7189 else if (MaskEnd
== 31 && sh_imm
+MaskBeg
== 32) {
7190 /* Special-case the ,32-n,n,31 form as that is just n-bit
7191 unsigned shift right, PPC32 p501 */
7192 DIP("srwi%s r%u,r%u,%d\n", flag_rC
? ".":"",
7193 rA_addr
, rS_addr
, MaskBeg
);
7194 assign( rA
, binop(Iop_Shr32
, mkexpr(rS
), mkU8(MaskBeg
)) );
7198 mask32
= MASK32(31-MaskEnd
, 31-MaskBeg
);
7199 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC
? ".":"",
7200 rA_addr
, rS_addr
, sh_imm
, MaskBeg
, MaskEnd
);
7201 // rA = ROTL(rS, Imm) & mask
7202 assign( rA
, binop(Iop_And32
,
7203 ROTL(mkexpr(rS
), mkU8(sh_imm
)),
7211 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
7212 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC
? ".":"",
7213 rA_addr
, rS_addr
, rB_addr
, MaskBeg
, MaskEnd
);
7215 mask64
= MASK64(31-MaskEnd
, 31-MaskBeg
);
7216 /* weird insn alert!
7217 tmp32 = (ROTL(rS_Lo32, rB[0-4])
7218 rA = ((tmp32 || tmp32) & mask64)
7220 // note, ROTL does the masking, so we don't do it here
7221 r
= ROTL( unop(Iop_64to32
, mkexpr(rS
)),
7222 unop(Iop_64to8
, mkexpr(rB
)) );
7223 r
= unop(Iop_32Uto64
, r
);
7224 assign(rot
, binop(Iop_Or64
, r
, binop(Iop_Shl64
, r
, mkU8(32))));
7225 assign( rA
, binop(Iop_And64
, mkexpr(rot
), mkU64(mask64
)) );
7227 mask32
= MASK32(31-MaskEnd
, 31-MaskBeg
);
7228 // rA = ROTL(rS, rB[0-4]) & mask
7229 // note, ROTL does the masking, so we don't do it here
7230 assign( rA
, binop(Iop_And32
,
7232 unop(Iop_32to8
, mkexpr(rB
))),
7238 /* 64bit Integer Rotates */
7240 msk_imm
= ((msk_imm
& 1) << 5) | (msk_imm
>> 1);
7243 vassert( msk_imm
< 64 );
7244 vassert( sh_imm
< 64 );
7248 /* r = ROTL64( rS, rB_lo6) */
7249 r
= ROTL( mkexpr(rS
), unop(Iop_64to8
, mkexpr(rB
)) );
7251 if (b1
== 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
7252 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC
? ".":"",
7253 rA_addr
, rS_addr
, rB_addr
, msk_imm
);
7254 // note, ROTL does the masking, so we don't do it here
7255 mask64
= MASK64(0, 63-msk_imm
);
7256 assign( rA
, binop(Iop_And64
, r
, mkU64(mask64
)) );
7258 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556)
7259 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC
? ".":"",
7260 rA_addr
, rS_addr
, rB_addr
, msk_imm
);
7261 mask64
= MASK64(63-msk_imm
, 63);
7262 assign( rA
, binop(Iop_And64
, r
, mkU64(mask64
)) );
7267 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
7268 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC
? ".":"",
7269 rA_addr
, rS_addr
, sh_imm
, msk_imm
);
7270 r
= ROTL(mkexpr(rS
), mkU8(sh_imm
));
7271 mask64
= MASK64(sh_imm
, 63-msk_imm
);
7272 assign( rA
, binop(Iop_And64
, r
, mkU64(mask64
)) );
7274 // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
7276 Hmm... looks like this'll do the job more simply:
7278 m = ~(1 << (63-msk_imm))
7282 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
7284 && sh_imm
+ msk_imm
== 64 && msk_imm
>= 1 && msk_imm
<= 63) {
7285 /* special-case the ,64-n,n form as that is just
7286 unsigned shift-right by n */
7287 DIP("srdi%s r%u,r%u,%u\n",
7288 flag_rC
? ".":"", rA_addr
, rS_addr
, msk_imm
);
7289 assign( rA
, binop(Iop_Shr64
, mkexpr(rS
), mkU8(msk_imm
)) );
7291 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC
? ".":"",
7292 rA_addr
, rS_addr
, sh_imm
, msk_imm
);
7293 r
= ROTL(mkexpr(rS
), mkU8(sh_imm
));
7294 mask64
= MASK64(0, 63-msk_imm
);
7295 assign( rA
, binop(Iop_And64
, r
, mkU64(mask64
)) );
7299 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
7301 && sh_imm
+ msk_imm
== 63 && sh_imm
>= 1 && sh_imm
<= 63) {
7302 /* special-case the ,n,63-n form as that is just
7304 DIP("sldi%s r%u,r%u,%u\n",
7305 flag_rC
? ".":"", rA_addr
, rS_addr
, sh_imm
);
7306 assign( rA
, binop(Iop_Shl64
, mkexpr(rS
), mkU8(sh_imm
)) );
7308 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC
? ".":"",
7309 rA_addr
, rS_addr
, sh_imm
, msk_imm
);
7310 r
= ROTL(mkexpr(rS
), mkU8(sh_imm
));
7311 mask64
= MASK64(63-msk_imm
, 63);
7312 assign( rA
, binop(Iop_And64
, r
, mkU64(mask64
)) );
7316 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
7317 IRTemp rA_orig
= newTemp(ty
);
7318 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC
? ".":"",
7319 rA_addr
, rS_addr
, sh_imm
, msk_imm
);
7320 r
= ROTL(mkexpr(rS
), mkU8(sh_imm
));
7321 mask64
= MASK64(sh_imm
, 63-msk_imm
);
7322 assign( rA_orig
, getIReg(rA_addr
) );
7323 assign( rA
, binop(Iop_Or64
,
7324 binop(Iop_And64
, mkU64(mask64
), r
),
7325 binop(Iop_And64
, mkU64(~mask64
),
7326 mkexpr(rA_orig
))) );
7330 vex_printf("dis_int_rot(ppc)(opc2)\n");
7337 vex_printf("dis_int_rot(ppc)(opc1)\n");
7341 putIReg( rA_addr
, mkexpr(rA
) );
7344 set_CR0( mkexpr(rA
) );
7351 Integer Load Instructions
7353 static Bool
dis_int_load ( UInt theInstr
)
7355 /* D-Form, X-Form, DS-Form */
7356 UChar opc1
= ifieldOPC(theInstr
);
7357 UChar rD_addr
= ifieldRegDS(theInstr
);
7358 UChar rA_addr
= ifieldRegA(theInstr
);
7359 UInt uimm16
= ifieldUIMM16(theInstr
);
7360 UChar rB_addr
= ifieldRegB(theInstr
);
7361 UInt opc2
= ifieldOPClo10(theInstr
);
7362 UChar b1
= ifieldBIT1(theInstr
);
7363 UChar b0
= ifieldBIT0(theInstr
);
7365 Int simm16
= extend_s_16to32(uimm16
);
7366 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
7367 IRTemp EA
= newTemp(ty
);
7371 case 0x1F: // register offset
7372 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
7374 case 0x38: // immediate offset: 64bit: lq: maskoff
7375 // lowest 4 bits of immediate before forming EA
7376 simm16
= simm16
& 0xFFFFFFF0;
7377 assign( EA
, ea_rAor0_simm( rA_addr
, simm16
) );
7379 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
7380 // lowest 2 bits of immediate before forming EA
7381 simm16
= simm16
& 0xFFFFFFFC;
7382 assign( EA
, ea_rAor0_simm( rA_addr
, simm16
) );
7384 default: // immediate offset
7385 assign( EA
, ea_rAor0_simm( rA_addr
, simm16
) );
7390 case 0x22: // lbz (Load B & Zero, PPC32 p433)
7391 DIP("lbz r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
7392 val
= load(Ity_I8
, mkexpr(EA
));
7393 putIReg( rD_addr
, mkWidenFrom8(ty
, val
, False
) );
7396 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
7397 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
7398 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
7401 DIP("lbzu r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
7402 val
= load(Ity_I8
, mkexpr(EA
));
7403 putIReg( rD_addr
, mkWidenFrom8(ty
, val
, False
) );
7404 putIReg( rA_addr
, mkexpr(EA
) );
7407 case 0x2A: // lha (Load HW Alg, PPC32 p445)
7408 DIP("lha r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
7409 val
= load(Ity_I16
, mkexpr(EA
));
7410 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, True
) );
7413 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
7414 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
7415 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
7418 DIP("lhau r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
7419 val
= load(Ity_I16
, mkexpr(EA
));
7420 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, True
) );
7421 putIReg( rA_addr
, mkexpr(EA
) );
7424 case 0x28: // lhz (Load HW & Zero, PPC32 p450)
7425 DIP("lhz r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
7426 val
= load(Ity_I16
, mkexpr(EA
));
7427 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, False
) );
7430 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
7431 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
7432 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
7435 DIP("lhzu r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
7436 val
= load(Ity_I16
, mkexpr(EA
));
7437 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, False
) );
7438 putIReg( rA_addr
, mkexpr(EA
) );
7441 case 0x20: // lwz (Load W & Zero, PPC32 p460)
7442 DIP("lwz r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
7443 val
= load(Ity_I32
, mkexpr(EA
));
7444 putIReg( rD_addr
, mkWidenFrom32(ty
, val
, False
) );
7447 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
7448 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
7449 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
7452 DIP("lwzu r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
7453 val
= load(Ity_I32
, mkexpr(EA
));
7454 putIReg( rD_addr
, mkWidenFrom32(ty
, val
, False
) );
7455 putIReg( rA_addr
, mkexpr(EA
) );
7461 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
7466 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
7467 DIP("lbzux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7468 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
7469 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
7472 val
= load(Ity_I8
, mkexpr(EA
));
7473 putIReg( rD_addr
, mkWidenFrom8(ty
, val
, False
) );
7474 putIReg( rA_addr
, mkexpr(EA
) );
7477 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
7478 DIP("lbzx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7479 val
= load(Ity_I8
, mkexpr(EA
));
7480 putIReg( rD_addr
, mkWidenFrom8(ty
, val
, False
) );
7483 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
7484 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
7485 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
7488 DIP("lhaux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7489 val
= load(Ity_I16
, mkexpr(EA
));
7490 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, True
) );
7491 putIReg( rA_addr
, mkexpr(EA
) );
7494 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
7495 DIP("lhax r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7496 val
= load(Ity_I16
, mkexpr(EA
));
7497 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, True
) );
7500 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
7501 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
7502 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
7505 DIP("lhzux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7506 val
= load(Ity_I16
, mkexpr(EA
));
7507 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, False
) );
7508 putIReg( rA_addr
, mkexpr(EA
) );
7511 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
7512 DIP("lhzx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7513 val
= load(Ity_I16
, mkexpr(EA
));
7514 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, False
) );
7517 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
7518 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
7519 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
7522 DIP("lwzux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7523 val
= load(Ity_I32
, mkexpr(EA
));
7524 putIReg( rD_addr
, mkWidenFrom32(ty
, val
, False
) );
7525 putIReg( rA_addr
, mkexpr(EA
) );
7528 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
7529 DIP("lwzx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7530 val
= load(Ity_I32
, mkexpr(EA
));
7531 putIReg( rD_addr
, mkWidenFrom32(ty
, val
, False
) );
7536 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
7537 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
7538 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
7541 DIP("ldux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7542 putIReg( rD_addr
, load(Ity_I64
, mkexpr(EA
)) );
7543 putIReg( rA_addr
, mkexpr(EA
) );
7546 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
7547 DIP("ldx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7548 putIReg( rD_addr
, load(Ity_I64
, mkexpr(EA
)) );
7551 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
7552 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
7553 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
7556 DIP("lwaux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7558 unop(Iop_32Sto64
, load(Ity_I32
, mkexpr(EA
))) );
7559 putIReg( rA_addr
, mkexpr(EA
) );
7562 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
7563 DIP("lwax r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7565 unop(Iop_32Sto64
, load(Ity_I32
, mkexpr(EA
))) );
7569 vex_printf("dis_int_load(ppc)(opc2)\n");
7574 /* DS Form - 64bit Loads. In each case EA will have been formed
7575 with the lowest 2 bits masked off the immediate offset. */
7577 switch ((b1
<<1) | b0
) {
7578 case 0x0: // ld (Load DWord, PPC64 p472)
7579 DIP("ld r%u,%d(r%u)\n", rD_addr
, simm16
, rA_addr
);
7580 putIReg( rD_addr
, load(Ity_I64
, mkexpr(EA
)) );
7583 case 0x1: // ldu (Load DWord, Update, PPC64 p474)
7584 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
7585 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
7588 DIP("ldu r%u,%d(r%u)\n", rD_addr
, simm16
, rA_addr
);
7589 putIReg( rD_addr
, load(Ity_I64
, mkexpr(EA
)) );
7590 putIReg( rA_addr
, mkexpr(EA
) );
7593 case 0x2: // lwa (Load Word Alg, PPC64 p499)
7594 DIP("lwa r%u,%d(r%u)\n", rD_addr
, simm16
, rA_addr
);
7596 unop(Iop_32Sto64
, load(Ity_I32
, mkexpr(EA
))) );
7600 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
7606 IRTemp high
= newTemp(ty
);
7607 IRTemp low
= newTemp(ty
);
7608 /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
7609 DIP("lq r%u,%d(r%u)\n", rD_addr
, simm16
, rA_addr
);
7610 /* NOTE: there are some changes to XER[41:42] that have not been
7613 // trap if EA misaligned on 16 byte address
7615 if (host_endness
== VexEndnessBE
) {
7616 assign(high
, load(ty
, mkexpr( EA
) ) );
7617 assign(low
, load(ty
, binop( Iop_Add64
,
7621 assign(low
, load(ty
, mkexpr( EA
) ) );
7622 assign(high
, load(ty
, binop( Iop_Add64
,
7627 assign(high
, load(ty
, binop( Iop_Add32
,
7630 assign(low
, load(ty
, binop( Iop_Add32
,
7634 gen_SIGBUS_if_misaligned( EA
, 16 );
7635 putIReg( rD_addr
, mkexpr( high
) );
7636 putIReg( rD_addr
+1, mkexpr( low
) );
7640 vex_printf("dis_int_load(ppc)(opc1)\n");
7649 Integer Store Instructions
7651 static Bool
dis_int_store ( UInt theInstr
, const VexAbiInfo
* vbi
)
7653 /* D-Form, X-Form, DS-Form */
7654 UChar opc1
= ifieldOPC(theInstr
);
7655 UInt rS_addr
= ifieldRegDS(theInstr
);
7656 UInt rA_addr
= ifieldRegA(theInstr
);
7657 UInt uimm16
= ifieldUIMM16(theInstr
);
7658 UInt rB_addr
= ifieldRegB(theInstr
);
7659 UInt opc2
= ifieldOPClo10(theInstr
);
7660 UChar b1
= ifieldBIT1(theInstr
);
7661 UChar b0
= ifieldBIT0(theInstr
);
7663 Int simm16
= extend_s_16to32(uimm16
);
7664 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
7665 IRTemp rS
= newTemp(ty
);
7666 IRTemp rB
= newTemp(ty
);
7667 IRTemp EA
= newTemp(ty
);
7669 assign( rB
, getIReg(rB_addr
) );
7670 assign( rS
, getIReg(rS_addr
) );
7673 case 0x1F: // register offset
7674 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
7676 case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
7677 // lowest 2 bits of immediate before forming EA
7678 simm16
= simm16
& 0xFFFFFFFC;
7680 default: // immediate offset
7681 assign( EA
, ea_rAor0_simm( rA_addr
, simm16
) );
7686 case 0x26: // stb (Store B, PPC32 p509)
7687 DIP("stb r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
7688 store( mkexpr(EA
), mkNarrowTo8(ty
, mkexpr(rS
)) );
7691 case 0x27: // stbu (Store B, Update, PPC32 p510)
7692 if (rA_addr
== 0 ) {
7693 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
7696 DIP("stbu r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
7697 putIReg( rA_addr
, mkexpr(EA
) );
7698 store( mkexpr(EA
), mkNarrowTo8(ty
, mkexpr(rS
)) );
7701 case 0x2C: // sth (Store HW, PPC32 p522)
7702 DIP("sth r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
7703 store( mkexpr(EA
), mkNarrowTo16(ty
, mkexpr(rS
)) );
7706 case 0x2D: // sthu (Store HW, Update, PPC32 p524)
7708 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
7711 DIP("sthu r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
7712 putIReg( rA_addr
, mkexpr(EA
) );
7713 store( mkexpr(EA
), mkNarrowTo16(ty
, mkexpr(rS
)) );
7716 case 0x24: // stw (Store W, PPC32 p530)
7717 DIP("stw r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
7718 store( mkexpr(EA
), mkNarrowTo32(ty
, mkexpr(rS
)) );
7721 case 0x25: // stwu (Store W, Update, PPC32 p534)
7723 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
7726 DIP("stwu r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
7727 putIReg( rA_addr
, mkexpr(EA
) );
7728 store( mkexpr(EA
), mkNarrowTo32(ty
, mkexpr(rS
)) );
7731 /* X Form : all these use EA_indexed */
7734 vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
7739 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
7741 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
7744 DIP("stbux r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
7745 putIReg( rA_addr
, mkexpr(EA
) );
7746 store( mkexpr(EA
), mkNarrowTo8(ty
, mkexpr(rS
)) );
7749 case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
7750 DIP("stbx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
7751 store( mkexpr(EA
), mkNarrowTo8(ty
, mkexpr(rS
)) );
7754 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
7756 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
7759 DIP("sthux r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
7760 putIReg( rA_addr
, mkexpr(EA
) );
7761 store( mkexpr(EA
), mkNarrowTo16(ty
, mkexpr(rS
)) );
7764 case 0x197: // sthx (Store HW Indexed, PPC32 p526)
7765 DIP("sthx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
7766 store( mkexpr(EA
), mkNarrowTo16(ty
, mkexpr(rS
)) );
7769 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
7771 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
7774 DIP("stwux r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
7775 putIReg( rA_addr
, mkexpr(EA
) );
7776 store( mkexpr(EA
), mkNarrowTo32(ty
, mkexpr(rS
)) );
7779 case 0x097: // stwx (Store W Indexed, PPC32 p536)
7780 DIP("stwx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
7781 store( mkexpr(EA
), mkNarrowTo32(ty
, mkexpr(rS
)) );
7786 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
7788 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
7791 DIP("stdux r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
7792 putIReg( rA_addr
, mkexpr(EA
) );
7793 store( mkexpr(EA
), mkexpr(rS
) );
7796 case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
7797 DIP("stdx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
7798 store( mkexpr(EA
), mkexpr(rS
) );
7802 vex_printf("dis_int_store(ppc)(opc2)\n");
7807 /* DS Form - 64bit Stores. In each case EA will have been formed
7808 with the lowest 2 bits masked off the immediate offset. */
7810 switch ((b1
<<1) | b0
) {
7811 case 0x0: // std (Store DWord, PPC64 p580)
7815 DIP("std r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
7816 store( mkexpr(EA
), mkexpr(rS
) );
7819 case 0x1: // stdu (Store DWord, Update, PPC64 p583)
7823 DIP("stdu r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
7824 putIReg( rA_addr
, mkexpr(EA
) );
7825 store( mkexpr(EA
), mkexpr(rS
) );
7828 case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
7829 IRTemp EA_hi
= newTemp(ty
);
7830 IRTemp EA_lo
= newTemp(ty
);
7831 DIP("stq r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
7834 if (host_endness
== VexEndnessBE
) {
7837 assign( EA_hi
, ea_rAor0_simm( rA_addr
, simm16
) );
7840 assign( EA_lo
, ea_rAor0_simm( rA_addr
, simm16
+8 ) );
7843 assign( EA_hi
, ea_rAor0_simm( rA_addr
, simm16
+8 ) );
7846 assign( EA_lo
, ea_rAor0_simm( rA_addr
, simm16
) );
7849 /* upper half of upper 64-bits */
7850 assign( EA_hi
, ea_rAor0_simm( rA_addr
, simm16
+4 ) );
7852 /* lower half of upper 64-bits */
7853 assign( EA_lo
, ea_rAor0_simm( rA_addr
, simm16
+12 ) );
7855 store( mkexpr(EA_hi
), mkexpr(rS
) );
7856 store( mkexpr(EA_lo
), getIReg( rS_addr
+1 ) );
7860 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
7866 vex_printf("dis_int_store(ppc)(opc1)\n");
7875 Integer Load/Store Multiple Instructions
7877 static Bool
dis_int_ldst_mult ( UInt theInstr
)
7880 UChar opc1
= ifieldOPC(theInstr
);
7881 UChar rD_addr
= ifieldRegDS(theInstr
);
7882 UChar rS_addr
= rD_addr
;
7883 UChar rA_addr
= ifieldRegA(theInstr
);
7884 UInt uimm16
= ifieldUIMM16(theInstr
);
7886 Int simm16
= extend_s_16to32(uimm16
);
7887 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
7888 IROp mkAdd
= mode64
? Iop_Add64
: Iop_Add32
;
7889 IRTemp EA
= newTemp(ty
);
7894 assign( EA
, ea_rAor0_simm( rA_addr
, simm16
) );
7897 case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
7898 if (rA_addr
>= rD_addr
) {
7899 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
7902 DIP("lmw r%u,%d(r%u)\n", rD_addr
, simm16
, rA_addr
);
7903 for (r
= rD_addr
; r
<= 31; r
++) {
7904 irx_addr
= binop(mkAdd
, mkexpr(EA
), mode64
? mkU64(ea_off
) : mkU32(ea_off
));
7905 putIReg( r
, mkWidenFrom32(ty
, load(Ity_I32
, irx_addr
),
7911 case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
7912 DIP("stmw r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
7913 for (r
= rS_addr
; r
<= 31; r
++) {
7914 irx_addr
= binop(mkAdd
, mkexpr(EA
), mode64
? mkU64(ea_off
) : mkU32(ea_off
));
7915 store( irx_addr
, mkNarrowTo32(ty
, getIReg(r
)) );
7921 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
7930 Integer Load/Store String Instructions
7933 void generate_lsw_sequence ( IRTemp tNBytes
, // # bytes, :: Ity_I32
7935 Int rD
, // first dst register
7936 Int maxBytes
) // 32 or 128
7939 IRExpr
* e_nbytes
= mkexpr(tNBytes
);
7940 IRExpr
* e_EA
= mkexpr(EA
);
7941 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
7943 vassert(rD
>= 0 && rD
< 32);
7944 rD
--; if (rD
< 0) rD
= 31;
7946 for (i
= 0; i
< maxBytes
; i
++) {
7947 /* if (nBytes < (i+1)) goto NIA; */
7948 stmt( IRStmt_Exit( binop(Iop_CmpLT32U
, e_nbytes
, mkU32(i
+1)),
7950 mkSzConst( ty
, nextInsnAddr()), OFFB_CIA
));
7951 /* when crossing into a new dest register, set it to zero. */
7953 rD
++; if (rD
== 32) rD
= 0;
7954 putIReg(rD
, mkSzImm(ty
, 0));
7957 /* rD |= (8Uto32(*(EA+i))) << shift */
7958 vassert(shift
== 0 || shift
== 8 || shift
== 16 || shift
== 24);
7965 mkNarrowTo32(ty
, getIReg(rD
)),
7971 binop( mkSzOp(ty
,Iop_Add8
),
7972 e_EA
, mkSzImm(ty
,i
)))
7974 mkU8(toUChar(shift
))
7985 void generate_stsw_sequence ( IRTemp tNBytes
, // # bytes, :: Ity_I32
7987 Int rS
, // first src register
7988 Int maxBytes
) // 32 or 128
7991 IRExpr
* e_nbytes
= mkexpr(tNBytes
);
7992 IRExpr
* e_EA
= mkexpr(EA
);
7993 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
7995 vassert(rS
>= 0 && rS
< 32);
7996 rS
--; if (rS
< 0) rS
= 31;
7998 for (i
= 0; i
< maxBytes
; i
++) {
7999 /* if (nBytes < (i+1)) goto NIA; */
8000 stmt( IRStmt_Exit( binop(Iop_CmpLT32U
, e_nbytes
, mkU32(i
+1)),
8002 mkSzConst( ty
, nextInsnAddr() ), OFFB_CIA
));
8003 /* check for crossing into a new src register. */
8005 rS
++; if (rS
== 32) rS
= 0;
8008 /* *(EA+i) = 32to8(rS >> shift) */
8009 vassert(shift
== 0 || shift
== 8 || shift
== 16 || shift
== 24);
8011 binop( mkSzOp(ty
,Iop_Add8
), e_EA
, mkSzImm(ty
,i
)),
8014 mkNarrowTo32( ty
, getIReg(rS
) ),
8015 mkU8( toUChar(shift
) )))
8021 static Bool
dis_int_ldst_str ( UInt theInstr
, /*OUT*/Bool
* stopHere
)
8024 UChar opc1
= ifieldOPC(theInstr
);
8025 UChar rD_addr
= ifieldRegDS(theInstr
);
8026 UChar rS_addr
= rD_addr
;
8027 UChar rA_addr
= ifieldRegA(theInstr
);
8028 UChar rB_addr
= ifieldRegB(theInstr
);
8029 UChar NumBytes
= rB_addr
;
8030 UInt opc2
= ifieldOPClo10(theInstr
);
8031 UChar b0
= ifieldBIT0(theInstr
);
8033 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8034 IRTemp t_EA
= newTemp(ty
);
8035 IRTemp t_nbytes
= IRTemp_INVALID
;
8039 if (opc1
!= 0x1F || b0
!= 0) {
8040 vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
8045 case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
8046 /* NB: does not reject the case where RA is in the range of
8047 registers to be loaded. It should. */
8048 DIP("lswi r%u,r%u,%d\n", rD_addr
, rA_addr
, NumBytes
);
8049 assign( t_EA
, ea_rAor0(rA_addr
) );
8050 if (NumBytes
== 8 && !mode64
) {
8051 /* Special case hack */
8052 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
8054 load(Ity_I32
, mkexpr(t_EA
)) );
8055 putIReg( (rD_addr
+1) % 32,
8057 binop(Iop_Add32
, mkexpr(t_EA
), mkU32(4))) );
8059 t_nbytes
= newTemp(Ity_I32
);
8060 assign( t_nbytes
, mkU32(NumBytes
==0 ? 32 : NumBytes
) );
8061 generate_lsw_sequence( t_nbytes
, t_EA
, rD_addr
, 32 );
8066 case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
8067 /* NB: does not reject the case where RA is in the range of
8068 registers to be loaded. It should. Although considering
8069 that that can only be detected at run time, it's not easy to
8071 if (rD_addr
== rA_addr
|| rD_addr
== rB_addr
)
8073 if (rD_addr
== 0 && rA_addr
== 0)
8075 DIP("lswx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
8076 t_nbytes
= newTemp(Ity_I32
);
8077 assign( t_EA
, ea_rAor0_idxd(rA_addr
,rB_addr
) );
8078 assign( t_nbytes
, unop( Iop_8Uto32
, getXER_BC() ) );
8079 generate_lsw_sequence( t_nbytes
, t_EA
, rD_addr
, 128 );
8083 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
8084 DIP("stswi r%u,r%u,%d\n", rS_addr
, rA_addr
, NumBytes
);
8085 assign( t_EA
, ea_rAor0(rA_addr
) );
8086 if (NumBytes
== 8 && !mode64
) {
8087 /* Special case hack */
8088 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
8089 store( mkexpr(t_EA
),
8091 store( binop(Iop_Add32
, mkexpr(t_EA
), mkU32(4)),
8092 getIReg((rD_addr
+1) % 32) );
8094 t_nbytes
= newTemp(Ity_I32
);
8095 assign( t_nbytes
, mkU32(NumBytes
==0 ? 32 : NumBytes
) );
8096 generate_stsw_sequence( t_nbytes
, t_EA
, rD_addr
, 32 );
8101 case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
8102 DIP("stswx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
8103 t_nbytes
= newTemp(Ity_I32
);
8104 assign( t_EA
, ea_rAor0_idxd(rA_addr
,rB_addr
) );
8105 assign( t_nbytes
, unop( Iop_8Uto32
, getXER_BC() ) );
8106 generate_stsw_sequence( t_nbytes
, t_EA
, rS_addr
, 128 );
8111 vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
8118 /* ------------------------------------------------------------------
8119 Integer Branch Instructions
8120 ------------------------------------------------------------------ */
8123 Branch helper function
8124 ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
8125 Returns an I32 which is 0x00000000 if the ctr condition failed
8126 and 0xFFFFFFFF otherwise.
8128 static IRExpr
* /* :: Ity_I32 */ branch_ctr_ok( UInt BO
)
8130 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8131 IRTemp ok
= newTemp(Ity_I32
);
8133 if ((BO
>> 2) & 1) { // independent of ctr
8134 assign( ok
, mkU32(0xFFFFFFFF) );
8136 if ((BO
>> 1) & 1) { // ctr == 0 ?
8137 assign( ok
, unop( Iop_1Sto32
,
8138 binop( mkSzOp(ty
, Iop_CmpEQ8
),
8139 getGST( PPC_GST_CTR
),
8141 } else { // ctr != 0 ?
8142 assign( ok
, unop( Iop_1Sto32
,
8143 binop( mkSzOp(ty
, Iop_CmpNE8
),
8144 getGST( PPC_GST_CTR
),
8153 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
8154 Returns an I32 which is either 0 if the condition failed or
8155 some arbitrary nonzero value otherwise. */
8157 static IRExpr
* /* :: Ity_I32 */ branch_cond_ok( UInt BO
, UInt BI
)
8160 IRTemp res
= newTemp(Ity_I32
);
8161 IRTemp cr_bi
= newTemp(Ity_I32
);
8163 if ((BO
>> 4) & 1) {
8164 assign( res
, mkU32(1) );
8166 // ok = (CR[BI] == BO[3]) Note, the following relies on
8167 // getCRbit_anywhere returning a value which
8168 // is either zero or has exactly 1 bit set.
8169 assign( cr_bi
, getCRbit_anywhere( BI
, &where
) );
8171 if ((BO
>> 3) & 1) {
8172 /* We can use cr_bi as-is. */
8173 assign( res
, mkexpr(cr_bi
) );
8175 /* We have to invert the sense of the information held in
8176 cr_bi. For that we need to know which bit
8177 getCRbit_anywhere regards as significant. */
8178 assign( res
, binop(Iop_Xor32
, mkexpr(cr_bi
),
8187 Integer Branch Instructions
8189 static Bool
dis_branch ( UInt theInstr
,
8190 const VexAbiInfo
* vbi
,
8191 /*OUT*/DisResult
* dres
)
8193 UChar opc1
= ifieldOPC(theInstr
);
8194 UChar BO
= ifieldRegDS(theInstr
);
8195 UChar BI
= ifieldRegA(theInstr
);
8196 UInt BD_u16
= ifieldUIMM16(theInstr
) & 0xFFFFFFFC; /* mask off */
8197 UChar b11to15
= ifieldRegB(theInstr
);
8198 UInt opc2
= ifieldOPClo10(theInstr
);
8199 UInt LI_u26
= ifieldUIMM26(theInstr
) & 0xFFFFFFFC; /* mask off */
8200 UChar flag_AA
= ifieldBIT1(theInstr
);
8201 UChar flag_LK
= ifieldBIT0(theInstr
);
8203 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8205 UInt BD
= extend_s_16to32(BD_u16
);
8206 IRTemp do_branch
= newTemp(Ity_I32
);
8207 IRTemp ctr_ok
= newTemp(Ity_I32
);
8208 IRTemp cond_ok
= newTemp(Ity_I32
);
8209 IRExpr
* e_nia
= mkSzImm(ty
, nextInsnAddr());
8210 IRConst
* c_nia
= mkSzConst(ty
, nextInsnAddr());
8211 IRTemp lr_old
= newTemp(ty
);
8213 /* Hack to pass through code that just wants to read the PC */
8214 if (theInstr
== 0x429F0005) {
8215 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO
, BI
);
8216 putGST( PPC_GST_LR
, e_nia
);
8220 /* The default what-next. Individual cases can override it. */
8221 dres
->whatNext
= Dis_StopHere
;
8222 vassert(dres
->jk_StopHere
== Ijk_INVALID
);
8225 case 0x12: // b (Branch, PPC32 p360)
8227 tgt
= mkSzAddr( ty
, extend_s_26to64(LI_u26
) );
8229 tgt
= mkSzAddr( ty
, guest_CIA_curr_instr
+
8230 (Long
)extend_s_26to64(LI_u26
) );
8233 DIP("b%s%s 0x%llx\n",
8234 flag_LK
? "l" : "", flag_AA
? "a" : "", tgt
);
8237 flag_LK
? "l" : "", flag_AA
? "a" : "", (Addr32
)tgt
);
8241 putGST( PPC_GST_LR
, e_nia
);
8242 if (vbi
->guest_ppc_zap_RZ_at_bl
8243 && vbi
->guest_ppc_zap_RZ_at_bl( (ULong
)tgt
) ) {
8244 IRTemp t_tgt
= newTemp(ty
);
8245 assign(t_tgt
, mode64
? mkU64(tgt
) : mkU32(tgt
) );
8246 make_redzone_AbiHint( vbi
, t_tgt
,
8247 "branch-and-link (unconditional call)" );
8251 dres
->jk_StopHere
= flag_LK
? Ijk_Call
: Ijk_Boring
; ;
8252 putGST( PPC_GST_CIA
, mkSzImm(ty
, tgt
) );
8255 case 0x10: // bc (Branch Conditional, PPC32 p361)
8256 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
8257 flag_LK
? "l" : "", flag_AA
? "a" : "", BO
, BI
, BD
);
8260 putGST( PPC_GST_CTR
,
8261 binop(mkSzOp(ty
, Iop_Sub8
),
8262 getGST( PPC_GST_CTR
), mkSzImm(ty
, 1)) );
8265 /* This is a bit subtle. ctr_ok is either all 0s or all 1s.
8266 cond_ok is either zero or nonzero, since that's the cheapest
8267 way to compute it. Anding them together gives a value which
8268 is either zero or non zero and so that's what we must test
8269 for in the IRStmt_Exit. */
8270 assign( ctr_ok
, branch_ctr_ok( BO
) );
8271 assign( cond_ok
, branch_cond_ok( BO
, BI
) );
8273 binop(Iop_And32
, mkexpr(cond_ok
), mkexpr(ctr_ok
)) );
8276 tgt
= mkSzAddr(ty
, extend_s_16to64(BD_u16
));
8278 tgt
= mkSzAddr(ty
, guest_CIA_curr_instr
+
8279 (Long
)extend_s_16to64(BD_u16
));
8282 putGST( PPC_GST_LR
, e_nia
);
8285 binop(Iop_CmpNE32
, mkexpr(do_branch
), mkU32(0)),
8286 flag_LK
? Ijk_Call
: Ijk_Boring
,
8287 mkSzConst(ty
, tgt
), OFFB_CIA
) );
8289 dres
->jk_StopHere
= Ijk_Boring
;
8290 putGST( PPC_GST_CIA
, e_nia
);
8294 /* For bclr and bcctr, it appears that the lowest two bits of
8295 b11to15 are a branch hint, and so we only need to ensure it's
8296 of the form 000XX. */
8297 if ((b11to15
& ~3) != 0) {
8298 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15
);
8303 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
8304 if ((BO
& 0x4) == 0) { // "decr and test CTR" option invalid
8305 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
8308 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK
? "l" : "", BO
, BI
);
8310 assign( cond_ok
, branch_cond_ok( BO
, BI
) );
8312 /* FIXME: this is confusing. lr_old holds the old value
8313 of ctr, not lr :-) */
8314 assign( lr_old
, addr_align( getGST( PPC_GST_CTR
), 4 ));
8317 putGST( PPC_GST_LR
, e_nia
);
8320 binop(Iop_CmpEQ32
, mkexpr(cond_ok
), mkU32(0)),
8324 if (flag_LK
&& vbi
->guest_ppc_zap_RZ_at_bl
) {
8325 make_redzone_AbiHint( vbi
, lr_old
,
8326 "b-ctr-l (indirect call)" );
8329 dres
->jk_StopHere
= flag_LK
? Ijk_Call
: Ijk_Boring
;;
8330 putGST( PPC_GST_CIA
, mkexpr(lr_old
) );
8333 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
8334 Bool vanilla_return
= False
;
8335 if ((BO
& 0x14 /* 1z1zz */) == 0x14 && flag_LK
== 0) {
8337 vanilla_return
= True
;
8339 DIP("bclr%s 0x%x, 0x%x\n", flag_LK
? "l" : "", BO
, BI
);
8343 putGST( PPC_GST_CTR
,
8344 binop(mkSzOp(ty
, Iop_Sub8
),
8345 getGST( PPC_GST_CTR
), mkSzImm(ty
, 1)) );
8348 /* See comments above for 'bc' about this */
8349 assign( ctr_ok
, branch_ctr_ok( BO
) );
8350 assign( cond_ok
, branch_cond_ok( BO
, BI
) );
8352 binop(Iop_And32
, mkexpr(cond_ok
), mkexpr(ctr_ok
)) );
8354 assign( lr_old
, addr_align( getGST( PPC_GST_LR
), 4 ));
8357 putGST( PPC_GST_LR
, e_nia
);
8360 binop(Iop_CmpEQ32
, mkexpr(do_branch
), mkU32(0)),
8364 if (vanilla_return
&& vbi
->guest_ppc_zap_RZ_at_blr
) {
8365 make_redzone_AbiHint( vbi
, lr_old
,
8366 "branch-to-lr (unconditional return)" );
8369 /* blrl is pretty strange; it's like a return that sets the
8370 return address of its caller to the insn following this
8371 one. Mark it as a return. */
8372 dres
->jk_StopHere
= Ijk_Ret
; /* was flag_LK ? Ijk_Call : Ijk_Ret; */
8373 putGST( PPC_GST_CIA
, mkexpr(lr_old
) );
8377 vex_printf("dis_int_branch(ppc)(opc2)\n");
8383 vex_printf("dis_int_branch(ppc)(opc1)\n");
8391 * PC relative instruction
8393 static Bool
dis_pc_relative ( UInt theInstr
)
8396 UChar opc1
= ifieldOPC(theInstr
);
8397 unsigned long long D
;
8398 UInt d0
= IFIELD(theInstr
, 6, 10);
8399 UInt d1
= IFIELD(theInstr
, 16, 5);
8400 UInt d2
= IFIELD(theInstr
, 0, 1);
8401 UChar rT_addr
= ifieldRegDS(theInstr
);
8402 UInt opc2
= ifieldOPClo5(theInstr
);
8403 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8405 if ( opc1
!= 0x13) {
8406 vex_printf("dis_pc_relative(ppc)(opc1)\n");
8411 case 0x002: // addpcis (Add PC immediate Shifted DX-form)
8413 IRExpr
* nia
= mkSzImm(ty
, nextInsnAddr());
8416 D
= (d0
<< 6) | (d1
<< 1) | d2
;
8417 DIP("addpcis %u,%llu\n", rT_addr
, D
);
8419 if ( (D
& 0x8000) == 0x8000 )
8420 D
= 0xFFFFFFFFFFFF0000UL
| D
; // sign extend
8422 if ( ty
== Ity_I32
) {
8423 result
= binop( Iop_Add32
, nia
, mkU32( D
<< 16 ) );
8425 vassert( ty
== Ity_I64
);
8426 result
= binop( Iop_Add64
, nia
, mkU64( D
<< 16 ) );
8429 putIReg( rT_addr
, result
);
8434 vex_printf("dis_pc_relative(ppc)(opc2)\n");
8442 Condition Register Logical Instructions
8444 static Bool
dis_cond_logic ( UInt theInstr
)
8447 UChar opc1
= ifieldOPC(theInstr
);
8448 UChar crbD_addr
= ifieldRegDS(theInstr
);
8449 UChar crfD_addr
= toUChar( IFIELD(theInstr
, 23, 3) );
8450 UChar crbA_addr
= ifieldRegA(theInstr
);
8451 UChar crfS_addr
= toUChar( IFIELD(theInstr
, 18, 3) );
8452 UChar crbB_addr
= ifieldRegB(theInstr
);
8453 UInt opc2
= ifieldOPClo10(theInstr
);
8454 UChar b0
= ifieldBIT0(theInstr
);
8456 IRTemp crbD
= newTemp(Ity_I32
);
8457 IRTemp crbA
= newTemp(Ity_I32
);
8458 IRTemp crbB
= newTemp(Ity_I32
);
8460 if (opc1
!= 19 || b0
!= 0) {
8461 vex_printf("dis_cond_logic(ppc)(opc1)\n");
8465 if (opc2
== 0) { // mcrf (Move Cond Reg Field, PPC32 p464)
8466 if (((crbD_addr
& 0x3) != 0) ||
8467 ((crbA_addr
& 0x3) != 0) || (crbB_addr
!= 0)) {
8468 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
8471 DIP("mcrf cr%u,cr%u\n", crfD_addr
, crfS_addr
);
8472 putCR0( crfD_addr
, getCR0( crfS_addr
) );
8473 putCR321( crfD_addr
, getCR321(crfS_addr
) );
8475 assign( crbA
, getCRbit(crbA_addr
) );
8476 if (crbA_addr
== crbB_addr
)
8479 assign( crbB
, getCRbit(crbB_addr
) );
8482 case 0x101: // crand (Cond Reg AND, PPC32 p372)
8483 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
8484 assign( crbD
, binop(Iop_And32
, mkexpr(crbA
), mkexpr(crbB
)) );
8486 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373)
8487 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
8488 assign( crbD
, binop(Iop_And32
,
8490 unop(Iop_Not32
, mkexpr(crbB
))) );
8492 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374)
8493 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
8494 assign( crbD
, unop(Iop_Not32
,
8495 binop(Iop_Xor32
, mkexpr(crbA
), mkexpr(crbB
))) );
8497 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375)
8498 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
8499 assign( crbD
, unop(Iop_Not32
,
8500 binop(Iop_And32
, mkexpr(crbA
), mkexpr(crbB
))) );
8502 case 0x021: // crnor (Cond Reg NOR, PPC32 p376)
8503 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
8504 assign( crbD
, unop(Iop_Not32
,
8505 binop(Iop_Or32
, mkexpr(crbA
), mkexpr(crbB
))) );
8507 case 0x1C1: // cror (Cond Reg OR, PPC32 p377)
8508 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
8509 assign( crbD
, binop(Iop_Or32
, mkexpr(crbA
), mkexpr(crbB
)) );
8511 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378)
8512 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
8513 assign( crbD
, binop(Iop_Or32
,
8515 unop(Iop_Not32
, mkexpr(crbB
))) );
8517 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379)
8518 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
8519 assign( crbD
, binop(Iop_Xor32
, mkexpr(crbA
), mkexpr(crbB
)) );
8522 vex_printf("dis_cond_logic(ppc)(opc2)\n");
8526 putCRbit( crbD_addr
, mkexpr(crbD
) );
8536 /* Do the code generation for a trap. Returned Bool is true iff
8537 this is an unconditional trap. If the two arg IRExpr*s are
8538 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s
8539 then they are 64-bit, and we must be disassembling 64-bit
8541 static Bool
do_trap ( UChar TO
,
8542 IRExpr
* argL0
, IRExpr
* argR0
, Addr64 cia
)
8545 IRExpr
*argLe
, *argRe
, *cond
, *tmp
;
8547 Bool is32bit
= typeOfIRExpr(irsb
->tyenv
, argL0
) == Ity_I32
;
8549 IROp opAND
= is32bit
? Iop_And32
: Iop_And64
;
8550 IROp opOR
= is32bit
? Iop_Or32
: Iop_Or64
;
8551 IROp opCMPORDS
= is32bit
? Iop_CmpORD32S
: Iop_CmpORD64S
;
8552 IROp opCMPORDU
= is32bit
? Iop_CmpORD32U
: Iop_CmpORD64U
;
8553 IROp opCMPNE
= is32bit
? Iop_CmpNE32
: Iop_CmpNE64
;
8554 IROp opCMPEQ
= is32bit
? Iop_CmpEQ32
: Iop_CmpEQ64
;
8555 IRExpr
* const0
= is32bit
? mkU32(0) : mkU64(0);
8556 IRExpr
* const2
= is32bit
? mkU32(2) : mkU64(2);
8557 IRExpr
* const4
= is32bit
? mkU32(4) : mkU64(4);
8558 IRExpr
* const8
= is32bit
? mkU32(8) : mkU64(8);
8560 const UChar b11100
= 0x1C;
8561 const UChar b00111
= 0x07;
8564 vassert( typeOfIRExpr(irsb
->tyenv
, argL0
) == Ity_I32
);
8565 vassert( typeOfIRExpr(irsb
->tyenv
, argR0
) == Ity_I32
);
8567 vassert( typeOfIRExpr(irsb
->tyenv
, argL0
) == Ity_I64
);
8568 vassert( typeOfIRExpr(irsb
->tyenv
, argR0
) == Ity_I64
);
8572 if ((TO
& b11100
) == b11100
|| (TO
& b00111
) == b00111
) {
8573 /* Unconditional trap. Just do the exit without
8574 testing the arguments. */
8576 binop(opCMPEQ
, const0
, const0
),
8578 mode64
? IRConst_U64(cia
) : IRConst_U32((UInt
)cia
),
8581 return True
; /* unconditional trap */
8585 argL
= newTemp(Ity_I32
);
8586 argR
= newTemp(Ity_I32
);
8588 argL
= newTemp(Ity_I64
);
8589 argR
= newTemp(Ity_I64
);
8592 assign( argL
, argL0
);
8593 assign( argR
, argR0
);
8595 argLe
= mkexpr(argL
);
8596 argRe
= mkexpr(argR
);
8599 if (TO
& 16) { // L <s R
8600 tmp
= binop(opAND
, binop(opCMPORDS
, argLe
, argRe
), const8
);
8601 cond
= binop(opOR
, tmp
, cond
);
8603 if (TO
& 8) { // L >s R
8604 tmp
= binop(opAND
, binop(opCMPORDS
, argLe
, argRe
), const4
);
8605 cond
= binop(opOR
, tmp
, cond
);
8607 if (TO
& 4) { // L == R
8608 tmp
= binop(opAND
, binop(opCMPORDS
, argLe
, argRe
), const2
);
8609 cond
= binop(opOR
, tmp
, cond
);
8611 if (TO
& 2) { // L <u R
8612 tmp
= binop(opAND
, binop(opCMPORDU
, argLe
, argRe
), const8
);
8613 cond
= binop(opOR
, tmp
, cond
);
8615 if (TO
& 1) { // L >u R
8616 tmp
= binop(opAND
, binop(opCMPORDU
, argLe
, argRe
), const4
);
8617 cond
= binop(opOR
, tmp
, cond
);
8620 binop(opCMPNE
, cond
, const0
),
8622 mode64
? IRConst_U64(cia
) : IRConst_U32((UInt
)cia
),
8625 return False
; /* not an unconditional trap */
8628 static Bool
dis_trapi ( UInt theInstr
,
8629 /*OUT*/DisResult
* dres
)
8632 UChar opc1
= ifieldOPC(theInstr
);
8633 UChar TO
= ifieldRegDS(theInstr
);
8634 UChar rA_addr
= ifieldRegA(theInstr
);
8635 UInt uimm16
= ifieldUIMM16(theInstr
);
8636 ULong simm16
= extend_s_16to64(uimm16
);
8637 Addr64 cia
= guest_CIA_curr_instr
;
8638 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8639 Bool uncond
= False
;
8642 case 0x03: // twi (Trap Word Immediate, PPC32 p548)
8643 uncond
= do_trap( TO
,
8644 mode64
? unop(Iop_64to32
, getIReg(rA_addr
))
8646 mkU32( (UInt
)simm16
),
8649 DIP("tweqi r%u,%d\n", rA_addr
, (Int
)simm16
);
8651 DIP("tw%di r%u,%d\n", TO
, rA_addr
, (Int
)simm16
);
8657 uncond
= do_trap( TO
, getIReg(rA_addr
), mkU64( (ULong
)simm16
), cia
);
8659 DIP("tdeqi r%u,%d\n", rA_addr
, (Int
)simm16
);
8661 DIP("td%di r%u,%d\n", TO
, rA_addr
, (Int
)simm16
);
8669 /* If the trap shows signs of being unconditional, don't
8670 continue decoding past it. */
8671 putGST( PPC_GST_CIA
, mkSzImm( ty
, nextInsnAddr() ));
8672 dres
->jk_StopHere
= Ijk_Boring
;
8673 dres
->whatNext
= Dis_StopHere
;
8679 static Bool
dis_trap ( UInt theInstr
,
8680 /*OUT*/DisResult
* dres
)
8683 UInt opc2
= ifieldOPClo10(theInstr
);
8684 UChar TO
= ifieldRegDS(theInstr
);
8685 UChar rA_addr
= ifieldRegA(theInstr
);
8686 UChar rB_addr
= ifieldRegB(theInstr
);
8687 Addr64 cia
= guest_CIA_curr_instr
;
8688 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8689 Bool uncond
= False
;
8691 if (ifieldBIT0(theInstr
) != 0)
8695 case 0x004: // tw (Trap Word, PPC64 p540)
8696 uncond
= do_trap( TO
,
8697 mode64
? unop(Iop_64to32
, getIReg(rA_addr
))
8699 mode64
? unop(Iop_64to32
, getIReg(rB_addr
))
8703 DIP("tweq r%u,r%u\n", rA_addr
, rB_addr
);
8705 DIP("tw%d r%u,r%u\n", TO
, rA_addr
, rB_addr
);
8708 case 0x044: // td (Trap Doubleword, PPC64 p534)
8711 uncond
= do_trap( TO
, getIReg(rA_addr
), getIReg(rB_addr
), cia
);
8713 DIP("tdeq r%u,r%u\n", rA_addr
, rB_addr
);
8715 DIP("td%d r%u,r%u\n", TO
, rA_addr
, rB_addr
);
8723 /* If the trap shows signs of being unconditional, don't
8724 continue decoding past it. */
8725 putGST( PPC_GST_CIA
, mkSzImm( ty
, nextInsnAddr() ));
8726 dres
->jk_StopHere
= Ijk_Boring
;
8727 dres
->whatNext
= Dis_StopHere
;
8735 System Linkage Instructions
8737 static Bool
dis_syslink ( UInt theInstr
,
8738 const VexAbiInfo
* abiinfo
, DisResult
* dres
)
8740 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8742 if (theInstr
!= 0x44000002) {
8743 vex_printf("dis_syslink(ppc)(theInstr)\n");
8747 // sc (System Call, PPC32 p504)
8750 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
8751 Valgrind can back the guest up to this instruction if it needs
8752 to restart the syscall. */
8753 putGST( PPC_GST_IP_AT_SYSCALL
, getGST( PPC_GST_CIA
) );
8755 /* It's important that all ArchRegs carry their up-to-date value
8756 at this point. So we declare an end-of-block here, which
8757 forces any TempRegs caching ArchRegs to be flushed. */
8758 putGST( PPC_GST_CIA
, mkSzImm( ty
, nextInsnAddr() ));
8760 dres
->whatNext
= Dis_StopHere
;
8761 dres
->jk_StopHere
= Ijk_Sys_syscall
;
8767 Memory Synchronization Instructions
8769 Note on Reservations:
8770 We rely on the assumption that V will in fact only allow one thread at
8771 once to run. In effect, a thread can make a reservation, but we don't
8772 check any stores it does. Instead, the reservation is cancelled when
8773 the scheduler switches to another thread (run_thread_for_a_while()).
8775 static Bool
dis_memsync ( UInt theInstr
)
8777 /* X-Form, XL-Form */
8778 UChar opc1
= ifieldOPC(theInstr
);
8779 UInt b11to25
= IFIELD(theInstr
, 11, 15);
8780 UChar flag_L
= IFIELD(theInstr
, 21, 2); //ISA 3.0
8781 UInt b11to20
= IFIELD(theInstr
, 11, 10);
8782 UInt M0
= IFIELD(theInstr
, 11, 5);
8783 UChar rD_addr
= ifieldRegDS(theInstr
);
8784 UChar rS_addr
= rD_addr
;
8785 UChar rA_addr
= ifieldRegA(theInstr
);
8786 UChar rB_addr
= ifieldRegB(theInstr
);
8787 UInt opc2
= ifieldOPClo10(theInstr
);
8788 UChar b0
= ifieldBIT0(theInstr
);
8790 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8791 IRTemp EA
= newTemp(ty
);
8793 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
8797 case 0x13: // isync (Instruction Synchronize, PPC32 p432)
8798 if (opc2
!= 0x096) {
8799 vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
8802 if (b11to25
!= 0 || b0
!= 0) {
8803 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
8807 stmt( IRStmt_MBE(Imbe_Fence
) );
8813 case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394)
8815 if (b11to20
!= 0 || b0
!= 0) {
8816 vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n");
8821 if (b11to20
!= 0 || b0
!= 0) {
8822 vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n");
8825 DIP("mbar %u\n", M0
);
8827 /* Insert a memory fence, just to be on the safe side. */
8828 stmt( IRStmt_MBE(Imbe_Fence
) );
8831 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
8833 /* According to the PowerPC ISA version 2.05, b0 (called EH
8834 in the documentation) is merely a hint bit to the
8835 hardware, I think as to whether or not contention is
8836 likely. So we can just ignore it. */
8837 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr
, rA_addr
, rB_addr
, b0
);
8839 // trap if misaligned
8840 gen_SIGBUS_if_misaligned( EA
, 4 );
8842 // and actually do the load
8843 res
= newTemp(Ity_I32
);
8844 stmt( stmt_load(res
, mkexpr(EA
), NULL
/*this is a load*/) );
8846 putIReg( rD_addr
, mkWidenFrom32(ty
, mkexpr(res
), False
) );
8850 case 0x034: { // lbarx (Load Word and Reserve Indexed)
8852 /* According to the PowerPC ISA version 2.05, b0 (called EH
8853 in the documentation) is merely a hint bit to the
8854 hardware, I think as to whether or not contention is
8855 likely. So we can just ignore it. */
8856 DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr
, rA_addr
, rB_addr
, b0
);
8858 // and actually do the load
8859 res
= newTemp(Ity_I8
);
8860 stmt( stmt_load(res
, mkexpr(EA
), NULL
/*this is a load*/) );
8862 putIReg( rD_addr
, mkWidenFrom8(ty
, mkexpr(res
), False
) );
8866 case 0x074: { // lharx (Load Word and Reserve Indexed)
8868 /* According to the PowerPC ISA version 2.05, b0 (called EH
8869 in the documentation) is merely a hint bit to the
8870 hardware, I think as to whether or not contention is
8871 likely. So we can just ignore it. */
8872 DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr
, rA_addr
, rB_addr
, b0
);
8874 // trap if misaligned
8875 gen_SIGBUS_if_misaligned( EA
, 2 );
8877 // and actually do the load
8878 res
= newTemp(Ity_I16
);
8879 stmt( stmt_load(res
, mkexpr(EA
), NULL
/*this is a load*/) );
8881 putIReg( rD_addr
, mkWidenFrom16(ty
, mkexpr(res
), False
) );
8886 // stwcx. (Store Word Conditional Indexed, PPC32 p532)
8887 // Note this has to handle stwcx. in both 32- and 64-bit modes,
8888 // so isn't quite as straightforward as it might otherwise be.
8889 IRTemp rS
= newTemp(Ity_I32
);
8892 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
8895 DIP("stwcx. r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
8897 // trap if misaligned
8898 gen_SIGBUS_if_misaligned( EA
, 4 );
8900 // Get the data to be stored, and narrow to 32 bits if necessary
8901 assign( rS
, mkNarrowTo32(ty
, getIReg(rS_addr
)) );
8903 // Do the store, and get success/failure bit into resSC
8904 resSC
= newTemp(Ity_I1
);
8905 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS
)) );
8907 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
8908 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
8909 putCR321(0, binop(Iop_Shl8
, unop(Iop_1Uto8
, mkexpr(resSC
)), mkU8(1)));
8910 putCR0(0, getXER_SO());
8913 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
8914 whether rS is stored is dependent on that value. */
8915 /* So I guess we can just ignore this case? */
8920 // stbcx. (Store Byte Conditional Indexed)
8921 // Note this has to handle stbcx. in both 32- and 64-bit modes,
8922 // so isn't quite as straightforward as it might otherwise be.
8923 IRTemp rS
= newTemp(Ity_I8
);
8926 vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
8929 DIP("stbcx. r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
8931 // Get the data to be stored, and narrow to 32 bits if necessary
8932 assign( rS
, mkNarrowTo8(ty
, getIReg(rS_addr
)) );
8934 // Do the store, and get success/failure bit into resSC
8935 resSC
= newTemp(Ity_I1
);
8936 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS
)) );
8938 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
8939 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
8940 putCR321(0, binop(Iop_Shl8
, unop(Iop_1Uto8
, mkexpr(resSC
)), mkU8(1)));
8941 putCR0(0, getXER_SO());
8944 If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and
8945 whether rS is stored is dependent on that value. */
8946 /* So I guess we can just ignore this case? */
8951 // sthcx. (Store Word Conditional Indexed, PPC32 p532)
8952 // Note this has to handle sthcx. in both 32- and 64-bit modes,
8953 // so isn't quite as straightforward as it might otherwise be.
8954 IRTemp rS
= newTemp(Ity_I16
);
8957 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
8960 DIP("sthcx. r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
8962 // trap if misaligned
8963 gen_SIGBUS_if_misaligned( EA
, 2 );
8965 // Get the data to be stored, and narrow to 16 bits if necessary
8966 assign( rS
, mkNarrowTo16(ty
, getIReg(rS_addr
)) );
8968 // Do the store, and get success/failure bit into resSC
8969 resSC
= newTemp(Ity_I1
);
8970 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS
)) );
8972 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
8973 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
8974 putCR321(0, binop(Iop_Shl8
, unop(Iop_1Uto8
, mkexpr(resSC
)), mkU8(1)));
8975 putCR0(0, getXER_SO());
8978 If resaddr != lharx_resaddr, CR0[EQ] is undefined, and
8979 whether rS is stored is dependent on that value. */
8980 /* So I guess we can just ignore this case? */
8984 case 0x256: // sync (Synchronize, PPC32 p543),
8985 // also lwsync (L==1), ptesync (L==2)
8986 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
8988 The PowerPC architecture used in IBM chips has expanded
8989 the sync instruction into two variants: lightweight sync
8990 and heavyweight sync. The original sync instruction is
8991 the new heavyweight sync and lightweight sync is a strict
8992 subset of the heavyweight sync functionality. This allows
8993 the programmer to specify a less expensive operation on
8994 high-end systems when the full sync functionality is not
8997 The basic "sync" mnemonic now utilizes an operand. "sync"
8998 without an operand now becomes a extended mnemonic for
8999 heavyweight sync. Processors without the lwsync
9000 instruction will not decode the L field and will perform a
9001 heavyweight sync. Everything is backward compatible.
9005 ptesync = sync 2 *** TODO - not implemented ***
9007 if (b11to20
!= 0 || b0
!= 0) {
9008 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
9011 if (flag_L
!= 0/*sync*/ && flag_L
!= 1/*lwsync*/) {
9012 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
9015 DIP("%ssync\n", flag_L
== 1 ? "lw" : "");
9016 /* Insert a memory fence. It's sometimes important that these
9017 are carried through to the generated code. */
9018 stmt( IRStmt_MBE(Imbe_Fence
) );
9022 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
9024 /* According to the PowerPC ISA version 2.05, b0 (called EH
9025 in the documentation) is merely a hint bit to the
9026 hardware, I think as to whether or not contention is
9027 likely. So we can just ignore it. */
9030 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr
, rA_addr
, rB_addr
, b0
);
9032 // trap if misaligned
9033 gen_SIGBUS_if_misaligned( EA
, 8 );
9035 // and actually do the load
9036 res
= newTemp(Ity_I64
);
9037 stmt( stmt_load( res
, mkexpr(EA
), NULL
/*this is a load*/) );
9039 putIReg( rD_addr
, mkexpr(res
) );
9043 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
9044 // A marginally simplified version of the stwcx. case
9045 IRTemp rS
= newTemp(Ity_I64
);
9048 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
9053 DIP("stdcx. r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9055 // trap if misaligned
9056 gen_SIGBUS_if_misaligned( EA
, 8 );
9058 // Get the data to be stored
9059 assign( rS
, getIReg(rS_addr
) );
9061 // Do the store, and get success/failure bit into resSC
9062 resSC
= newTemp(Ity_I1
);
9063 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS
)) );
9065 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
9066 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
9067 putCR321(0, binop(Iop_Shl8
, unop(Iop_1Uto8
, mkexpr(resSC
)), mkU8(1)));
9068 putCR0(0, getXER_SO());
9071 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
9072 whether rS is stored is dependent on that value. */
9073 /* So I guess we can just ignore this case? */
9077 /* 128bit Memsync */
9078 case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
9079 IRTemp res_hi
= newTemp(ty
);
9080 IRTemp res_lo
= newTemp(ty
);
9082 /* According to the PowerPC ISA version 2.07, b0 (called EH
9083 in the documentation) is merely a hint bit to the
9084 hardware, I think as to whether or not contention is
9085 likely. So we can just ignore it. */
9086 DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr
, rA_addr
, rB_addr
, b0
);
9088 // trap if misaligned
9089 gen_SIGBUS_if_misaligned( EA
, 16 );
9091 // and actually do the load
9093 if (host_endness
== VexEndnessBE
) {
9094 stmt( stmt_load( res_hi
,
9095 mkexpr(EA
), NULL
/*this is a load*/) );
9096 stmt( stmt_load( res_lo
,
9097 binop(Iop_Add64
, mkexpr(EA
), mkU64(8) ),
9098 NULL
/*this is a load*/) );
9100 stmt( stmt_load( res_lo
,
9101 mkexpr(EA
), NULL
/*this is a load*/) );
9102 stmt( stmt_load( res_hi
,
9103 binop(Iop_Add64
, mkexpr(EA
), mkU64(8) ),
9104 NULL
/*this is a load*/) );
9107 stmt( stmt_load( res_hi
,
9108 binop( Iop_Add32
, mkexpr(EA
), mkU32(4) ),
9109 NULL
/*this is a load*/) );
9110 stmt( stmt_load( res_lo
,
9111 binop( Iop_Add32
, mkexpr(EA
), mkU32(12) ),
9112 NULL
/*this is a load*/) );
9114 putIReg( rD_addr
, mkexpr(res_hi
) );
9115 putIReg( rD_addr
+1, mkexpr(res_lo
) );
9119 case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
9120 // A marginally simplified version of the stwcx. case
9121 IRTemp rS_hi
= newTemp(ty
);
9122 IRTemp rS_lo
= newTemp(ty
);
9125 vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
9129 DIP("stqcx. r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9131 // trap if misaligned
9132 gen_SIGBUS_if_misaligned( EA
, 16 );
9133 // Get the data to be stored
9134 assign( rS_hi
, getIReg(rS_addr
) );
9135 assign( rS_lo
, getIReg(rS_addr
+1) );
9137 // Do the store, and get success/failure bit into resSC
9138 resSC
= newTemp(Ity_I1
);
9141 if (host_endness
== VexEndnessBE
) {
9142 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS_hi
) ) );
9143 store( binop( Iop_Add64
, mkexpr(EA
), mkU64(8) ),
9146 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS_lo
) ) );
9147 store( binop( Iop_Add64
, mkexpr(EA
), mkU64(8) ),
9151 stmt( stmt_load( resSC
, binop( Iop_Add32
,
9155 store( binop(Iop_Add32
, mkexpr(EA
), mkU32(12) ), mkexpr(rS_lo
) );
9158 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
9159 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
9160 putCR321(0, binop( Iop_Shl8
,
9161 unop(Iop_1Uto8
, mkexpr(resSC
) ),
9163 putCR0(0, getXER_SO());
9168 vex_printf("dis_memsync(ppc)(opc2)\n");
9174 vex_printf("dis_memsync(ppc)(opc1)\n");
9183 Integer Shift Instructions
9185 static Bool
dis_int_shift ( UInt theInstr
)
9187 /* X-Form, XS-Form */
9188 UChar opc1
= ifieldOPC(theInstr
);
9189 UChar rS_addr
= ifieldRegDS(theInstr
);
9190 UChar rA_addr
= ifieldRegA(theInstr
);
9191 UChar rB_addr
= ifieldRegB(theInstr
);
9192 UChar sh_imm
= rB_addr
;
9193 UInt opc2
= ifieldOPClo10(theInstr
);
9194 UChar b1
= ifieldBIT1(theInstr
);
9195 UChar flag_rC
= ifieldBIT0(theInstr
);
9197 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
9198 IRTemp rA
= newTemp(ty
);
9199 IRTemp rS
= newTemp(ty
);
9200 IRTemp rB
= newTemp(ty
);
9201 IRTemp outofrange
= newTemp(Ity_I1
);
9202 IRTemp rS_lo32
= newTemp(Ity_I32
);
9203 IRTemp rB_lo32
= newTemp(Ity_I32
);
9206 assign( rS
, getIReg(rS_addr
) );
9207 assign( rB
, getIReg(rB_addr
) );
9208 assign( rS_lo32
, mkNarrowTo32(ty
, mkexpr(rS
)) );
9209 assign( rB_lo32
, mkNarrowTo32(ty
, mkexpr(rB
)) );
9213 case 0x018: { // slw (Shift Left Word, PPC32 p505)
9214 DIP("slw%s r%u,r%u,r%u\n", flag_rC
? ".":"",
9215 rA_addr
, rS_addr
, rB_addr
);
9217 /* ppc32 semantics are:
9218 slw(x,y) = (x << (y & 31)) -- primary result
9219 & ~((y << 26) >>s 31) -- make result 0
9228 mkexpr(rB_lo32
), mkU32(31)))),
9231 binop(Iop_Shl32
, mkexpr(rB_lo32
), mkU8(26)),
9233 assign( rA
, mkWidenFrom32(ty
, e_tmp
, /* Signed */False
) );
9237 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
9238 IRTemp sh_amt
= newTemp(Ity_I32
);
9239 DIP("sraw%s r%u,r%u,r%u\n", flag_rC
? ".":"",
9240 rA_addr
, rS_addr
, rB_addr
);
9241 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
9243 rA = Sar32( rS, amt > 31 ? 31 : amt )
9244 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
9246 assign( sh_amt
, binop(Iop_And32
, mkU32(0x3F),
9249 binop(Iop_CmpLT32U
, mkU32(31), mkexpr(sh_amt
)) );
9250 e_tmp
= binop( Iop_Sar32
,
9253 IRExpr_ITE( mkexpr(outofrange
),
9255 mkexpr(sh_amt
)) ) );
9256 assign( rA
, mkWidenFrom32(ty
, e_tmp
, /* Signed */True
) );
9258 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SRAW
,
9260 mkWidenFrom32(ty
, mkexpr(rS_lo32
), True
),
9261 mkWidenFrom32(ty
, mkexpr(sh_amt
), True
),
9262 mkWidenFrom32(ty
, getXER_CA_32(), True
) );
9266 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
9267 DIP("srawi%s r%u,r%u,%d\n", flag_rC
? ".":"",
9268 rA_addr
, rS_addr
, sh_imm
);
9269 vassert(sh_imm
< 32);
9271 assign( rA
, binop(Iop_Sar64
,
9272 binop(Iop_Shl64
, getIReg(rS_addr
),
9274 mkU8(32 + sh_imm
)) );
9276 assign( rA
, binop(Iop_Sar32
, mkexpr(rS_lo32
),
9280 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SRAWI
,
9282 mkWidenFrom32(ty
, mkexpr(rS_lo32
), /* Syned */True
),
9283 mkSzImm(ty
, sh_imm
),
9284 mkWidenFrom32(ty
, getXER_CA_32(), /* Syned */False
) );
9287 case 0x218: // srw (Shift Right Word, PPC32 p508)
9288 DIP("srw%s r%u,r%u,r%u\n", flag_rC
? ".":"",
9289 rA_addr
, rS_addr
, rB_addr
);
9290 /* rA = rS >>u rB */
9291 /* ppc32 semantics are:
9292 srw(x,y) = (x >>u (y & 31)) -- primary result
9293 & ~((y << 26) >>s 31) -- make result 0
9302 binop(Iop_And32
, mkexpr(rB_lo32
),
9306 binop(Iop_Shl32
, mkexpr(rB_lo32
),
9309 assign( rA
, mkWidenFrom32(ty
, e_tmp
, /* Signed */False
) );
9314 case 0x01B: // sld (Shift Left DWord, PPC64 p568)
9315 DIP("sld%s r%u,r%u,r%u\n",
9316 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
9318 /* ppc64 semantics are:
9319 slw(x,y) = (x << (y & 63)) -- primary result
9320 & ~((y << 57) >>s 63) -- make result 0
9329 binop(Iop_And64
, mkexpr(rB
), mkU64(63)))),
9332 binop(Iop_Shl64
, mkexpr(rB
), mkU8(57)),
9336 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
9337 IRTemp sh_amt
= newTemp(Ity_I64
);
9338 DIP("srad%s r%u,r%u,r%u\n",
9339 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
9341 rA = Sar64( rS, amt > 63 ? 63 : amt )
9342 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
9344 assign( sh_amt
, binop(Iop_And64
, mkU64(0x7F), mkexpr(rB
)) );
9346 binop(Iop_CmpLT64U
, mkU64(63), mkexpr(sh_amt
)) );
9351 IRExpr_ITE( mkexpr(outofrange
),
9355 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SRAD
,
9356 mkexpr(rA
), mkexpr(rS
), mkexpr(sh_amt
),
9357 mkWidenFrom32(ty
, getXER_CA_32(), /* Syned */False
) );
9361 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
9363 vassert(sh_imm
< 64);
9364 DIP("sradi%s r%u,r%u,%u\n",
9365 flag_rC
? ".":"", rA_addr
, rS_addr
, sh_imm
);
9366 assign( rA
, binop(Iop_Sar64
, getIReg(rS_addr
), mkU8(sh_imm
)) );
9368 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SRADI
,
9372 mkWidenFrom32(ty
, getXER_CA_32(), /* Syned */False
) );
9375 case 0x21B: // srd (Shift Right DWord, PPC64 p574)
9376 DIP("srd%s r%u,r%u,r%u\n",
9377 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
9378 /* rA = rS >>u rB */
9379 /* ppc semantics are:
9380 srw(x,y) = (x >>u (y & 63)) -- primary result
9381 & ~((y << 57) >>s 63) -- make result 0
9390 binop(Iop_And64
, mkexpr(rB
), mkU64(63)))),
9393 binop(Iop_Shl64
, mkexpr(rB
), mkU8(57)),
9398 vex_printf("dis_int_shift(ppc)(opc2)\n");
9402 vex_printf("dis_int_shift(ppc)(opc1)\n");
9406 putIReg( rA_addr
, mkexpr(rA
) );
9409 set_CR0( mkexpr(rA
) );
9417 Integer Load/Store Reverse Instructions
9419 /* Generates code to swap the byte order in an Ity_I32. */
9420 static IRExpr
* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t
)
9422 vassert(typeOfIRTemp(irsb
->tyenv
, t
) == Ity_I32
);
9423 return unop(Iop_Reverse8sIn32_x1
, mkexpr(t
));
9426 /* Generates code to swap the byte order in the lower half of an Ity_I32,
9427 and zeroes the upper half. */
9428 static IRExpr
* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t
)
9430 vassert(typeOfIRTemp(irsb
->tyenv
, t
) == Ity_I32
);
9433 binop(Iop_And32
, binop(Iop_Shl32
, mkexpr(t
), mkU8(8)),
9435 binop(Iop_And32
, binop(Iop_Shr32
, mkexpr(t
), mkU8(8)),
9440 static Bool
dis_int_ldst_rev ( UInt theInstr
)
9443 UChar opc1
= ifieldOPC(theInstr
);
9444 UChar rD_addr
= ifieldRegDS(theInstr
);
9445 UChar rS_addr
= rD_addr
;
9446 UChar rA_addr
= ifieldRegA(theInstr
);
9447 UChar rB_addr
= ifieldRegB(theInstr
);
9448 UInt opc2
= ifieldOPClo10(theInstr
);
9449 UChar b0
= ifieldBIT0(theInstr
);
9451 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
9452 IRTemp EA
= newTemp(ty
);
9453 IRTemp w1
= newTemp(Ity_I32
);
9454 IRTemp w2
= newTemp(Ity_I32
);
9456 if (opc1
!= 0x1F || b0
!= 0) {
9457 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
9461 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
9465 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
9466 DIP("lhbrx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9467 assign( w1
, unop(Iop_16Uto32
, load(Ity_I16
, mkexpr(EA
))) );
9468 assign( w2
, gen_byterev16(w1
) );
9469 putIReg( rD_addr
, mkWidenFrom32(ty
, mkexpr(w2
),
9470 /* Signed */False
) );
9473 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
9474 DIP("lwbrx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9475 assign( w1
, load(Ity_I32
, mkexpr(EA
)) );
9476 assign( w2
, gen_byterev32(w1
) );
9477 putIReg( rD_addr
, mkWidenFrom32(ty
, mkexpr(w2
),
9478 /* Signed */False
) );
9481 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
9483 /* Caller makes sure we are only called in mode64. */
9485 /* If we supported swapping LE/BE loads in the backend then we could
9486 just load the value with the bytes reversed by doing a BE load
9487 on an LE machine and a LE load on a BE machine.
9489 IRTemp dw1 = newTemp(Ity_I64);
9490 if (host_endness == VexEndnessBE)
9491 assign( dw1, IRExpr_Load(Iend_LE, Ity_I64, mkexpr(EA)));
9493 assign( dw1, IRExpr_Load(Iend_BE, Ity_I64, mkexpr(EA)));
9494 putIReg( rD_addr, mkexpr(dw1) );
9496 But since we currently don't we load the value as is and then
9497 switch it around with Iop_Reverse8sIn64_x1. */
9499 IRTemp dw1
= newTemp(Ity_I64
);
9500 IRTemp dw2
= newTemp(Ity_I64
);
9501 DIP("ldbrx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9502 assign( dw1
, load(Ity_I64
, mkexpr(EA
)) );
9503 assign( dw2
, unop(Iop_Reverse8sIn64_x1
, mkexpr(dw1
)) );
9504 putIReg( rD_addr
, mkexpr(dw2
) );
9508 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
9509 DIP("sthbrx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9510 assign( w1
, mkNarrowTo32(ty
, getIReg(rS_addr
)) );
9511 store( mkexpr(EA
), unop(Iop_32to16
, gen_byterev16(w1
)) );
9514 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
9515 DIP("stwbrx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9516 assign( w1
, mkNarrowTo32(ty
, getIReg(rS_addr
)) );
9517 store( mkexpr(EA
), gen_byterev32(w1
) );
9520 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
9522 IRTemp lo
= newTemp(Ity_I32
);
9523 IRTemp hi
= newTemp(Ity_I32
);
9524 IRTemp rS
= newTemp(Ity_I64
);
9525 assign( rS
, getIReg( rS_addr
) );
9526 DIP("stdbrx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9527 assign(lo
, unop(Iop_64HIto32
, mkexpr(rS
)));
9528 assign(hi
, unop(Iop_64to32
, mkexpr(rS
)));
9529 store( mkexpr( EA
),
9530 binop( Iop_32HLto64
, gen_byterev32( hi
),
9531 gen_byterev32( lo
) ) );
9536 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
9545 Processor Control Instructions
9547 static Bool
dis_proc_ctl ( const VexAbiInfo
* vbi
, UInt theInstr
)
9549 UChar opc1
= ifieldOPC(theInstr
);
9552 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
9553 UChar b21to22
= toUChar( IFIELD( theInstr
, 21, 2 ) );
9554 UChar rD_addr
= ifieldRegDS(theInstr
);
9555 UInt b11to20
= IFIELD( theInstr
, 11, 10 );
9558 UChar rS_addr
= rD_addr
;
9561 UChar b20
= toUChar( IFIELD( theInstr
, 20, 1 ) );
9562 UInt CRM
= IFIELD( theInstr
, 12, 8 );
9563 UChar b11
= toUChar( IFIELD( theInstr
, 11, 1 ) );
9565 UInt opc2
= ifieldOPClo10(theInstr
);
9566 UChar b0
= ifieldBIT0(theInstr
);
9568 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
9569 IRTemp rS
= newTemp(ty
);
9570 assign( rS
, getIReg(rS_addr
) );
9572 /* Reorder SPR field as per PPC32 p470 */
9573 SPR
= ((SPR
& 0x1F) << 5) | ((SPR
>> 5) & 0x1F);
9574 /* Reorder TBR field as per PPC32 p475 */
9575 TBR
= ((TBR
& 31) << 5) | ((TBR
>> 5) & 31);
9577 /* b0 = 0, inst is treated as floating point inst for reservation purposes
9578 * b0 = 1, inst is treated as vector inst for reservation purposes
9581 vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0
);
9587 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
9588 if (b21to22
!= 0 || b11to20
!= 0) {
9589 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
9592 DIP("mcrxr crf%d\n", crfD
);
9593 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
9594 putGST_field( PPC_GST_CR
,
9595 getGST_field( PPC_GST_XER
, 7 ),
9599 putXER_SO( mkU8(0) );
9600 putXER_OV( mkU8(0) );
9601 putXER_CA( mkU8(0) );
9606 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467)
9607 // b20==1 & b11==0: mfocrf (Move from One CR Field)
9608 // However it seems that the 'mfcr' behaviour is an acceptable
9609 // implementation of mfocr (from the 2.02 arch spec)
9611 DIP("mfcr r%u\n", rD_addr
);
9612 putIReg( rD_addr
, mkWidenFrom32(ty
, getGST( PPC_GST_CR
),
9613 /* Signed */False
) );
9616 if (b20
== 1 && b11
== 0) {
9617 DIP("mfocrf r%u,%u\n", rD_addr
, CRM
);
9618 putIReg( rD_addr
, mkWidenFrom32(ty
, getGST( PPC_GST_CR
),
9619 /* Signed */False
) );
9626 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
9628 switch (SPR
) { // Choose a register...
9630 DIP("mfxer r%u\n", rD_addr
);
9631 putIReg( rD_addr
, mkWidenFrom32(ty
, getGST( PPC_GST_XER
),
9632 /* Signed */False
) );
9635 DIP("mfspr r%u (DSCR)\n", rD_addr
);
9636 putIReg( rD_addr
, getGST( PPC_GST_DSCR
) );
9639 DIP("mflr r%u\n", rD_addr
);
9640 putIReg( rD_addr
, getGST( PPC_GST_LR
) );
9643 DIP("mfctr r%u\n", rD_addr
);
9644 putIReg( rD_addr
, getGST( PPC_GST_CTR
) );
9647 DIP("mfspr r%u (TFHAR)\n", rD_addr
);
9648 putIReg( rD_addr
, getGST( PPC_GST_TFHAR
) );
9651 DIP("mfspr r%u (TFIAR)\n", rD_addr
);
9652 putIReg( rD_addr
, getGST( PPC_GST_TFIAR
) );
9655 DIP("mfspr r%u (TEXASR)\n", rD_addr
);
9656 putIReg( rD_addr
, getGST( PPC_GST_TEXASR
) );
9659 DIP("mfspr r%u (TEXASRU)\n", rD_addr
);
9660 putIReg( rD_addr
, getGST( PPC_GST_TEXASRU
) );
9663 DIP("mfspr r%u (PSPB)\n", rD_addr
);
9664 putIReg( rD_addr
, getGST( PPC_GST_PSPB
) );
9667 DIP("mfspr r%u (PPR)\n", rD_addr
);
9668 putIReg( rD_addr
, getGST( PPC_GST_PPR
) );
9671 DIP("mfspr r%u (PPR)32\n", rD_addr
);
9672 putIReg( rD_addr
, getGST( PPC_GST_PPR32
) );
9675 DIP("mfvrsave r%u\n", rD_addr
);
9676 putIReg( rD_addr
, mkWidenFrom32(ty
, getGST( PPC_GST_VRSAVE
),
9677 /* Signed */False
) );
9681 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr
);
9682 putIReg( rD_addr
, getGST( PPC_GST_SPRG3_RO
) );
9685 case 268 /* 0x10C TB - 64 bit time base register */:
9687 IRTemp val
= newTemp(Ity_I64
);
9688 IRExpr
** args
= mkIRExprVec_0();
9689 IRDirty
* d
= unsafeIRDirty_1_N(
9692 "ppcg_dirtyhelper_MFTB",
9693 fnptr_to_fnentry(vbi
,
9694 &ppcg_dirtyhelper_MFTB
),
9696 /* execute the dirty call, dumping the result in val. */
9697 stmt( IRStmt_Dirty(d
) );
9698 putIReg( rD_addr
, (mode64
) ? mkexpr(val
) :
9699 unop(Iop_64to32
, mkexpr(val
)) );
9703 case 269 /* 0x10D TBU - upper 32-bits of time base register */:
9705 DIP("mfspr r%u,%u", rD_addr
, SPR
);
9706 IRTemp val
= newTemp(Ity_I64
);
9707 IRExpr
** args
= mkIRExprVec_0();
9708 IRDirty
* d
= unsafeIRDirty_1_N(
9711 "ppcg_dirtyhelper_MFTB",
9712 fnptr_to_fnentry(vbi
,
9713 &ppcg_dirtyhelper_MFTB
),
9715 /* execute the dirty call, dumping the result in val. */
9716 stmt( IRStmt_Dirty(d
) );
9718 mkWidenFrom32(ty
, unop(Iop_64HIto32
, mkexpr(val
)),
9719 /* Signed */False
) );
9722 case 284 /* 0x1 TBL - lower 32-bits of time base register */:
9724 DIP("mfspr r%u,%u", rD_addr
, SPR
);
9725 IRTemp val
= newTemp(Ity_I64
);
9726 IRExpr
** args
= mkIRExprVec_0();
9727 IRDirty
* d
= unsafeIRDirty_1_N(
9730 "ppcg_dirtyhelper_MFTB",
9731 fnptr_to_fnentry(vbi
,
9732 &ppcg_dirtyhelper_MFTB
),
9734 /* execute the dirty call, dumping the result in val. */
9735 stmt( IRStmt_Dirty(d
) );
9737 mkWidenFrom32(ty
, unop(Iop_64to32
, mkexpr(val
)),
9738 /* Signed */False
) );
9742 /* Again, runs natively on PPC7400 (7447, really). Not
9743 bothering with a feature test. */
9744 case 287: /* 0x11F */ {
9745 IRTemp val
= newTemp(Ity_I32
);
9746 IRExpr
** args
= mkIRExprVec_0();
9747 IRDirty
* d
= unsafeIRDirty_1_N(
9750 "ppc32g_dirtyhelper_MFSPR_287",
9752 (vbi
, &ppc32g_dirtyhelper_MFSPR_287
),
9755 /* execute the dirty call, dumping the result in val. */
9756 stmt( IRStmt_Dirty(d
) );
9758 mkWidenFrom32(ty
, mkexpr(val
), False
/*unsigned*/) );
9759 DIP("mfspr r%u,%u", rD_addr
, SPR
);
9764 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR
);
9769 case 0x173: { // mftb (Move from Time Base, PPC32 p475)
9770 IRTemp val
= newTemp(Ity_I64
);
9771 IRExpr
** args
= mkIRExprVec_0();
9772 IRDirty
* d
= unsafeIRDirty_1_N(
9775 "ppcg_dirtyhelper_MFTB",
9776 fnptr_to_fnentry(vbi
, &ppcg_dirtyhelper_MFTB
),
9778 /* execute the dirty call, dumping the result in val. */
9779 stmt( IRStmt_Dirty(d
) );
9783 DIP("mftbu r%u", rD_addr
);
9785 mkWidenFrom32(ty
, unop(Iop_64HIto32
, mkexpr(val
)),
9786 /* Signed */False
) );
9789 DIP("mftb r%u", rD_addr
);
9790 putIReg( rD_addr
, (mode64
) ? mkexpr(val
) :
9791 unop(Iop_64to32
, mkexpr(val
)) );
9794 DIP("mftbl r%u", rD_addr
);
9796 mkWidenFrom32(ty
, unop(Iop_64to32
, mkexpr(val
)),
9797 /* Signed */False
) );
9800 return False
; /* illegal instruction */
9806 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
9807 // b20==1: mtocrf (Move to One Cond Reg Field)
9813 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
9814 1 field is written. It seems more robust to decline to
9815 decode the insn if so. */
9817 case 0x01: case 0x02: case 0x04: case 0x08:
9818 case 0x10: case 0x20: case 0x40: case 0x80:
9824 DIP("%s 0x%x,r%u\n", b20
==1 ? "mtocrf" : "mtcrf",
9826 /* Write to each field specified by CRM */
9827 for (cr
= 0; cr
< 8; cr
++) {
9828 if ((CRM
& (1 << (7-cr
))) == 0)
9831 putGST_field( PPC_GST_CR
,
9833 mkNarrowTo32(ty
, mkexpr(rS
)),
9839 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
9841 switch (SPR
) { // Choose a register...
9843 DIP("mtxer r%u\n", rS_addr
);
9844 putGST( PPC_GST_XER
, mkNarrowTo32(ty
, mkexpr(rS
)) );
9847 DIP("mtspr r%u (DSCR)\n", rS_addr
);
9848 putGST( PPC_GST_DSCR
, mkexpr(rS
) );
9851 DIP("mtlr r%u\n", rS_addr
);
9852 putGST( PPC_GST_LR
, mkexpr(rS
) );
9855 DIP("mtctr r%u\n", rS_addr
);
9856 putGST( PPC_GST_CTR
, mkexpr(rS
) );
9859 DIP("mtvrsave r%u\n", rS_addr
);
9860 putGST( PPC_GST_VRSAVE
, mkNarrowTo32(ty
, mkexpr(rS
)) );
9863 DIP("mtspr r%u (TFHAR)\n", rS_addr
);
9864 putGST( PPC_GST_TFHAR
, mkexpr(rS
) );
9867 DIP("mtspr r%u (TFIAR)\n", rS_addr
);
9868 putGST( PPC_GST_TFIAR
, mkexpr(rS
) );
9871 DIP("mtspr r%u (TEXASR)\n", rS_addr
);
9872 putGST( PPC_GST_TEXASR
, mkexpr(rS
) );
9875 DIP("mtspr r%u (PSPB)\n", rS_addr
);
9876 putGST( PPC_GST_PSPB
, mkexpr(rS
) );
9879 DIP("mtspr r%u (PPR)\n", rS_addr
);
9880 putGST( PPC_GST_PPR
, mkexpr(rS
) );
9883 DIP("mtspr r%u (PPR32)\n", rS_addr
);
9884 putGST( PPC_GST_PPR32
, mkexpr(rS
) );
9887 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR
);
9892 case 0x33: // mfvsrd
9894 UChar XS
= ifieldRegXS( theInstr
);
9895 UChar rA_addr
= ifieldRegA(theInstr
);
9897 IRTemp vS
= newTemp( Ity_V128
);
9898 DIP("mfvsrd r%u,vsr%d\n", rA_addr
, XS
);
9901 * For SX=0, mfvsrd is treated as a Floating-Point
9902 * instruction in terms of resource availability.
9903 * For SX=1, mfvsrd is treated as a Vector instruction in
9904 * terms of resource availability.
9905 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9907 assign( vS
, getVSReg( XS
) );
9908 high64
= unop( Iop_V128HIto64
, mkexpr( vS
) );
9909 putIReg( rA_addr
, (mode64
) ? high64
:
9910 unop( Iop_64to32
, high64
) );
9914 case 0x73: // mfvsrwz
9916 UChar XS
= ifieldRegXS( theInstr
);
9917 UChar rA_addr
= ifieldRegA(theInstr
);
9919 IRTemp vS
= newTemp( Ity_V128
);
9920 DIP("mfvsrwz r%u,vsr%d\n", rA_addr
, XS
);
9922 * For SX=0, mfvsrwz is treated as a Floating-Point
9923 * instruction in terms of resource availability.
9924 * For SX=1, mfvsrwz is treated as a Vector instruction in
9925 * terms of resource availability.
9926 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9929 assign( vS
, getVSReg( XS
) );
9930 high64
= unop( Iop_V128HIto64
, mkexpr( vS
) );
9931 /* move value to the destination setting the upper 32-bits to zero */
9932 putIReg( rA_addr
, (mode64
) ?
9933 binop( Iop_And64
, high64
, mkU64( 0xFFFFFFFF ) ) :
9935 binop( Iop_And64
, high64
, mkU64( 0xFFFFFFFF ) ) ) );
9939 case 0xB3: // mtvsrd
9941 UChar XT
= ifieldRegXT( theInstr
);
9942 UChar rA_addr
= ifieldRegA(theInstr
);
9943 IRTemp rA
= newTemp(ty
);
9944 DIP("mtvsrd vsr%d,r%u\n", XT
, rA_addr
);
9946 * For SX=0, mfvsrd is treated as a Floating-Point
9947 * instruction in terms of resource availability.
9948 * For SX=1, mfvsrd is treated as a Vector instruction in
9949 * terms of resource availability.
9950 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9952 assign( rA
, getIReg(rA_addr
) );
9955 putVSReg( XT
, binop( Iop_64HLtoV128
, mkexpr( rA
), mkU64( 0 ) ) );
9957 putVSReg( XT
, binop( Iop_64HLtoV128
,
9958 binop( Iop_32HLto64
,
9965 case 0xD3: // mtvsrwa
9967 UChar XT
= ifieldRegXT( theInstr
);
9968 UChar rA_addr
= ifieldRegA(theInstr
);
9969 IRTemp rA
= newTemp( Ity_I32
);
9970 DIP("mtvsrwa vsr%d,r%u\n", XT
, rA_addr
);
9972 * For SX=0, mtvsrwa is treated as a Floating-Point
9973 * instruction in terms of resource availability.
9974 * For SX=1, mtvsrwa is treated as a Vector instruction in
9975 * terms of resource availability.
9976 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9979 assign( rA
, unop( Iop_64to32
, getIReg( rA_addr
) ) );
9981 assign( rA
, getIReg(rA_addr
) );
9983 putVSReg( XT
, binop( Iop_64HLtoV128
,
9984 unop( Iop_32Sto64
, mkexpr( rA
) ),
9989 case 0xF3: // mtvsrwz
9991 UChar XT
= ifieldRegXT( theInstr
);
9992 UChar rA_addr
= ifieldRegA(theInstr
);
9993 IRTemp rA
= newTemp( Ity_I32
);
9994 DIP("mtvsrwz vsr%d,r%u\n", rA_addr
, XT
);
9996 * For SX=0, mtvsrwz is treated as a Floating-Point
9997 * instruction in terms of resource availability.
9998 * For SX=1, mtvsrwz is treated as a Vector instruction in
9999 * terms of resource availability.
10000 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
10003 assign( rA
, unop( Iop_64to32
, getIReg( rA_addr
) ) );
10005 assign( rA
, getIReg(rA_addr
) );
10007 putVSReg( XT
, binop( Iop_64HLtoV128
,
10008 binop( Iop_32HLto64
, mkU32( 0 ), mkexpr ( rA
) ),
10014 vex_printf("dis_proc_ctl(ppc)(opc2)\n");
10022 Cache Management Instructions
10024 static Bool
dis_cache_manage ( UInt theInstr
,
10026 const VexArchInfo
* guest_archinfo
)
10029 UChar opc1
= ifieldOPC(theInstr
);
10030 UChar b21to25
= ifieldRegDS(theInstr
);
10031 UChar rA_addr
= ifieldRegA(theInstr
);
10032 UChar rB_addr
= ifieldRegB(theInstr
);
10033 UInt opc2
= ifieldOPClo10(theInstr
);
10034 UChar b0
= ifieldBIT0(theInstr
);
10035 UInt lineszB
= guest_archinfo
->ppc_icache_line_szB
;
10036 Bool is_dcbzl
= False
;
10038 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
10040 // Check for valid hint values for dcbt and dcbtst as currently described in
10041 // ISA 2.07. If valid, then we simply set b21to25 to zero since we have no
10042 // means of modeling the hint anyway.
10043 if (opc1
== 0x1F && ((opc2
== 0x116) || (opc2
== 0xF6))) {
10044 if (b21to25
== 0x10 || b21to25
< 0x10)
10047 if (opc1
== 0x1F && opc2
== 0x116 && b21to25
== 0x11)
10050 if (opc1
== 0x1F && opc2
== 0x3F6) { // dcbz
10051 if (b21to25
== 1) {
10054 if (!(guest_archinfo
->ppc_dcbzl_szB
)) {
10055 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
10061 if (opc1
!= 0x1F || b0
!= 0) {
10062 if (0) vex_printf("dis_cache_manage %d %d\n",
10064 vex_printf("dis_cache_manage(ppc)(opc1|b0)\n");
10069 vassert(lineszB
== 16 || lineszB
== 32 || lineszB
== 64 || lineszB
== 128);
10072 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
10073 //zz vassert(0); /* AWAITING TEST CASE */
10074 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
10075 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n");
10078 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
10079 DIP("dcbf r%u,r%u\n", rA_addr
, rB_addr
);
10080 /* nop as far as vex is concerned */
10083 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
10084 DIP("dcbst r%u,r%u\n", rA_addr
, rB_addr
);
10085 /* nop as far as vex is concerned */
10088 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
10089 DIP("dcbt r%u,r%u\n", rA_addr
, rB_addr
);
10090 /* nop as far as vex is concerned */
10093 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
10094 DIP("dcbtst r%u,r%u\n", rA_addr
, rB_addr
);
10095 /* nop as far as vex is concerned */
10098 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
10099 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
10100 /* Clear all bytes in cache block at (rA|0) + rB. */
10101 IRTemp EA
= newTemp(ty
);
10102 IRTemp addr
= newTemp(ty
);
10107 clearszB
= guest_archinfo
->ppc_dcbzl_szB
;
10108 DIP("dcbzl r%u,r%u\n", rA_addr
, rB_addr
);
10111 clearszB
= guest_archinfo
->ppc_dcbz_szB
;
10112 DIP("dcbz r%u,r%u\n", rA_addr
, rB_addr
);
10115 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
10118 /* Round EA down to the start of the containing block. */
10119 assign( addr
, binop( Iop_And64
,
10121 mkU64( ~((ULong
)clearszB
-1) )) );
10123 for (i
= 0; i
< clearszB
/ 8; i
++) {
10124 irx_addr
= binop( Iop_Add64
, mkexpr(addr
), mkU64(i
*8) );
10125 store( irx_addr
, mkU64(0) );
10128 /* Round EA down to the start of the containing block. */
10129 assign( addr
, binop( Iop_And32
,
10131 mkU32( ~(clearszB
-1) )) );
10133 for (i
= 0; i
< clearszB
/ 4; i
++) {
10134 irx_addr
= binop( Iop_Add32
, mkexpr(addr
), mkU32(i
*4) );
10135 store( irx_addr
, mkU32(0) );
10142 // icbi (Instruction Cache Block Invalidate, PPC32 p431)
10143 /* Invalidate all translations containing code from the cache
10144 block at (rA|0) + rB. */
10145 IRTemp EA
= newTemp(ty
);
10146 IRTemp addr
= newTemp(ty
);
10147 DIP("icbi r%u,r%u\n", rA_addr
, rB_addr
);
10148 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
10150 /* Round EA down to the start of the containing block. */
10151 assign( addr
, binop( mkSzOp(ty
, Iop_And8
),
10153 mkSzImm(ty
, ~(((ULong
)lineszB
)-1) )) );
10154 putGST( PPC_GST_CMSTART
, mkexpr(addr
) );
10155 putGST( PPC_GST_CMLEN
, mkSzImm(ty
, lineszB
) );
10157 /* be paranoid ... */
10158 stmt( IRStmt_MBE(Imbe_Fence
) );
10160 putGST( PPC_GST_CIA
, mkSzImm(ty
, nextInsnAddr()));
10161 dres
->jk_StopHere
= Ijk_InvalICache
;
10162 dres
->whatNext
= Dis_StopHere
;
10167 vex_printf("dis_cache_manage(ppc)(opc2)\n");
10174 /*------------------------------------------------------------*/
10175 /*--- Floating Point Helpers ---*/
10176 /*------------------------------------------------------------*/
10178 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
10179 /* Produces a value in 0 .. 3, which is encoded as per the type
10180 IRRoundingMode. PPCRoundingMode encoding is different to
10181 IRRoundingMode, so need to map it.
10184 static IRExpr
* /* :: Ity_I32 */ set_round_to_Oddmode ( void )
10186 /* PPC/ valgrind have two-bits to designate the rounding mode.
10187 ISA 3.0 adds instructions than can use a round to odd mode
10188 but did not change the number of bits for the rm. Basically,
10189 they added two instructions that only differ by the rounding
10190 mode the operation uses. In essesce, they encoded the rm
10191 in the name. In order to avoid having to create Iops, that
10192 encode the rm in th name, we will "expand" the definition of
10193 the rounding mode bits. We will just pass the rm and then
10194 map the to odd mode to the appropriate PPCFpOp name that
10195 will tell us which instruction to map to.
10197 rounding mode | PPC | IR
10198 ------------------------
10199 to nearest | 000 | 00
10201 to +infinity | 010 | 10
10202 to -infinity | 011 | 01
10208 static IRExpr
* /* :: Ity_I32 */ get_IR_roundingmode ( void )
10211 rounding mode | PPC | IR
10212 ------------------------
10213 to nearest | 00 | 00
10215 to +infinity | 10 | 10
10216 to -infinity | 11 | 01
10218 IRTemp rm_PPC32
= newTemp(Ity_I32
);
10219 assign( rm_PPC32
, getGST_masked( PPC_GST_FPSCR
, MASK_FPSCR_RN
) );
10221 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
10222 return binop( Iop_Xor32
,
10225 binop(Iop_Shl32
, mkexpr(rm_PPC32
), mkU8(1)),
10229 /* The DFP IR rounding modes were chosen such that the existing PPC to IR
10230 * mapping would still work with the extended three bit DFP rounding
10233 * rounding mode | PPC | IR
10234 * -----------------------------------------------
10235 * to nearest, ties to even | 000 | 000
10236 * to zero | 001 | 011
10237 * to +infinity | 010 | 010
10238 * to -infinity | 011 | 001
10239 * to nearest, ties away from 0 | 100 | 100
10240 * to nearest, ties toward 0 | 101 | 111
10241 * to away from 0 | 110 | 110
10242 * to prepare for shorter precision | 111 | 101
10244 static IRExpr
* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
10246 IRTemp rm_PPC32
= newTemp( Ity_I32
);
10247 assign( rm_PPC32
, getGST_masked_upper( PPC_GST_FPSCR
, MASK_FPSCR_DRN
) );
10249 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
10250 return binop( Iop_Xor32
,
10251 mkexpr( rm_PPC32
),
10253 binop( Iop_Shl32
, mkexpr( rm_PPC32
), mkU8( 1 ) ),
10257 #define NANmaskSingle 0x7F800000
10258 #define NANmaskDouble 0x7FF00000
10260 static IRExpr
* Check_NaN( IRExpr
* value
, IRExpr
* Hi32Mask
)
10262 IRTemp exp_zero
= newTemp(Ity_I8
);
10263 IRTemp frac_mask
= newTemp(Ity_I32
);
10264 IRTemp frac_not_zero
= newTemp(Ity_I8
);
10266 /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
10267 * The input value is always 64-bits, for single precision values, the
10268 * lower 32 bits must be zero.
10271 * [62:54] exponent field is equal to 0xFF for NAN and Infinity.
10272 * [53:32] fraction field is zero for Infinity and non-zero for NAN
10273 * [31:0] unused for single precision representation
10276 * [62:51] exponent field is equal to 0xFF for NAN and Infinity.
10277 * [50:0] fraction field is zero for Infinity and non-zero for NAN
10279 * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
10281 assign( frac_mask
, unop( Iop_Not32
,
10283 mkU32( 0x80000000ULL
), Hi32Mask
) ) );
10287 binop( Iop_CmpEQ32
,
10289 unop( Iop_64HIto32
,
10290 unop( Iop_ReinterpF64asI64
,
10294 assign( frac_not_zero
,
10297 binop( Iop_CmpNE32
,
10299 unop( Iop_64HIto32
,
10300 unop( Iop_ReinterpF64asI64
,
10302 mkexpr( frac_mask
) ),
10305 binop( Iop_CmpNE32
,
10308 unop( Iop_ReinterpF64asI64
,
10310 mkU32( 0xFFFFFFFF ) ),
10311 mkU32( 0x0 ) ) ) ) );
10312 return unop( Iop_8Sto32
,
10314 mkexpr( exp_zero
),
10315 mkexpr( frac_not_zero
) ) );
10318 static IRExpr
* Complement_non_NaN( IRExpr
* value
, IRExpr
* nan_mask
)
10320 /* This function will only complement the 64-bit floating point value if it
10321 * is not Nan. NaN is not a signed value. Need to do computations using
10322 * 32-bit operands to ensure it will run in 32-bit mode.
10324 return binop( Iop_32HLto64
,
10328 unop( Iop_64HIto32
,
10329 unop( Iop_ReinterpF64asI64
,
10334 unop( Iop_64HIto32
,
10335 unop( Iop_ReinterpF64asI64
,
10339 unop( Iop_ReinterpF64asI64
, value
) ) );
10342 /*------------------------------------------------------------*/
10343 /*--- Floating Point Instruction Translation ---*/
10344 /*------------------------------------------------------------*/
10347 Floating Point Load Instructions
10349 static Bool
dis_fp_load ( UInt theInstr
)
10351 /* X-Form, D-Form */
10352 UChar opc1
= ifieldOPC(theInstr
);
10353 UChar frD_addr
= ifieldRegDS(theInstr
);
10354 UChar rA_addr
= ifieldRegA(theInstr
);
10355 UChar rB_addr
= ifieldRegB(theInstr
);
10356 UInt opc2
= ifieldOPClo10(theInstr
);
10357 UChar b0
= ifieldBIT0(theInstr
);
10358 UInt uimm16
= ifieldUIMM16(theInstr
);
10360 Int simm16
= extend_s_16to32(uimm16
);
10361 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
10362 IRTemp EA
= newTemp(ty
);
10363 IRTemp rA
= newTemp(ty
);
10364 IRTemp rB
= newTemp(ty
);
10365 IRTemp iHi
= newTemp(Ity_I32
);
10366 IRTemp iLo
= newTemp(Ity_I32
);
10368 assign( rA
, getIReg(rA_addr
) );
10369 assign( rB
, getIReg(rB_addr
) );
10371 /* These are completely straightforward from a rounding and status
10372 bits perspective: no rounding involved and no funny status or CR
10376 case 0x30: // lfs (Load Float Single, PPC32 p441)
10377 DIP("lfs fr%u,%d(r%u)\n", frD_addr
, simm16
, rA_addr
);
10378 assign( EA
, ea_rAor0_simm(rA_addr
, simm16
) );
10380 unop(Iop_F32toF64
, load(Ity_F32
, mkexpr(EA
))) );
10383 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
10386 DIP("lfsu fr%u,%d(r%u)\n", frD_addr
, simm16
, rA_addr
);
10387 assign( EA
, ea_rA_simm(rA_addr
, simm16
) );
10389 unop(Iop_F32toF64
, load(Ity_F32
, mkexpr(EA
))) );
10390 putIReg( rA_addr
, mkexpr(EA
) );
10393 case 0x32: // lfd (Load Float Double, PPC32 p437)
10394 DIP("lfd fr%u,%d(r%u)\n", frD_addr
, simm16
, rA_addr
);
10395 assign( EA
, ea_rAor0_simm(rA_addr
, simm16
) );
10396 putFReg( frD_addr
, load(Ity_F64
, mkexpr(EA
)) );
10399 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
10402 DIP("lfdu fr%u,%d(r%u)\n", frD_addr
, simm16
, rA_addr
);
10403 assign( EA
, ea_rA_simm(rA_addr
, simm16
) );
10404 putFReg( frD_addr
, load(Ity_F64
, mkexpr(EA
)) );
10405 putIReg( rA_addr
, mkexpr(EA
) );
10410 vex_printf("dis_fp_load(ppc)(instr,b0)\n");
10415 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
10416 DIP("lfsx fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
10417 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
10418 putFReg( frD_addr
, unop( Iop_F32toF64
,
10419 load(Ity_F32
, mkexpr(EA
))) );
10422 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
10425 DIP("lfsux fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
10426 assign( EA
, ea_rA_idxd(rA_addr
, rB_addr
) );
10428 unop(Iop_F32toF64
, load(Ity_F32
, mkexpr(EA
))) );
10429 putIReg( rA_addr
, mkexpr(EA
) );
10432 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
10433 DIP("lfdx fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
10434 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
10435 putFReg( frD_addr
, load(Ity_F64
, mkexpr(EA
)) );
10438 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
10441 DIP("lfdux fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
10442 assign( EA
, ea_rA_idxd(rA_addr
, rB_addr
) );
10443 putFReg( frD_addr
, load(Ity_F64
, mkexpr(EA
)) );
10444 putIReg( rA_addr
, mkexpr(EA
) );
10447 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
10448 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
10449 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
10450 assign( iLo
, load(Ity_I32
, mkexpr(EA
)) );
10451 assign( iHi
, binop(Iop_Sub32
,
10453 binop(Iop_Shr32
, mkexpr(iLo
), mkU8(31))) );
10454 putFReg( frD_addr
, unop(Iop_ReinterpI64asF64
,
10455 binop(Iop_32HLto64
, mkexpr(iHi
), mkexpr(iLo
))) );
10458 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
10460 IRTemp dw
= newTemp( Ity_I64
);
10461 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
10462 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
10463 assign( iLo
, load(Ity_I32
, mkexpr(EA
)) );
10464 assign( dw
, binop( Iop_32HLto64
, mkU32( 0 ), mkexpr( iLo
) ) );
10465 putFReg( frD_addr
, unop( Iop_ReinterpI64asF64
, mkexpr( dw
) ) );
10470 vex_printf("dis_fp_load(ppc)(opc2)\n");
10476 vex_printf("dis_fp_load(ppc)(opc1)\n");
10485 Floating Point Store Instructions
10487 static Bool
dis_fp_store ( UInt theInstr
)
10489 /* X-Form, D-Form */
10490 UChar opc1
= ifieldOPC(theInstr
);
10491 UChar frS_addr
= ifieldRegDS(theInstr
);
10492 UChar rA_addr
= ifieldRegA(theInstr
);
10493 UChar rB_addr
= ifieldRegB(theInstr
);
10494 UInt opc2
= ifieldOPClo10(theInstr
);
10495 UChar b0
= ifieldBIT0(theInstr
);
10496 Int uimm16
= ifieldUIMM16(theInstr
);
10498 Int simm16
= extend_s_16to32(uimm16
);
10499 IRTemp frS
= newTemp(Ity_F64
);
10500 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
10501 IRTemp EA
= newTemp(ty
);
10502 IRTemp rA
= newTemp(ty
);
10503 IRTemp rB
= newTemp(ty
);
10505 assign( frS
, getFReg(frS_addr
) );
10506 assign( rA
, getIReg(rA_addr
) );
10507 assign( rB
, getIReg(rB_addr
) );
10509 /* These are straightforward from a status bits perspective: no
10510 funny status or CR bits affected. For single precision stores,
10511 the values are truncated and denormalised (not rounded) to turn
10512 them into single precision values. */
10516 case 0x34: // stfs (Store Float Single, PPC32 p518)
10517 DIP("stfs fr%u,%d(r%u)\n", frS_addr
, simm16
, rA_addr
);
10518 assign( EA
, ea_rAor0_simm(rA_addr
, simm16
) );
10519 /* Use Iop_TruncF64asF32 to truncate and possible denormalise
10520 the value to be stored in the correct way, without any
10522 store( mkexpr(EA
), unop(Iop_TruncF64asF32
, mkexpr(frS
)) );
10525 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
10528 DIP("stfsu fr%u,%d(r%u)\n", frS_addr
, simm16
, rA_addr
);
10529 assign( EA
, ea_rA_simm(rA_addr
, simm16
) );
10530 /* See comment for stfs */
10531 store( mkexpr(EA
), unop(Iop_TruncF64asF32
, mkexpr(frS
)) );
10532 putIReg( rA_addr
, mkexpr(EA
) );
10535 case 0x36: // stfd (Store Float Double, PPC32 p513)
10536 DIP("stfd fr%u,%d(r%u)\n", frS_addr
, simm16
, rA_addr
);
10537 assign( EA
, ea_rAor0_simm(rA_addr
, simm16
) );
10538 store( mkexpr(EA
), mkexpr(frS
) );
10541 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
10544 DIP("stfdu fr%u,%d(r%u)\n", frS_addr
, simm16
, rA_addr
);
10545 assign( EA
, ea_rA_simm(rA_addr
, simm16
) );
10546 store( mkexpr(EA
), mkexpr(frS
) );
10547 putIReg( rA_addr
, mkexpr(EA
) );
10552 vex_printf("dis_fp_store(ppc)(instr,b0)\n");
10556 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
10557 DIP("stfsx fr%u,r%u,r%u\n", frS_addr
, rA_addr
, rB_addr
);
10558 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
10559 /* See note for stfs */
10561 unop(Iop_TruncF64asF32
, mkexpr(frS
)) );
10564 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
10567 DIP("stfsux fr%u,r%u,r%u\n", frS_addr
, rA_addr
, rB_addr
);
10568 assign( EA
, ea_rA_idxd(rA_addr
, rB_addr
) );
10569 /* See note for stfs */
10570 store( mkexpr(EA
), unop(Iop_TruncF64asF32
, mkexpr(frS
)) );
10571 putIReg( rA_addr
, mkexpr(EA
) );
10574 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
10575 DIP("stfdx fr%u,r%u,r%u\n", frS_addr
, rA_addr
, rB_addr
);
10576 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
10577 store( mkexpr(EA
), mkexpr(frS
) );
10580 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
10583 DIP("stfdux fr%u,r%u,r%u\n", frS_addr
, rA_addr
, rB_addr
);
10584 assign( EA
, ea_rA_idxd(rA_addr
, rB_addr
) );
10585 store( mkexpr(EA
), mkexpr(frS
) );
10586 putIReg( rA_addr
, mkexpr(EA
) );
10589 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
10590 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10591 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr
, rA_addr
, rB_addr
);
10592 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
10594 unop(Iop_64to32
, unop(Iop_ReinterpF64asI64
, mkexpr(frS
))) );
10598 vex_printf("dis_fp_store(ppc)(opc2)\n");
10604 vex_printf("dis_fp_store(ppc)(opc1)\n");
10613 Floating Point Arith Instructions
10615 static Bool
dis_fp_arith ( UInt theInstr
)
10618 UChar opc1
= ifieldOPC(theInstr
);
10619 UChar frD_addr
= ifieldRegDS(theInstr
);
10620 UChar frA_addr
= ifieldRegA(theInstr
);
10621 UChar frB_addr
= ifieldRegB(theInstr
);
10622 UChar frC_addr
= ifieldRegC(theInstr
);
10623 UChar opc2
= ifieldOPClo5(theInstr
);
10624 UChar flag_rC
= ifieldBIT0(theInstr
);
10626 IRTemp frD
= newTemp(Ity_F64
);
10627 IRTemp frA
= newTemp(Ity_F64
);
10628 IRTemp frB
= newTemp(Ity_F64
);
10629 IRTemp frC
= newTemp(Ity_F64
);
10630 IRExpr
* rm
= get_IR_roundingmode();
10632 /* By default, we will examine the results of the operation and set
10633 fpscr[FPRF] accordingly. */
10634 Bool set_FPRF
= True
;
10636 /* By default, if flag_RC is set, we will clear cr1 after the
10637 operation. In reality we should set cr1 to indicate the
10638 exception status of the operation, but since we're not
10639 simulating exceptions, the exception status will appear to be
10640 zero. Hence cr1 should be cleared if this is a . form insn. */
10641 Bool clear_CR1
= True
;
10643 assign( frA
, getFReg(frA_addr
));
10644 assign( frB
, getFReg(frB_addr
));
10645 assign( frC
, getFReg(frC_addr
));
10650 case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
10653 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10654 frD_addr
, frA_addr
, frB_addr
);
10655 assign( frD
, triop( Iop_DivF64r32
,
10656 rm
, mkexpr(frA
), mkexpr(frB
) ));
10659 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
10662 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10663 frD_addr
, frA_addr
, frB_addr
);
10664 assign( frD
, triop( Iop_SubF64r32
,
10665 rm
, mkexpr(frA
), mkexpr(frB
) ));
10668 case 0x15: // fadds (Floating Add Single, PPC32 p401)
10671 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10672 frD_addr
, frA_addr
, frB_addr
);
10673 assign( frD
, triop( Iop_AddF64r32
,
10674 rm
, mkexpr(frA
), mkexpr(frB
) ));
10677 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
10678 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
10679 if (frA_addr
!= 0 || frC_addr
!= 0)
10681 DIP("fsqrts%s fr%u,fr%u\n", flag_rC
? ".":"",
10682 frD_addr
, frB_addr
);
10683 // however illogically, on ppc970 this insn behaves identically
10684 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32.
10685 assign( frD
, binop( Iop_SqrtF64
, rm
, mkexpr(frB
) ));
10688 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
10689 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10690 if (frA_addr
!= 0 || frC_addr
!= 0)
10692 DIP("fres%s fr%u,fr%u\n", flag_rC
? ".":"",
10693 frD_addr
, frB_addr
);
10695 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
10696 assign( frD
, triop( Iop_DivF64r32
,
10698 ieee_one
, mkexpr(frB
) ));
10702 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
10705 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10706 frD_addr
, frA_addr
, frC_addr
);
10707 assign( frD
, triop( Iop_MulF64r32
,
10708 rm
, mkexpr(frA
), mkexpr(frC
) ));
10711 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
10712 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10713 // Undocumented instruction?
10714 if (frA_addr
!= 0 || frC_addr
!= 0)
10716 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC
? ".":"",
10717 frD_addr
, frB_addr
);
10718 assign( frD
, unop(Iop_RSqrtEst5GoodF64
, mkexpr(frB
)) );
10722 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
10729 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
10732 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10733 frD_addr
, frA_addr
, frB_addr
);
10734 assign( frD
, triop(Iop_DivF64
, rm
, mkexpr(frA
), mkexpr(frB
)) );
10737 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
10740 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10741 frD_addr
, frA_addr
, frB_addr
);
10742 assign( frD
, triop(Iop_SubF64
, rm
, mkexpr(frA
), mkexpr(frB
)) );
10745 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
10748 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10749 frD_addr
, frA_addr
, frB_addr
);
10750 assign( frD
, triop(Iop_AddF64
, rm
, mkexpr(frA
), mkexpr(frB
)) );
10753 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
10754 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
10755 if (frA_addr
!= 0 || frC_addr
!= 0)
10757 DIP("fsqrt%s fr%u,fr%u\n", flag_rC
? ".":"",
10758 frD_addr
, frB_addr
);
10759 assign( frD
, binop(Iop_SqrtF64
, rm
, mkexpr(frB
)) );
10762 case 0x17: { // fsel (Floating Select, PPC32 p426)
10763 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10764 IRTemp cc
= newTemp(Ity_I32
);
10765 IRTemp cc_b0
= newTemp(Ity_I32
);
10767 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10768 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
10770 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
10771 // => GT|EQ == (cc & 0x1 == 0)
10772 assign( cc
, binop(Iop_CmpF64
, mkexpr(frA
),
10773 IRExpr_Const(IRConst_F64(0))) );
10774 assign( cc_b0
, binop(Iop_And32
, mkexpr(cc
), mkU32(1)) );
10776 // frD = (frA >= 0.0) ? frC : frB
10777 // = (cc_b0 == 0) ? frC : frB
10780 binop(Iop_CmpEQ32
, mkexpr(cc_b0
), mkU32(0)),
10784 /* One of the rare ones which don't mess with FPRF */
10789 case 0x18: // fre (Floating Reciprocal Estimate)
10790 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10791 // Note: unclear whether this insn really exists or not
10792 // ppc970 doesn't have it, but POWER5 does
10793 if (frA_addr
!= 0 || frC_addr
!= 0)
10795 DIP("fre%s fr%u,fr%u\n", flag_rC
? ".":"",
10796 frD_addr
, frB_addr
);
10798 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
10799 assign( frD
, triop( Iop_DivF64
,
10801 ieee_one
, mkexpr(frB
) ));
10805 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
10807 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
10808 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10809 frD_addr
, frA_addr
, frC_addr
);
10810 assign( frD
, triop(Iop_MulF64
, rm
, mkexpr(frA
), mkexpr(frC
)) );
10813 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
10814 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10815 if (frA_addr
!= 0 || frC_addr
!= 0)
10817 DIP("frsqrte%s fr%u,fr%u\n", flag_rC
? ".":"",
10818 frD_addr
, frB_addr
);
10819 assign( frD
, unop(Iop_RSqrtEst5GoodF64
, mkexpr(frB
)) );
10823 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
10829 vex_printf("dis_fp_arith(ppc)(opc1)\n");
10833 putFReg( frD_addr
, mkexpr(frD
) );
10836 // XXX XXX XXX FIXME
10837 // set FPRF from frD
10840 if (flag_rC
&& clear_CR1
) {
10841 putCR321( 1, mkU8(0) );
10842 putCR0( 1, mkU8(0) );
10851 Floating Point Mult-Add Instructions
10853 static Bool
dis_fp_multadd ( UInt theInstr
)
10856 UChar opc1
= ifieldOPC(theInstr
);
10857 UChar frD_addr
= ifieldRegDS(theInstr
);
10858 UChar frA_addr
= ifieldRegA(theInstr
);
10859 UChar frB_addr
= ifieldRegB(theInstr
);
10860 UChar frC_addr
= ifieldRegC(theInstr
);
10861 UChar opc2
= ifieldOPClo5(theInstr
);
10862 UChar flag_rC
= ifieldBIT0(theInstr
);
10864 IRTemp frD
= newTemp(Ity_F64
);
10865 IRTemp frA
= newTemp(Ity_F64
);
10866 IRTemp frB
= newTemp(Ity_F64
);
10867 IRTemp frC
= newTemp(Ity_F64
);
10868 IRTemp rmt
= newTemp(Ity_I32
);
10869 IRTemp tmp
= newTemp(Ity_F64
);
10870 IRTemp sign_tmp
= newTemp(Ity_I64
);
10871 IRTemp nan_mask
= newTemp(Ity_I32
);
10874 /* By default, we will examine the results of the operation and set
10875 fpscr[FPRF] accordingly. */
10876 Bool set_FPRF
= True
;
10878 /* By default, if flag_RC is set, we will clear cr1 after the
10879 operation. In reality we should set cr1 to indicate the
10880 exception status of the operation, but since we're not
10881 simulating exceptions, the exception status will appear to be
10882 zero. Hence cr1 should be cleared if this is a . form insn. */
10883 Bool clear_CR1
= True
;
10885 /* Bind the rounding mode expression to a temp; there's no
10886 point in creating gratuitous CSEs, as we know we'll need
10887 to use it twice. */
10888 assign( rmt
, get_IR_roundingmode() );
10891 assign( frA
, getFReg(frA_addr
));
10892 assign( frB
, getFReg(frB_addr
));
10893 assign( frC
, getFReg(frC_addr
));
10895 /* The rounding in this is all a bit dodgy. The idea is to only do
10896 one rounding. That clearly isn't achieveable without dedicated
10897 four-input IR primops, although in the single precision case we
10898 can sort-of simulate it by doing the inner multiply in double
10901 In the negated cases, the negation happens after rounding. */
10906 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
10907 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10908 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
10909 assign( frD
, qop( Iop_MSubF64r32
, rm
,
10910 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ));
10913 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
10914 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10915 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
10916 assign( frD
, qop( Iop_MAddF64r32
, rm
,
10917 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ));
10920 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
10921 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
10923 if (opc2
== 0x1E) {
10924 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10925 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
10926 assign( tmp
, qop( Iop_MSubF64r32
, rm
,
10927 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ) );
10929 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10930 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
10931 assign( tmp
, qop( Iop_MAddF64r32
, rm
,
10932 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ) );
10935 assign( nan_mask
, Check_NaN( mkexpr( tmp
),
10936 mkU32( NANmaskSingle
) ) );
10937 assign( sign_tmp
, Complement_non_NaN( mkexpr( tmp
),
10938 mkexpr( nan_mask
) ) );
10939 assign( frD
, unop( Iop_ReinterpI64asF64
, mkexpr( sign_tmp
) ) );
10943 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
10950 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
10951 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10952 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
10953 assign( frD
, qop( Iop_MSubF64
, rm
,
10954 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ));
10957 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
10958 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10959 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
10960 assign( frD
, qop( Iop_MAddF64
, rm
,
10961 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ));
10964 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
10965 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
10967 if (opc2
== 0x1E) {
10968 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10969 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
10970 assign( tmp
, qop( Iop_MSubF64
, rm
,
10971 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ) );
10973 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
10974 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
10975 assign( tmp
, qop( Iop_MAddF64
, rm
,
10976 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ));
10979 assign( nan_mask
, Check_NaN( mkexpr( tmp
),
10980 mkU32( NANmaskDouble
) ) );
10981 assign( sign_tmp
, Complement_non_NaN( mkexpr( tmp
),
10982 mkexpr( nan_mask
) ) );
10983 assign( frD
, unop( Iop_ReinterpI64asF64
, mkexpr( sign_tmp
) ) );
10987 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
10993 vex_printf("dis_fp_multadd(ppc)(opc1)\n");
10997 putFReg( frD_addr
, mkexpr(frD
) );
11000 // XXX XXX XXX FIXME
11001 // set FPRF from frD
11004 if (flag_rC
&& clear_CR1
) {
11005 putCR321( 1, mkU8(0) );
11006 putCR0( 1, mkU8(0) );
11013 * fe_flag is set to 1 if any of the following conditions occurs:
11014 * - The floating-point operand in register FRB is a Zero, a
11015 * NaN, an Infinity, or a negative value.
11016 * - e_b is less than or equal to: -970 for double precision; -103 for single precision
11017 * Otherwise fe_flag is set to 0.
11019 * fg_flag is set to 1 if either of the following conditions occurs.
11020 * - The floating-point operand in register FRB is a Zero, an
11021 * Infinity, or a denormalized value.
11022 * Otherwise fg_flag is set to 0.
11026 static void do_fp_tsqrt(IRTemp frB_Int
, Bool sp
, IRTemp
* fe_flag_tmp
, IRTemp
* fg_flag_tmp
)
11028 // The following temps are for holding intermediate results
11029 IRTemp e_b
= newTemp(Ity_I32
);
11030 IRExpr
* fe_flag
, * fg_flag
;
11031 IRTemp frB_exp_shR
= newTemp(Ity_I32
);
11032 UInt bias
= sp
? 127 : 1023;
11033 IRExpr
* frbNaN
, * frbDenorm
, * frBNeg
;
11035 IRTemp frbZero_tmp
= newTemp(Ity_I1
);
11036 IRTemp frbInf_tmp
= newTemp(Ity_I1
);
11037 *fe_flag_tmp
= newTemp(Ity_I32
);
11038 *fg_flag_tmp
= newTemp(Ity_I32
);
11041 assign( frB_exp_shR
, fp_exp_part( Ity_I32
, frB_Int
) );
11043 assign( frB_exp_shR
, fp_exp_part( Ity_I64
, frB_Int
) );
11045 assign(e_b
, binop( Iop_Sub32
, mkexpr(frB_exp_shR
), mkU32( bias
) ));
11047 ////////////////// fe_flag tests BEGIN //////////////////////
11048 /* We first do all tests that may result in setting fe_flag to '1'.
11049 * (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv()
11053 frbNaN
= is_NaN( Ity_I32
, frB_Int
);
11054 assign( frbInf_tmp
, is_Inf( Ity_I32
, frB_Int
) );
11055 assign( frbZero_tmp
, is_Zero( Ity_I32
, frB_Int
) );
11058 frbNaN
= is_NaN( Ity_I64
, frB_Int
);
11059 assign( frbInf_tmp
, is_Inf( Ity_I64
, frB_Int
) );
11060 assign( frbZero_tmp
, is_Zero( Ity_I64
, frB_Int
) );
11064 // Test_value = -970 for double precision
11065 UInt test_value
= sp
? 0xffffff99 : 0xfffffc36;
11066 eb_LTE
= binop( Iop_CmpLE32S
, mkexpr( e_b
), mkU32( test_value
) );
11068 frBNeg
= binop( Iop_CmpEQ32
,
11070 sp
? mkexpr( frB_Int
) : unop( Iop_64HIto32
, mkexpr( frB_Int
) ),
11073 ////////////////// fe_flag tests END //////////////////////
11075 ////////////////// fg_flag tests BEGIN //////////////////////
11077 * The following tests were already performed above in the fe_flag
11078 * tests. So these conditions will result in both fe_ and fg_ flags
11080 * - Test if FRB is Zero
11081 * - Test if FRB is an Infinity
11085 * Test if FRB holds a denormalized value. A denormalized value is one where
11086 * the exp is 0 and the fraction is non-zero.
11089 IRTemp frac_part
= newTemp(Ity_I32
);
11090 assign( frac_part
, binop( Iop_And32
, mkexpr(frB_Int
), mkU32(0x007fffff)) );
11092 = mkAND1( binop( Iop_CmpEQ32
, mkexpr( frB_exp_shR
), mkU32( 0 ) ),
11093 binop( Iop_CmpNE32
, mkexpr( frac_part
), mkU32( 0 ) ) );
11095 IRExpr
* hi32
, * low32
, * fraction_is_nonzero
;
11096 IRTemp frac_part
= newTemp(Ity_I64
);
11098 assign( frac_part
, FP_FRAC_PART(frB_Int
) );
11099 hi32
= unop( Iop_64HIto32
, mkexpr( frac_part
) );
11100 low32
= unop( Iop_64to32
, mkexpr( frac_part
) );
11101 fraction_is_nonzero
= binop( Iop_CmpNE32
, binop( Iop_Or32
, low32
, hi32
),
11104 = mkAND1( binop( Iop_CmpEQ32
, mkexpr( frB_exp_shR
), mkU32( 0 ) ),
11105 fraction_is_nonzero
);
11107 ////////////////// fg_flag tests END //////////////////////
11109 /////////////////////////
11110 fe_flag
= mkOR1( mkexpr( frbZero_tmp
),
11112 mkOR1( mkexpr( frbInf_tmp
),
11113 mkOR1( frBNeg
, eb_LTE
) ) ) );
11115 fe_flag
= unop(Iop_1Uto32
, fe_flag
);
11117 fg_flag
= mkOR1( mkexpr( frbZero_tmp
),
11118 mkOR1( mkexpr( frbInf_tmp
), frbDenorm
) );
11119 fg_flag
= unop(Iop_1Uto32
, fg_flag
);
11120 assign (*fg_flag_tmp
, fg_flag
);
11121 assign (*fe_flag_tmp
, fe_flag
);
11124 * fe_flag is set to 1 if any of the following conditions occurs:
11125 * - The double-precision floating-point operand in register FRA is a NaN or an
11127 * - The double-precision floating-point operand in register FRB is a Zero, a
11128 * NaN, or an Infinity.
11129 * - e_b is less than or equal to -1022.
11130 * - e_b is greater than or equal to 1021.
11131 * - The double-precision floating-point operand in register FRA is not a zero
11132 * and the difference, e_a - e_b, is greater than or equal to 1023.
11133 * - The double-precision floating-point operand in register FRA is not a zero
11134 * and the difference, e_a - e_b, is less than or equal to -1021.
11135 * - The double-precision floating-point operand in register FRA is not a zero
11136 * and e_a is less than or equal to -970
11137 * Otherwise fe_flag is set to 0.
11139 * fg_flag is set to 1 if either of the following conditions occurs.
11140 * - The double-precision floating-point operand in register FRA is an Infinity.
11141 * - The double-precision floating-point operand in register FRB is a Zero, an
11142 * Infinity, or a denormalized value.
11143 * Otherwise fg_flag is set to 0.
11146 static void _do_fp_tdiv(IRTemp frA_int
, IRTemp frB_int
, Bool sp
, IRTemp
* fe_flag_tmp
, IRTemp
* fg_flag_tmp
)
11148 // The following temps are for holding intermediate results
11149 IRTemp e_a
= newTemp(Ity_I32
);
11150 IRTemp e_b
= newTemp(Ity_I32
);
11151 IRTemp frA_exp_shR
= newTemp(Ity_I32
);
11152 IRTemp frB_exp_shR
= newTemp(Ity_I32
);
11154 UInt bias
= sp
? 127 : 1023;
11155 *fe_flag_tmp
= newTemp(Ity_I32
);
11156 *fg_flag_tmp
= newTemp(Ity_I32
);
11158 /* The following variables hold boolean results from tests
11159 * that are OR'ed together for setting the fe_ and fg_ flags.
11160 * For some cases, the booleans are used more than once, so
11161 * I make those IRTemp's instead of IRExpr's.
11163 IRExpr
* fraNaN
, * frbNaN
, * frbDenorm
;
11164 IRExpr
* eb_LTE
, * eb_GTE
, * ea_eb_GTE
, * ea_eb_LTE
, * ea_LTE
;
11165 IRTemp fraInf_tmp
= newTemp(Ity_I1
);
11166 IRTemp frbZero_tmp
= newTemp(Ity_I1
);
11167 IRTemp frbInf_tmp
= newTemp(Ity_I1
);
11168 IRTemp fraNotZero_tmp
= newTemp(Ity_I1
);
11170 /* The following are the flags that are set by OR'ing the results of
11171 * all the tests done for tdiv. These flags are the input to the specified CR.
11173 IRExpr
* fe_flag
, * fg_flag
;
11175 // Create temps that will be used throughout the following tests.
11177 assign( frA_exp_shR
, fp_exp_part( Ity_I32
, frA_int
) );
11178 assign( frB_exp_shR
, fp_exp_part( Ity_I32
, frB_int
) );
11180 assign( frA_exp_shR
, fp_exp_part( Ity_I64
, frA_int
) );
11181 assign( frB_exp_shR
, fp_exp_part( Ity_I64
, frB_int
) );
11184 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
11185 assign(e_a
, binop( Iop_Sub32
, mkexpr(frA_exp_shR
), mkU32( bias
) ));
11186 assign(e_b
, binop( Iop_Sub32
, mkexpr(frB_exp_shR
), mkU32( bias
) ));
11189 ////////////////// fe_flag tests BEGIN //////////////////////
11190 /* We first do all tests that may result in setting fe_flag to '1'. */
11193 * Test if the double-precision floating-point operand in register FRA is
11196 fraNaN
= sp
? is_NaN( Ity_I32
, frA_int
) : is_NaN( Ity_I64
, frA_int
);
11198 * Test if the double-precision floating-point operands in register FRA
11199 * and FRB is an Infinity. Test if FRB is zero.
11202 assign(fraInf_tmp
, is_Inf( Ity_I32
, frA_int
) );
11203 assign( frbInf_tmp
, is_Inf( Ity_I32
, frB_int
) );
11204 assign( frbZero_tmp
, is_Zero( Ity_I32
, frB_int
) );
11207 assign(fraInf_tmp
, is_Inf( Ity_I64
, frA_int
) );
11208 assign( frbInf_tmp
, is_Inf( Ity_I64
, frB_int
) );
11209 assign( frbZero_tmp
, is_Zero( Ity_I64
, frB_int
) );
11212 * Test if the double-precision floating-point operand in register FRB is
11215 frbNaN
= sp
? is_NaN( Ity_I32
, frB_int
) : is_NaN( Ity_I64
, frB_int
);
11218 * Test if e_b <= -1022 for double precision;
11219 * or e_b <= -126 for single precision
11222 UInt test_value
= sp
? 0xffffff82 : 0xfffffc02;
11223 eb_LTE
= binop(Iop_CmpLE32S
, mkexpr(e_b
), mkU32(test_value
));
11227 * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
11228 * or e_b >= -125 (125 < e_b) for single precision
11231 Int test_value
= sp
? 125 : 1021;
11232 eb_GTE
= binop(Iop_CmpLT32S
, mkU32(test_value
), mkexpr(e_b
));
11236 * Test if FRA != Zero and (e_a - e_b) >= bias
11239 assign( fraNotZero_tmp
, unop( Iop_Not1
, is_Zero( Ity_I32
, frA_int
) ) );
11241 assign( fraNotZero_tmp
, unop( Iop_Not1
, is_Zero( Ity_I64
, frA_int
) ) );
11243 ea_eb_GTE
= mkAND1( mkexpr( fraNotZero_tmp
),
11244 binop( Iop_CmpLT32S
, mkU32( bias
),
11245 binop( Iop_Sub32
, mkexpr( e_a
),
11246 mkexpr( e_b
) ) ) );
11249 * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
11252 UInt test_value
= sp
? 0xffffff83 : 0xfffffc03;
11254 ea_eb_LTE
= mkAND1( mkexpr( fraNotZero_tmp
),
11255 binop( Iop_CmpLE32S
,
11259 mkU32( test_value
) ) );
11263 * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
11266 UInt test_value
= 0xfffffc36; //Int test_value = -970;
11268 ea_LTE
= mkAND1( mkexpr( fraNotZero_tmp
), binop( Iop_CmpLE32S
,
11270 mkU32( test_value
) ) );
11272 ////////////////// fe_flag tests END //////////////////////
11274 ////////////////// fg_flag tests BEGIN //////////////////////
11276 * The following tests were already performed above in the fe_flag
11277 * tests. So these conditions will result in both fe_ and fg_ flags
11279 * - Test if FRA is an Infinity
11280 * - Test if FRB ix Zero
11281 * - Test if FRB is an Infinity
11285 * Test if FRB holds a denormalized value. A denormalized value is one where
11286 * the exp is 0 and the fraction is non-zero.
11289 IRExpr
* fraction_is_nonzero
;
11292 fraction_is_nonzero
= binop( Iop_CmpNE32
, FP_FRAC_PART32(frB_int
),
11295 IRExpr
* hi32
, * low32
;
11296 IRTemp frac_part
= newTemp(Ity_I64
);
11297 assign( frac_part
, FP_FRAC_PART(frB_int
) );
11299 hi32
= unop( Iop_64HIto32
, mkexpr( frac_part
) );
11300 low32
= unop( Iop_64to32
, mkexpr( frac_part
) );
11301 fraction_is_nonzero
= binop( Iop_CmpNE32
, binop( Iop_Or32
, low32
, hi32
),
11304 frbDenorm
= mkAND1( binop( Iop_CmpEQ32
, mkexpr( frB_exp_shR
),
11305 mkU32( 0x0 ) ), fraction_is_nonzero
);
11308 ////////////////// fg_flag tests END //////////////////////
11314 mkexpr( fraInf_tmp
),
11316 mkexpr( frbZero_tmp
),
11320 mkexpr( frbInf_tmp
),
11325 ea_LTE
) ) ) ) ) ) ) ) );
11327 fe_flag
= unop(Iop_1Uto32
, fe_flag
);
11329 fg_flag
= mkOR1( mkexpr( fraInf_tmp
), mkOR1( mkexpr( frbZero_tmp
),
11330 mkOR1( mkexpr( frbInf_tmp
),
11332 fg_flag
= unop(Iop_1Uto32
, fg_flag
);
11333 assign(*fe_flag_tmp
, fe_flag
);
11334 assign(*fg_flag_tmp
, fg_flag
);
11337 /* See description for _do_fp_tdiv() above. */
11338 static IRExpr
* do_fp_tdiv(IRTemp frA_int
, IRTemp frB_int
)
11340 IRTemp fe_flag
, fg_flag
;
11341 /////////////////////////
11342 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
11343 * where fl_flag == 1 on ppc64.
11345 IRExpr
* fl_flag
= unop(Iop_Not32
, mkU32(0xFFFFFE));
11346 fe_flag
= fg_flag
= IRTemp_INVALID
;
11347 _do_fp_tdiv(frA_int
, frB_int
, False
/*not single precision*/, &fe_flag
, &fg_flag
);
11348 return binop( Iop_Or32
,
11350 binop( Iop_Shl32
, fl_flag
, mkU8( 3 ) ),
11351 binop( Iop_Shl32
, mkexpr(fg_flag
), mkU8( 2 ) ) ),
11352 binop( Iop_Shl32
, mkexpr(fe_flag
), mkU8( 1 ) ) );
11355 static Bool
dis_fp_tests ( UInt theInstr
)
11357 UChar opc1
= ifieldOPC(theInstr
);
11358 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
11359 UChar frB_addr
= ifieldRegB(theInstr
);
11360 UChar b0
= ifieldBIT0(theInstr
);
11361 UInt opc2
= ifieldOPClo10(theInstr
);
11362 IRTemp frB_I64
= newTemp(Ity_I64
);
11364 if (opc1
!= 0x3F || b0
!= 0 ){
11365 vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
11368 assign( frB_I64
, unop( Iop_ReinterpF64asI64
, getFReg( frB_addr
) ) );
11371 case 0x080: // ftdiv
11373 UChar frA_addr
= ifieldRegA(theInstr
);
11374 IRTemp frA_I64
= newTemp(Ity_I64
);
11375 UChar b21to22
= toUChar( IFIELD( theInstr
, 21, 2 ) );
11376 if (b21to22
!= 0 ) {
11377 vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
11381 assign( frA_I64
, unop( Iop_ReinterpF64asI64
, getFReg( frA_addr
) ) );
11382 putGST_field( PPC_GST_CR
, do_fp_tdiv(frA_I64
, frB_I64
), crfD
);
11384 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD
, frA_addr
, frB_addr
);
11387 case 0x0A0: // ftsqrt
11389 IRTemp flags
= newTemp(Ity_I32
);
11390 IRTemp fe_flag
, fg_flag
;
11391 fe_flag
= fg_flag
= IRTemp_INVALID
;
11392 UChar b18to22
= toUChar( IFIELD( theInstr
, 18, 5 ) );
11393 if ( b18to22
!= 0) {
11394 vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
11397 DIP("ftsqrt crf%d,fr%u\n", crfD
, frB_addr
);
11398 do_fp_tsqrt(frB_I64
, False
/* not single precision*/, &fe_flag
, &fg_flag
);
11399 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
11400 * where fl_flag == 1 on ppc64.
11404 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
11405 binop( Iop_Shl32
, mkexpr(fg_flag
), mkU8( 2 ) ) ),
11406 binop( Iop_Shl32
, mkexpr(fe_flag
), mkU8( 1 ) ) ) );
11407 putGST_field( PPC_GST_CR
, mkexpr(flags
), crfD
);
11412 vex_printf("dis_fp_tests(ppc)(opc2)\n");
11420 Floating Point Compare Instructions
11422 static Bool
dis_fp_cmp ( UInt theInstr
)
11425 UChar opc1
= ifieldOPC(theInstr
);
11426 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
11427 UChar b21to22
= toUChar( IFIELD( theInstr
, 21, 2 ) );
11428 UChar frA_addr
= ifieldRegA(theInstr
);
11429 UChar frB_addr
= ifieldRegB(theInstr
);
11430 UInt opc2
= ifieldOPClo10(theInstr
);
11431 UChar b0
= ifieldBIT0(theInstr
);
11433 IRTemp ccIR
= newTemp(Ity_I32
);
11434 IRTemp ccPPC32
= newTemp(Ity_I32
);
11436 IRTemp frA
= newTemp(Ity_F64
);
11437 IRTemp frB
= newTemp(Ity_F64
);
11439 if (opc1
!= 0x3F || b21to22
!= 0 || b0
!= 0) {
11440 vex_printf("dis_fp_cmp(ppc)(instr)\n");
11444 assign( frA
, getFReg(frA_addr
));
11445 assign( frB
, getFReg(frB_addr
));
11447 assign( ccIR
, binop(Iop_CmpF64
, mkexpr(frA
), mkexpr(frB
)) );
11449 /* Map compare result from IR to PPC32 */
11451 FP cmp result | PPC | IR
11452 --------------------------
11459 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
11460 // | ((ccIR ^ (ccIR>>6)) & 1)
11474 binop(Iop_Shr32
, mkexpr(ccIR
), mkU8(5))
11483 binop(Iop_Shr32
, mkexpr(ccIR
), mkU8(6))
11492 putGST_field( PPC_GST_CR
, mkexpr(ccPPC32
), crfD
);
11493 putFPCC( mkexpr( ccPPC32
) );
11495 // XXX XXX XXX FIXME
11496 // Also write the result into FPRF (it's not entirely clear how)
11498 /* Note: Differences between fcmpu and fcmpo are only in exception
11499 flag settings, which aren't supported anyway. */
11501 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
11502 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD
, frA_addr
, frB_addr
);
11504 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
11505 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD
, frA_addr
, frB_addr
);
11508 vex_printf("dis_fp_cmp(ppc)(opc2)\n");
11517 Floating Point Rounding/Conversion Instructions
11519 static Bool
dis_fp_round ( UInt theInstr
)
11522 UChar opc1
= ifieldOPC(theInstr
);
11523 UChar b16to20
= ifieldRegA(theInstr
);
11524 UChar frD_addr
= ifieldRegDS(theInstr
);
11525 UChar frB_addr
= ifieldRegB(theInstr
);
11526 UInt opc2
= ifieldOPClo10(theInstr
);
11527 UChar flag_rC
= ifieldBIT0(theInstr
);
11529 IRTemp frD
= newTemp(Ity_F64
);
11530 IRTemp frB
= newTemp(Ity_F64
);
11531 IRTemp r_tmp32
= newTemp(Ity_I32
);
11532 IRTemp r_tmp64
= newTemp(Ity_I64
);
11533 IRExpr
* rm
= get_IR_roundingmode();
11535 /* By default, we will examine the results of the operation and set
11536 fpscr[FPRF] accordingly. */
11537 Bool set_FPRF
= True
;
11539 /* By default, if flag_RC is set, we will clear cr1 after the
11540 operation. In reality we should set cr1 to indicate the
11541 exception status of the operation, but since we're not
11542 simulating exceptions, the exception status will appear to be
11543 zero. Hence cr1 should be cleared if this is a . form insn. */
11544 Bool clear_CR1
= True
;
11545 if ((!(opc1
== 0x3F || opc1
== 0x3B)) || b16to20
!= 0) {
11546 vex_printf("dis_fp_round(ppc)(instr)\n");
11550 assign( frB
, getFReg(frB_addr
));
11551 if (opc1
== 0x3B) {
11552 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
11553 * they're very similar to the other instructions handled here, but have
11554 * a different primary opcode.
11557 case 0x34E: // fcfids (Float convert from signed DWord to single precision)
11558 DIP("fcfids%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11559 assign( r_tmp64
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
)) );
11560 assign( frD
, binop( Iop_RoundF64toF32
, rm
, binop( Iop_I64StoF64
, rm
,
11561 mkexpr( r_tmp64
) ) ) );
11564 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
11565 DIP("fcfidus%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11566 assign( r_tmp64
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
)) );
11567 assign( frD
, unop( Iop_F32toF64
, binop( Iop_I64UtoF32
, rm
, mkexpr( r_tmp64
) ) ) );
11574 case 0x00C: // frsp (Float Round to Single, PPC32 p423)
11575 DIP("frsp%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11576 assign( frD
, binop( Iop_RoundF64toF32
, rm
, mkexpr(frB
) ));
11579 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
11580 DIP("fctiw%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11582 binop(Iop_F64toI32S
, rm
, mkexpr(frB
)) );
11583 assign( frD
, unop( Iop_ReinterpI64asF64
,
11584 unop( Iop_32Uto64
, mkexpr(r_tmp32
))));
11585 /* FPRF is undefined after fctiw. Leave unchanged. */
11589 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
11590 DIP("fctiwz%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11592 binop(Iop_F64toI32S
, mkU32(Irrm_ZERO
), mkexpr(frB
) ));
11593 assign( frD
, unop( Iop_ReinterpI64asF64
,
11594 unop( Iop_32Uto64
, mkexpr(r_tmp32
))));
11595 /* FPRF is undefined after fctiwz. Leave unchanged. */
11599 case 0x08F: case 0x08E: // fctiwu[z]
11600 DIP("fctiwu%s%s fr%u,fr%u\n", opc2
== 0x08F ? "z" : "",
11601 flag_rC
? ".":"", frD_addr
, frB_addr
);
11603 binop( Iop_F64toI32U
,
11604 opc2
== 0x08F ? mkU32( Irrm_ZERO
) : rm
,
11606 assign( frD
, unop( Iop_ReinterpI64asF64
,
11607 unop( Iop_32Uto64
, mkexpr(r_tmp32
))));
11608 /* FPRF is undefined after fctiwz. Leave unchanged. */
11613 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
11614 DIP("fctid%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11616 binop(Iop_F64toI64S
, rm
, mkexpr(frB
)) );
11617 assign( frD
, unop( Iop_ReinterpI64asF64
, mkexpr(r_tmp64
)) );
11618 /* FPRF is undefined after fctid. Leave unchanged. */
11622 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
11623 DIP("fctidz%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11625 binop(Iop_F64toI64S
, mkU32(Irrm_ZERO
), mkexpr(frB
)) );
11626 assign( frD
, unop( Iop_ReinterpI64asF64
, mkexpr(r_tmp64
)) );
11627 /* FPRF is undefined after fctidz. Leave unchanged. */
11631 case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
11633 DIP("fctidu%s%s fr%u,fr%u\n", opc2
== 0x3AE ? "" : "z",
11634 flag_rC
? ".":"", frD_addr
, frB_addr
);
11636 binop(Iop_F64toI64U
, opc2
== 0x3AE ? rm
: mkU32(Irrm_ZERO
), mkexpr(frB
)) );
11637 assign( frD
, unop( Iop_ReinterpI64asF64
, mkexpr(r_tmp64
)) );
11638 /* FPRF is undefined after fctidz. Leave unchanged. */
11642 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
11643 DIP("fcfid%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11644 assign( r_tmp64
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
)) );
11646 binop(Iop_I64StoF64
, rm
, mkexpr(r_tmp64
)) );
11649 case 0x3CE: // fcfidu (Float convert from unsigned DWord)
11650 DIP("fcfidu%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11651 assign( r_tmp64
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
)) );
11652 assign( frD
, binop( Iop_I64UtoF64
, rm
, mkexpr( r_tmp64
) ) );
11655 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
11657 case 0x188: // frin (Floating Round to Integer Nearest)
11658 DIP("frin%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11660 binop(Iop_F64toI64S
, mkU32(Irrm_NEAREST
), mkexpr(frB
)) );
11662 case 0x1A8: // friz (Floating Round to Integer Toward Zero)
11663 DIP("friz%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11665 binop(Iop_F64toI64S
, mkU32(Irrm_ZERO
), mkexpr(frB
)) );
11667 case 0x1C8: // frip (Floating Round to Integer Plus)
11668 DIP("frip%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11670 binop(Iop_F64toI64S
, mkU32(Irrm_PosINF
), mkexpr(frB
)) );
11672 case 0x1E8: // frim (Floating Round to Integer Minus)
11673 DIP("frim%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
11675 binop(Iop_F64toI64S
, mkU32(Irrm_NegINF
), mkexpr(frB
)) );
11679 /* don't use the rounded integer if frB is outside -9e18..9e18 */
11680 /* F64 has only log10(2**52) significant digits anyway */
11681 /* need to preserve sign of zero */
11682 /* frD = (fabs(frB) > 9e18) ? frB :
11683 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */
11684 assign(frD
, IRExpr_ITE(
11688 IRExpr_Const(IRConst_F64(9e18
)),
11689 unop(Iop_AbsF64
, mkexpr(frB
)))),
11696 unop(Iop_ReinterpF64asI64
,
11702 binop(Iop_I64StoF64
, mkU32(0),
11703 mkexpr(r_tmp64
)) )),
11704 binop(Iop_I64StoF64
, mkU32(0), mkexpr(r_tmp64
) )
11710 vex_printf("dis_fp_round(ppc)(opc2)\n");
11714 putFReg( frD_addr
, mkexpr(frD
) );
11717 // XXX XXX XXX FIXME
11718 // set FPRF from frD
11721 if (flag_rC
&& clear_CR1
) {
11722 putCR321( 1, mkU8(0) );
11723 putCR0( 1, mkU8(0) );
11730 Floating Point Pair Instructions
11732 static Bool
dis_fp_pair ( UInt theInstr
)
11734 /* X-Form/DS-Form */
11735 UChar opc1
= ifieldOPC(theInstr
);
11736 UChar frT_hi_addr
= ifieldRegDS(theInstr
);
11737 UChar frT_lo_addr
= frT_hi_addr
+ 1;
11738 UChar rA_addr
= ifieldRegA(theInstr
);
11739 UChar rB_addr
= ifieldRegB(theInstr
);
11740 UInt uimm16
= ifieldUIMM16(theInstr
);
11741 Int simm16
= extend_s_16to32(uimm16
);
11742 UInt opc2
= ifieldOPClo10(theInstr
);
11743 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
11744 IRTemp EA_hi
= newTemp(ty
);
11745 IRTemp EA_lo
= newTemp(ty
);
11746 IRTemp frT_hi
= newTemp(Ity_F64
);
11747 IRTemp frT_lo
= newTemp(Ity_F64
);
11748 UChar b0
= ifieldBIT0(theInstr
);
11752 case 0x1F: // register offset
11753 /* These instructions work on a pair of registers. The specified
11754 * register must be even.
11756 if ((frT_hi_addr
%2) != 0) {
11757 vex_printf("dis_fp_pair(ppc) ldpx or stdpx: odd frT register\n");
11762 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125)
11763 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr
, rA_addr
, rB_addr
);
11766 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125)
11767 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr
, rA_addr
, rB_addr
);
11770 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
11775 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
11778 assign( EA_hi
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
11782 UInt DS
= IFIELD( theInstr
, 2, 14);
11783 UChar vRT
= ifieldRegDS(theInstr
);
11784 IRTemp EA
= newTemp( ty
);
11786 opc2
= ifieldOPC0o2(theInstr
);
11789 case 0x0: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125)
11790 /* This instruction works on a pair of registers. The specified
11791 * register must be even.
11793 if ((frT_hi_addr
%2) != 0) {
11794 vex_printf("dis_fp_pair(ppc) lfdp : odd frT register\n");
11798 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr
, simm16
, rA_addr
);
11799 assign( EA_hi
, ea_rAor0_simm( rA_addr
, simm16
) );
11803 case 0x2: // lxsd (Load VSX Scalar Doubleword)
11804 DIP("lxsd v%u,%u(r%u)\n", vRT
, DS
, rA_addr
);
11806 assign( EA
, ea_rAor0_simm( rA_addr
, DS
<<2 ) );
11808 putVSReg( vRT
+32, binop( Iop_64HLtoV128
,
11809 load( Ity_I64
, mkexpr( EA
) ),
11813 case 0x3: // lxssp (Load VSX Scalar Single from memory,
11814 // store as double in register)
11815 DIP("lxssp v%u,%u(r%u)\n", vRT
, DS
, rA_addr
);
11817 assign( EA
, ea_rAor0_simm( rA_addr
, DS
<<2 ) );
11820 binop( Iop_64HLtoV128
,
11821 unop( Iop_ReinterpF64asI64
,
11822 unop( Iop_F32toF64
,
11823 unop( Iop_ReinterpI32asF32
,
11824 load( Ity_I32
, mkexpr( EA
) ) ) ) ),
11829 vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n");
11836 UInt DS
= IFIELD( theInstr
, 2, 14);
11837 UChar vRS
= ifieldRegDS(theInstr
);
11838 IRTemp EA
= newTemp( ty
);
11840 opc2
= ifieldOPC0o2(theInstr
);
11844 // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125)
11845 /* This instruction works on a pair of registers. The specified
11846 * register must be even.
11848 if ((frT_hi_addr
%2) != 0) {
11849 vex_printf("dis_fp_pair(ppc) stfdp : odd frT register\n");
11853 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr
, simm16
, rA_addr
);
11854 assign( EA_hi
, ea_rAor0_simm( rA_addr
, simm16
) );
11862 UInt T
= IFIELD( theInstr
, 21, 5); // T or S depending on inst
11863 UInt TX
= IFIELD( theInstr
, 3, 1); // TX or SX field
11865 word
[0] = newTemp(Ity_I64
);
11866 word
[1] = newTemp(Ity_I64
);
11867 DS
= IFIELD( theInstr
, 4, 12); // DQ in the instruction definition
11868 assign( EA
, ea_rAor0_simm( rA_addr
, DS
<<4 ) );
11870 if ( IFIELD( theInstr
, 0, 3) == 1) {
11871 // lxv (Load VSX Vector)
11872 DIP("lxv v%u,%u(r%u)\n", vRS
, DS
, rA_addr
);
11874 assign( word
[0], load( Ity_I64
, mkexpr( EA
) ) );
11876 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
11877 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
11879 assign( word
[1], load( Ity_I64
, irx_addr
) );
11881 if (host_endness
== VexEndnessBE
)
11882 putVSReg( TX
*32+T
, binop( Iop_64HLtoV128
,
11884 mkexpr( word
[1] ) ) );
11886 putVSReg( TX
*32+T
, binop( Iop_64HLtoV128
,
11888 mkexpr( word
[0] ) ) );
11891 } else if ( IFIELD( theInstr
, 0, 3) == 5) {
11892 // stxv (Store VSX Vector)
11893 DIP("stxv v%u,%u(r%u)\n", vRS
, DS
, rA_addr
);
11895 if (host_endness
== VexEndnessBE
) {
11896 store( mkexpr(EA
), unop( Iop_V128HIto64
,
11897 getVSReg( TX
*32+T
) ) );
11898 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
11899 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
11900 store( irx_addr
, unop( Iop_V128to64
,
11901 getVSReg( TX
*32+T
) ) );
11903 store( mkexpr(EA
), unop( Iop_V128to64
,
11904 getVSReg( TX
*32+T
) ) );
11905 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
11906 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
11907 store( irx_addr
, unop( Iop_V128HIto64
,
11908 getVSReg( TX
*32+T
) ) );
11913 vex_printf("dis_fp_pair vector load/store (ppc) : DS-form wrong opc2\n");
11919 // stxsd (Store VSX Scalar Doubleword)
11920 DIP("stxsd v%u,%u(r%u)\n", vRS
, DS
, rA_addr
);
11922 assign( EA
, ea_rAor0_simm( rA_addr
, DS
<<2 ) );
11924 store( mkexpr(EA
), unop( Iop_V128HIto64
,
11925 getVSReg( vRS
+32 ) ) );
11926 /* HW is clearing vector element 1. Don't see that in the ISA but
11929 putVSReg( vRS
+32, binop( Iop_64HLtoV128
,
11930 unop( Iop_V128HIto64
,
11931 getVSReg( vRS
+32 ) ),
11937 // stxssp (Store VSX Scalar Single - store double precision
11938 // value from register into memory in single precision format)
11939 IRTemp high64
= newTemp(Ity_F64
);
11940 IRTemp val32
= newTemp(Ity_I32
);
11942 DIP("stxssp v%u,%u(r%u)\n", vRS
, DS
, rA_addr
);
11944 assign( EA
, ea_rAor0_simm( rA_addr
, DS
<<2 ) );
11945 assign(high64
, unop( Iop_ReinterpI64asF64
,
11946 unop( Iop_V128HIto64
, getVSReg( vRS
+32 ) ) ) );
11948 assign(val32
, unop( Iop_ReinterpF32asI32
,
11949 unop( Iop_TruncF64asF32
,
11950 mkexpr(high64
) ) ) );
11951 store( mkexpr(EA
), mkexpr( val32
) );
11956 vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n");
11961 default: // immediate offset
11962 vex_printf("dis_fp_pair(ppc)(instr)\n");
11967 assign( EA_lo
, binop(Iop_Add64
, mkexpr(EA_hi
), mkU64(8)) );
11969 assign( EA_lo
, binop(Iop_Add32
, mkexpr(EA_hi
), mkU32(8)) );
11971 assign( frT_hi
, getFReg(frT_hi_addr
) );
11972 assign( frT_lo
, getFReg(frT_lo_addr
) );
11975 putFReg( frT_hi_addr
, load(Ity_F64
, mkexpr(EA_hi
)) );
11976 putFReg( frT_lo_addr
, load(Ity_F64
, mkexpr(EA_lo
)) );
11978 store( mkexpr(EA_hi
), mkexpr(frT_hi
) );
11979 store( mkexpr(EA_lo
), mkexpr(frT_lo
) );
11987 Floating Point Merge Instructions
11989 static Bool
dis_fp_merge ( UInt theInstr
)
11992 UInt opc2
= ifieldOPClo10(theInstr
);
11993 UChar frD_addr
= ifieldRegDS(theInstr
);
11994 UChar frA_addr
= ifieldRegA(theInstr
);
11995 UChar frB_addr
= ifieldRegB(theInstr
);
11997 IRTemp frD
= newTemp(Ity_F64
);
11998 IRTemp frA
= newTemp(Ity_F64
);
11999 IRTemp frB
= newTemp(Ity_F64
);
12001 assign( frA
, getFReg(frA_addr
));
12002 assign( frB
, getFReg(frB_addr
));
12005 case 0x3c6: // fmrgew floating merge even word
12006 DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr
, frA_addr
, frB_addr
);
12008 assign( frD
, unop( Iop_ReinterpI64asF64
,
12009 binop( Iop_32HLto64
,
12010 unop( Iop_64HIto32
,
12011 unop( Iop_ReinterpF64asI64
,
12013 unop( Iop_64HIto32
,
12014 unop( Iop_ReinterpF64asI64
,
12015 mkexpr(frB
) ) ) ) ) );
12018 case 0x346: // fmrgow floating merge odd word
12019 DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr
, frA_addr
, frB_addr
);
12021 assign( frD
, unop( Iop_ReinterpI64asF64
,
12022 binop( Iop_32HLto64
,
12024 unop( Iop_ReinterpF64asI64
,
12027 unop( Iop_ReinterpF64asI64
,
12028 mkexpr(frB
) ) ) ) ) );
12032 vex_printf("dis_fp_merge(ppc)(opc2)\n");
12036 putFReg( frD_addr
, mkexpr(frD
) );
12041 Floating Point Move Instructions
12043 static Bool
dis_fp_move ( UInt theInstr
)
12046 UChar opc1
= ifieldOPC(theInstr
);
12047 UChar frD_addr
= ifieldRegDS(theInstr
);
12048 UChar frA_addr
= ifieldRegA(theInstr
);
12049 UChar frB_addr
= ifieldRegB(theInstr
);
12050 UInt opc2
= ifieldOPClo10(theInstr
);
12051 UChar flag_rC
= ifieldBIT0(theInstr
);
12053 IRTemp frD
= newTemp(Ity_F64
);
12054 IRTemp frB
= newTemp(Ity_F64
);
12055 IRTemp itmpB
= newTemp(Ity_F64
);
12060 if (opc1
!= 0x3F || (frA_addr
!= 0 && opc2
!= 0x008)) {
12061 vex_printf("dis_fp_move(ppc)(instr)\n");
12065 assign( frB
, getFReg(frB_addr
));
12068 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
12069 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frA_addr
,
12071 signA
= newTemp(Ity_I32
);
12072 hiD
= newTemp(Ity_I32
);
12073 itmpB
= newTemp(Ity_I64
);
12074 frA
= newTemp(Ity_F64
);
12075 assign( frA
, getFReg(frA_addr
) );
12077 /* get A's sign bit */
12078 assign(signA
, binop(Iop_And32
,
12079 unop(Iop_64HIto32
, unop(Iop_ReinterpF64asI64
,
12081 mkU32(0x80000000)) );
12083 assign( itmpB
, unop(Iop_ReinterpF64asI64
, mkexpr(frB
)) );
12085 /* mask off B's sign bit and or in A's sign bit */
12086 assign(hiD
, binop(Iop_Or32
,
12089 mkexpr(itmpB
)), /* frB's high 32 bits */
12090 mkU32(0x7fffffff)),
12093 /* combine hiD/loB into frD */
12094 assign( frD
, unop(Iop_ReinterpI64asF64
,
12095 binop(Iop_32HLto64
,
12098 mkexpr(itmpB
)))) ); /* frB's low 32 bits */
12101 case 0x028: // fneg (Floating Negate, PPC32 p416)
12102 DIP("fneg%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
12103 assign( frD
, unop( Iop_NegF64
, mkexpr(frB
) ));
12106 case 0x048: // fmr (Floating Move Register, PPC32 p410)
12107 DIP("fmr%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
12108 assign( frD
, mkexpr(frB
) );
12111 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
12112 DIP("fnabs%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
12113 assign( frD
, unop( Iop_NegF64
, unop( Iop_AbsF64
, mkexpr(frB
) )));
12116 case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
12117 DIP("fabs%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
12118 assign( frD
, unop( Iop_AbsF64
, mkexpr(frB
) ));
12122 vex_printf("dis_fp_move(ppc)(opc2)\n");
12126 putFReg( frD_addr
, mkexpr(frD
) );
12128 /* None of these change FPRF. cr1 is set in the usual way though,
12129 if flag_rC is set. */
12132 putCR321( 1, mkU8(0) );
12133 putCR0( 1, mkU8(0) );
12142 Floating Point Status/Control Register Instructions
12144 static Bool
dis_fp_scr ( UInt theInstr
, Bool GX_level
)
12146 /* Many forms - see each switch case */
12147 UChar opc1
= ifieldOPC(theInstr
);
12148 UInt opc2
= ifieldOPClo10(theInstr
);
12149 UChar flag_rC
= ifieldBIT0(theInstr
);
12151 if (opc1
!= 0x3F) {
12152 vex_printf("dis_fp_scr(ppc)(instr)\n");
12157 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
12158 // Bit crbD of the FPSCR is set.
12159 UChar crbD
= ifieldRegDS(theInstr
);
12160 UInt b11to20
= IFIELD(theInstr
, 11, 10);
12162 if (b11to20
!= 0) {
12163 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
12166 DIP("mtfsb1%s crb%d \n", flag_rC
? ".":"", crbD
);
12167 putGST_masked( PPC_GST_FPSCR
, mkU64( 1 <<( 31 - crbD
) ),
12168 1ULL << ( 31 - crbD
) );
12172 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
12173 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
12174 UChar b21to22
= toUChar( IFIELD( theInstr
, 21, 2 ) );
12175 UChar crfS
= toUChar( IFIELD( theInstr
, 18, 3 ) );
12176 UChar b11to17
= toUChar( IFIELD( theInstr
, 11, 7 ) );
12177 IRTemp tmp
= newTemp(Ity_I32
);
12179 if (b21to22
!= 0 || b11to17
!= 0 || flag_rC
!= 0) {
12180 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
12183 DIP("mcrfs crf%d,crf%d\n", crfD
, crfS
);
12186 fpscr_all
= getGST_masked( PPC_GST_FPSCR
, MASK_FPSCR_RN
);
12187 assign( tmp
, binop(Iop_And32
,
12188 binop(Iop_Shr32
,fpscr_all
,mkU8(4 * (7-crfS
))),
12190 putGST_field( PPC_GST_CR
, mkexpr(tmp
), crfD
);
12194 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
12195 // Bit crbD of the FPSCR is cleared.
12196 UChar crbD
= ifieldRegDS(theInstr
);
12197 UInt b11to20
= IFIELD(theInstr
, 11, 10);
12199 if (b11to20
!= 0) {
12200 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
12203 DIP("mtfsb0%s crb%d\n", flag_rC
? ".":"", crbD
);
12204 putGST_masked( PPC_GST_FPSCR
, mkU64( 0 ), 1ULL << ( 31 - crbD
) );
12208 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
12209 UInt crfD
= IFIELD( theInstr
, 23, 3 );
12210 UChar b17to22
= toUChar( IFIELD( theInstr
, 17, 6 ) );
12211 UChar IMM
= toUChar( IFIELD( theInstr
, 12, 4 ) );
12212 UChar b11
= toUChar( IFIELD( theInstr
, 11, 1 ) );
12213 UChar Wbit
= toUChar( IFIELD( theInstr
, 16, 1 ) );
12215 if (b17to22
!= 0 || b11
!= 0 || (Wbit
&& !GX_level
)) {
12216 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
12219 DIP("mtfsfi%s crf%u,%d%s\n", flag_rC
? ".":"", crfD
, IMM
, Wbit
? ",1":"");
12220 crfD
= crfD
+ (8 * (1 - Wbit
) );
12221 putGST_field( PPC_GST_FPSCR
, mkU32( IMM
), crfD
);
12225 case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
12226 UChar frD_addr
= ifieldRegDS(theInstr
);
12227 UChar frB_addr
= ifieldRegB(theInstr
);
12228 IRTemp frB
= newTemp(Ity_F64
);
12229 UInt b11to12
= IFIELD(theInstr
, 19, 2);
12230 UInt b13to15
= IFIELD(theInstr
, 16, 3);
12231 UInt RN
= IFIELD(theInstr
, 11, 2);
12232 UInt DRN
= IFIELD(theInstr
, 11, 3);
12234 /* The FPSCR_DRN, FPSCR_RN and FPSCR_FPCC are all stored in
12235 * their own 8-bit entries with distinct offsets. The FPSCR
12236 * register is handled as two 32-bit values. We need to
12237 * assemble the pieces into the single 64-bit value to return.
12239 IRExpr
* fpscr_lower
12241 getGST_masked( PPC_GST_FPSCR
, (MASK_FPSCR_RN
| MASK_FPSCR_C_FPCC
) ),
12249 IRExpr
* fpscr_upper
= getGST_masked_upper( PPC_GST_FPSCR
, MASK_FPSCR_DRN
);
12251 if ((b11to12
== 0) && (b13to15
== 0)) {
12252 DIP("mffs%s fr%u\n", flag_rC
? ".":"", frD_addr
);
12254 unop( Iop_ReinterpI64asF64
,
12255 binop( Iop_32HLto64
, fpscr_upper
, fpscr_lower
) ) );
12257 } else if ((b11to12
== 0) && (b13to15
== 1)) {
12258 DIP("mffsce fr%u\n", frD_addr
);
12259 /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE,
12260 or XE but in case that changes in the future, do the masking. */
12262 unop( Iop_ReinterpI64asF64
,
12263 binop( Iop_32HLto64
, fpscr_upper
,
12264 binop( Iop_And32
, fpscr_lower
,
12265 mkU32( 0xFFFFFF07 ) ) ) ) );
12267 } else if ((b11to12
== 2) && (b13to15
== 4)) {
12268 IRTemp frB_int
= newTemp(Ity_I64
);
12270 DIP("mffscdrn fr%u,fr%u\n", frD_addr
, frB_addr
);
12272 assign( frB
, getFReg(frB_addr
));
12273 assign( frB_int
, unop( Iop_ReinterpF64asI64
, mkexpr( frB
) ) );
12275 /* Clear all of the FPSCR bits except for the DRN field, VE,
12276 OE, UE, ZE and XE bits and write the result to the frD
12277 register. Note, currently the exception bits are not tracked but
12278 will mask anyway in case that changes in the future. */
12280 unop( Iop_ReinterpI64asF64
,
12281 binop( Iop_32HLto64
,
12282 binop( Iop_And32
, mkU32(0x7), fpscr_upper
),
12283 binop( Iop_And32
, mkU32(0xFF), fpscr_lower
) ) ) );
12285 /* Put new_DRN bits into the FPSCR register */
12286 putGST_masked( PPC_GST_FPSCR
, mkexpr( frB_int
), MASK_FPSCR_DRN
);
12288 } else if ((b11to12
== 2) && (b13to15
== 5)) {
12289 DIP("mffscdrni fr%u,%u\n", frD_addr
, DRN
);
12291 /* Clear all of the FPSCR bits except for the DRN field, VE,
12292 OE, UE, ZE and XE bits and write the result to the frD
12293 register. Note, currently the exception bits are not tracked but
12294 will mask anyway in case that changes in the future. */
12296 unop( Iop_ReinterpI64asF64
,
12297 binop( Iop_32HLto64
,
12298 binop( Iop_And32
, mkU32(0x7), fpscr_upper
),
12299 binop( Iop_And32
, mkU32(0xFF), fpscr_lower
) ) ) );
12301 /* Put new_DRN bits into the FPSCR register */
12302 putGST_masked( PPC_GST_FPSCR
, binop( Iop_32HLto64
, mkU32( DRN
),
12303 mkU32( 0 ) ), MASK_FPSCR_DRN
);
12305 } else if ((b11to12
== 2) && (b13to15
== 6)) {
12306 IRTemp frB_int
= newTemp(Ity_I64
);
12308 DIP("mffscrn fr%u,fr%u\n", frD_addr
,frB_addr
);
12310 assign( frB
, getFReg(frB_addr
));
12311 assign( frB_int
, unop( Iop_ReinterpF64asI64
, mkexpr( frB
) ) );
12313 /* Clear all of the FPSCR bits except for the DRN field, VE,
12314 OE, UE, ZE and XE bits and write the result to the frD
12315 register. Note, currently the exception bits are not tracked but
12316 will mask anyway in case that changes in the future. */
12318 unop( Iop_ReinterpI64asF64
,
12319 binop( Iop_32HLto64
,
12320 binop( Iop_And32
, mkU32(0x7), fpscr_upper
),
12321 binop( Iop_And32
, mkU32(0xFF), fpscr_lower
) ) ) );
12323 /* Put new_CRN bits into the FPSCR register */
12324 putGST_masked( PPC_GST_FPSCR
, mkexpr( frB_int
), MASK_FPSCR_RN
);
12326 } else if ((b11to12
== 2) && (b13to15
== 7)) {
12327 DIP("mffscrni fr%u,%u\n", frD_addr
, RN
);
12329 /* Clear all of the FPSCR bits except for the DRN field, VE,
12330 OE, UE, ZE and XE bits and write the result to the frD
12331 register. Note, currently the exception bits are not tracked but
12332 will mask anyway in case that changes in the future. */
12334 unop( Iop_ReinterpI64asF64
,
12335 binop( Iop_32HLto64
,
12336 binop( Iop_And32
, mkU32(0x7), fpscr_upper
),
12337 binop( Iop_And32
, mkU32(0xFF), fpscr_lower
) ) ) );
12339 /* Put new_RN bits into the FPSCR register */
12340 putGST_masked( PPC_GST_FPSCR
, binop( Iop_32HLto64
, mkU32( 0 ),
12341 mkU32( RN
) ), MASK_FPSCR_RN
);
12343 } else if ((b11to12
== 3) && (b13to15
== 0)) {
12344 DIP("mffsl fr%u\n", frD_addr
);
12345 /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE,
12346 XE, FR, FI, C, FL, FG, FE, FU. Also only track DRN in the upper
12347 bits but in case that changes in the future we will do the
12350 unop( Iop_ReinterpI64asF64
,
12351 binop( Iop_32HLto64
,
12352 binop( Iop_And32
, fpscr_upper
,
12354 binop( Iop_And32
, fpscr_lower
,
12355 mkU32( 0x7F0FF ) ) ) ) );
12357 vex_printf("dis_fp_scr(ppc)(mff**) Unrecognized instruction.\n");
12363 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
12364 UChar b25
= toUChar( IFIELD(theInstr
, 25, 1) );
12365 UChar FM
= toUChar( IFIELD(theInstr
, 17, 8) );
12366 UChar frB_addr
= ifieldRegB(theInstr
);
12367 IRTemp frB
= newTemp(Ity_F64
);
12368 IRTemp rB_64
= newTemp( Ity_I64
);
12372 #define BFP_MASK_SEED 0x3000000000000000ULL
12373 #define DFP_MASK_SEED 0x7000000000000000ULL
12376 /* This implies that Decimal Floating Point is supported, and the
12377 * FPSCR must be managed as a 64-bit register.
12379 Wbit
= toUChar( IFIELD(theInstr
, 16, 1) );
12385 /* new 64 bit move variant for power 6. If L field (bit 25) is
12386 * a one do a full 64 bit move. Note, the FPSCR is not really
12387 * properly modeled. This instruciton only changes the value of
12388 * the rounding mode bit fields RN, FPCC and DRN. The HW exception bits
12389 * do not get set in the simulator. 1/12/09
12391 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC
? ".":"", FM
, frB_addr
);
12392 mask
= 0x1F0001F003;
12395 DIP("mtfsf%s %d,fr%u\n", flag_rC
? ".":"", FM
, frB_addr
);
12396 // Build 32bit mask from FM:
12398 for (i
=0; i
<8; i
++) {
12399 if ((FM
& (1<<(7-i
))) == 1) {
12400 /* FPSCR field k is set to the contents of the corresponding
12401 * field of register FRB, where k = i+8x(1-W). In the Power
12402 * ISA, register field numbering is from left to right, so field
12403 * 15 is the least significant field in a 64-bit register. To
12404 * generate the mask, we set all the appropriate rounding mode
12405 * bits in the highest order nibble (field 0) and shift right
12406 * 'k x nibble length'.
12409 mask
|= DFP_MASK_SEED
>> ( 4 * ( i
+ 8 * ( 1 - Wbit
) ) );
12411 mask
|= BFP_MASK_SEED
>> ( 4 * ( i
+ 8 * ( 1 - Wbit
) ) );
12413 if ((FM
& (1<<(7-i
))) == 0x2) { //set the FPCC bits
12416 if ((FM
& (1<<(7-i
))) == 0x4) { //set the Floating-Point Class Descriptor (C) bit
12421 assign( frB
, getFReg(frB_addr
));
12422 assign( rB_64
, unop( Iop_ReinterpF64asI64
, mkexpr( frB
) ) );
12423 putGST_masked( PPC_GST_FPSCR
, mkexpr( rB_64
), mask
);
12428 vex_printf("dis_fp_scr(ppc)(opc2)\n");
12434 /*------------------------------------------------------------*/
12435 /*--- Decimal Floating Point (DFP) Helper functions ---*/
12436 /*------------------------------------------------------------*/
12438 #define DFP_EXTND 2
12439 #define DFP_LONG_BIAS 398
12440 #define DFP_LONG_ENCODED_FIELD_MASK 0x1F00
12441 #define DFP_EXTND_BIAS 6176
12442 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
12443 #define DFP_LONG_EXP_MSK 0XFF
12444 #define DFP_EXTND_EXP_MSK 0XFFF
12446 #define DFP_G_FIELD_LONG_MASK 0x7FFC0000 // upper 32-bits only
12447 #define DFP_LONG_GFIELD_RT_SHIFT (63 - 13 - 32) // adj for upper 32-bits
12448 #define DFP_G_FIELD_EXTND_MASK 0x7FFFC000 // upper 32-bits only
12449 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
12450 #define DFP_T_FIELD_LONG_MASK 0x3FFFF // mask for upper 32-bits
12451 #define DFP_T_FIELD_EXTND_MASK 0x03FFFF // mask for upper 32-bits
12452 #define DFP_LONG_EXP_MAX 369 // biased max
12453 #define DFP_LONG_EXP_MIN 0 // biased min
12454 #define DFP_EXTND_EXP_MAX 6111 // biased max
12455 #define DFP_EXTND_EXP_MIN 0 // biased min
12456 #define DFP_LONG_MAX_SIG_DIGITS 16
12457 #define DFP_EXTND_MAX_SIG_DIGITS 34
12458 #define MAX_DIGITS_IN_STRING 8
12461 #define AND(x, y) binop( Iop_And32, x, y )
12462 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
12463 #define OR(x, y) binop( Iop_Or32, x, y )
12464 #define OR3(x, y, z) OR( x, OR( y, z ) )
12465 #define OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
12466 #define NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1, mkexpr( x ) ) ) )
12468 #define SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
12469 #define SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
12471 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
12472 (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
12473 ((_b1) << 1) | ((_b0) << 0))
12475 static IRExpr
* Gfield_encoding( IRExpr
* lmexp
, IRExpr
* lmd32
)
12477 IRTemp lmd_07_mask
= newTemp( Ity_I32
);
12478 IRTemp lmd_8_mask
= newTemp( Ity_I32
);
12479 IRTemp lmd_9_mask
= newTemp( Ity_I32
);
12480 IRTemp lmexp_00_mask
= newTemp( Ity_I32
);
12481 IRTemp lmexp_01_mask
= newTemp( Ity_I32
);
12482 IRTemp lmexp_10_mask
= newTemp( Ity_I32
);
12483 IRTemp lmd_07_val
= newTemp( Ity_I32
);
12484 IRTemp lmd_8_val
= newTemp( Ity_I32
);
12485 IRTemp lmd_9_val
= newTemp( Ity_I32
);
12487 /* The encodig is as follows:
12488 * lmd - left most digit
12489 * lme - left most 2-bits of the exponent
12492 * 0 - 7 (lmexp << 3) | lmd
12493 * 8 0b11000 (24 decimal) if lme=0b00;
12494 * 0b11010 (26 decimal) if lme=0b01;
12495 * 0b11100 (28 decimal) if lme=0b10;
12496 * 9 0b11001 (25 decimal) if lme=0b00;
12497 * 0b11011 (27 decimal) if lme=0b01;
12498 * 0b11101 (29 decimal) if lme=0b10;
12501 /* Generate the masks for each condition */
12502 assign( lmd_07_mask
,
12503 unop( Iop_1Sto32
, binop( Iop_CmpLE32U
, lmd32
, mkU32( 7 ) ) ) );
12504 assign( lmd_8_mask
,
12505 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, lmd32
, mkU32( 8 ) ) ) );
12506 assign( lmd_9_mask
,
12507 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, lmd32
, mkU32( 9 ) ) ) );
12508 assign( lmexp_00_mask
,
12509 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, lmexp
, mkU32( 0 ) ) ) );
12510 assign( lmexp_01_mask
,
12511 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, lmexp
, mkU32( 1 ) ) ) );
12512 assign( lmexp_10_mask
,
12513 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, lmexp
, mkU32( 2 ) ) ) );
12515 /* Generate the values for each LMD condition, assuming the condition
12518 assign( lmd_07_val
,
12519 binop( Iop_Or32
, binop( Iop_Shl32
, lmexp
, mkU8( 3 ) ), lmd32
) );
12524 mkexpr( lmexp_00_mask
),
12527 mkexpr( lmexp_01_mask
),
12529 binop( Iop_And32
, mkexpr( lmexp_10_mask
), mkU32( 28 ) ) ) );
12534 mkexpr( lmexp_00_mask
),
12537 mkexpr( lmexp_01_mask
),
12539 binop( Iop_And32
, mkexpr( lmexp_10_mask
), mkU32( 29 ) ) ) );
12541 /* generate the result from the possible LMD values */
12542 return binop( Iop_Or32
,
12545 mkexpr( lmd_07_mask
),
12546 mkexpr( lmd_07_val
) ),
12548 mkexpr( lmd_8_mask
),
12549 mkexpr( lmd_8_val
) ) ),
12550 binop( Iop_And32
, mkexpr( lmd_9_mask
), mkexpr( lmd_9_val
) ) );
12553 static void Get_lmd( IRTemp
* lmd
, IRExpr
* gfield_0_4
)
12555 /* Extract the exponent and the left most digit of the mantissa
12556 * from the G field bits [0:4].
12558 IRTemp lmd_07_mask
= newTemp( Ity_I32
);
12559 IRTemp lmd_8_00_mask
= newTemp( Ity_I32
);
12560 IRTemp lmd_8_01_mask
= newTemp( Ity_I32
);
12561 IRTemp lmd_8_10_mask
= newTemp( Ity_I32
);
12562 IRTemp lmd_9_00_mask
= newTemp( Ity_I32
);
12563 IRTemp lmd_9_01_mask
= newTemp( Ity_I32
);
12564 IRTemp lmd_9_10_mask
= newTemp( Ity_I32
);
12566 IRTemp lmd_07_val
= newTemp( Ity_I32
);
12567 IRTemp lmd_8_val
= newTemp( Ity_I32
);
12568 IRTemp lmd_9_val
= newTemp( Ity_I32
);
12570 /* The left most digit (LMD) encoding is as follows:
12572 * 0 - 7 (lmexp << 3) | lmd
12573 * 8 0b11000 (24 decimal) if lme=0b00;
12574 * 0b11010 (26 decimal) if lme=0b01;
12575 * 0b11100 (28 decimal) if lme=0b10
12576 * 9 0b11001 (25 decimal) if lme=0b00;
12577 * 0b11011 (27 decimal) if lme=0b01;
12578 * 0b11101 (29 decimal) if lme=0b10;
12581 /* Generate the masks for each condition of LMD and exponent bits */
12582 assign( lmd_07_mask
,
12583 unop( Iop_1Sto32
, binop( Iop_CmpLE32U
,
12585 mkU32( BITS5(1,0,1,1,1) ) ) ) );
12586 assign( lmd_8_00_mask
,
12587 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
12589 mkU32( BITS5(1,1,0,0,0) ) ) ) );
12590 assign( lmd_8_01_mask
,
12591 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
12593 mkU32( BITS5(1,1,0,1,0) ) ) ) );
12594 assign( lmd_8_10_mask
,
12595 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
12597 mkU32( BITS5(1,1,1,0,0) ) ) ) );
12598 assign( lmd_9_00_mask
,
12599 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
12601 mkU32( BITS5(1,1,0,0,1) ) ) ) );
12602 assign( lmd_9_01_mask
,
12603 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
12605 mkU32( BITS5(1,1,0,1,1) ) ) ) );
12606 assign( lmd_9_10_mask
,
12607 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
12609 mkU32( BITS5(1,1,1,0,1) ) ) ) );
12611 /* Generate the values for each LMD condition, assuming the condition
12614 assign( lmd_07_val
, binop( Iop_And32
, gfield_0_4
, mkU32( 0x7 ) ) );
12615 assign( lmd_8_val
, mkU32( 0x8 ) );
12616 assign( lmd_9_val
, mkU32( 0x9 ) );
12619 OR( OR3 ( AND( mkexpr( lmd_07_mask
), mkexpr( lmd_07_val
) ),
12620 AND( mkexpr( lmd_8_00_mask
), mkexpr( lmd_8_val
) ),
12621 AND( mkexpr( lmd_8_01_mask
), mkexpr( lmd_8_val
) )),
12622 OR4( AND( mkexpr( lmd_8_10_mask
), mkexpr( lmd_8_val
) ),
12623 AND( mkexpr( lmd_9_00_mask
), mkexpr( lmd_9_val
) ),
12624 AND( mkexpr( lmd_9_01_mask
), mkexpr( lmd_9_val
) ),
12625 AND( mkexpr( lmd_9_10_mask
), mkexpr( lmd_9_val
) )
12629 #define DIGIT1_SHR 4 // shift digit 1 to bottom 4 bits
12630 #define DIGIT2_SHR 8 // shift digit 2 to bottom 4 bits
12631 #define DIGIT3_SHR 12
12632 #define DIGIT4_SHR 16
12633 #define DIGIT5_SHR 20
12634 #define DIGIT6_SHR 24
12635 #define DIGIT7_SHR 28
12637 static IRExpr
* bcd_digit_inval( IRExpr
* bcd_u
, IRExpr
* bcd_l
)
12639 /* 60-bit BCD string stored in two 32-bit values. Check that each,
12640 * digit is a valid BCD number, i.e. less then 9.
12642 IRTemp valid
= newTemp( Ity_I32
);
12645 AND4( AND4 ( unop( Iop_1Sto32
,
12646 binop( Iop_CmpLE32U
,
12652 binop( Iop_CmpLE32U
,
12656 mkU8 ( DIGIT1_SHR
) ),
12660 binop( Iop_CmpLE32U
,
12664 mkU8 ( DIGIT2_SHR
) ),
12668 binop( Iop_CmpLE32U
,
12672 mkU8 ( DIGIT3_SHR
) ),
12674 mkU32( 0x9 ) ) ) ),
12675 AND4 ( unop( Iop_1Sto32
,
12676 binop( Iop_CmpLE32U
,
12680 mkU8 ( DIGIT4_SHR
) ),
12684 binop( Iop_CmpLE32U
,
12688 mkU8 ( DIGIT5_SHR
) ),
12692 binop( Iop_CmpLE32U
,
12696 mkU8 ( DIGIT6_SHR
) ),
12700 binop( Iop_CmpLE32U
,
12704 mkU8 ( DIGIT7_SHR
) ),
12706 mkU32( 0x9 ) ) ) ),
12707 AND4( unop( Iop_1Sto32
,
12708 binop( Iop_CmpLE32U
,
12714 binop( Iop_CmpLE32U
,
12718 mkU8 ( DIGIT1_SHR
) ),
12722 binop( Iop_CmpLE32U
,
12726 mkU8 ( DIGIT2_SHR
) ),
12730 binop( Iop_CmpLE32U
,
12734 mkU8 ( DIGIT3_SHR
) ),
12736 mkU32( 0x9 ) ) ) ),
12737 AND4( unop( Iop_1Sto32
,
12738 binop( Iop_CmpLE32U
,
12742 mkU8 ( DIGIT4_SHR
) ),
12746 binop( Iop_CmpLE32U
,
12750 mkU8 ( DIGIT5_SHR
) ),
12754 binop( Iop_CmpLE32U
,
12758 mkU8 ( DIGIT6_SHR
) ),
12762 binop( Iop_CmpLE32U
,
12766 mkU8 ( DIGIT7_SHR
) ),
12768 mkU32( 0x9 ) ) ) ) ) );
12770 return unop( Iop_Not32
, mkexpr( valid
) );
12780 static IRExpr
* Generate_neg_sign_mask( IRExpr
* sign
)
12782 return binop( Iop_Or32
,
12783 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, sign
, mkU32( 0xB ) ) ),
12784 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, sign
, mkU32( 0xD ) ) )
12788 static IRExpr
* Generate_pos_sign_mask( IRExpr
* sign
)
12790 return binop( Iop_Or32
,
12793 binop( Iop_CmpEQ32
, sign
, mkU32( 0xA ) ) ),
12795 binop( Iop_CmpEQ32
, sign
, mkU32( 0xC ) ) ) ),
12798 binop( Iop_CmpEQ32
, sign
, mkU32( 0xE ) ) ),
12800 binop( Iop_CmpEQ32
, sign
, mkU32( 0xF ) ) ) ) );
12803 static IRExpr
* Generate_sign_bit( IRExpr
* pos_sign_mask
,
12804 IRExpr
* neg_sign_mask
)
12806 return binop( Iop_Or32
,
12807 binop( Iop_And32
, neg_sign_mask
, mkU32( 0x80000000 ) ),
12808 binop( Iop_And32
, pos_sign_mask
, mkU32( 0x00000000 ) ) );
12811 static IRExpr
* Generate_inv_mask( IRExpr
* invalid_bcd_mask
,
12812 IRExpr
* pos_sign_mask
,
12813 IRExpr
* neg_sign_mask
)
12814 /* first argument is all 1's if the BCD string had an invalid digit in it. */
12816 return binop( Iop_Or32
,
12819 binop( Iop_CmpEQ32
,
12820 binop( Iop_Or32
, pos_sign_mask
, neg_sign_mask
),
12821 mkU32( 0x0 ) ) ) );
12824 static void Generate_132_bit_bcd_string( IRExpr
* frBI64_hi
, IRExpr
* frBI64_lo
,
12825 IRTemp
* top_12_l
, IRTemp
* mid_60_u
,
12826 IRTemp
* mid_60_l
, IRTemp
* low_60_u
,
12829 IRTemp tmplow60
= newTemp( Ity_I64
);
12830 IRTemp tmpmid60
= newTemp( Ity_I64
);
12831 IRTemp tmptop12
= newTemp( Ity_I64
);
12832 IRTemp low_50
= newTemp( Ity_I64
);
12833 IRTemp mid_50
= newTemp( Ity_I64
);
12834 IRTemp top_10
= newTemp( Ity_I64
);
12835 IRTemp top_12_u
= newTemp( Ity_I32
); // only needed for a dummy arg
12837 /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
12839 /* low_50[49:0] = ((frBI64_lo[49:32] << 14) | frBI64_lo[31:0]) */
12841 binop( Iop_32HLto64
,
12843 unop( Iop_64HIto32
, frBI64_lo
),
12844 mkU32( 0x3FFFF ) ),
12845 unop( Iop_64to32
, frBI64_lo
) ) );
12847 /* Convert the 50 bit densely packed BCD string to a 60 bit
12850 assign( tmplow60
, unop( Iop_DPBtoBCD
, mkexpr( low_50
) ) );
12851 assign( *low_60_u
, unop( Iop_64HIto32
, mkexpr( tmplow60
) ) );
12852 assign( *low_60_l
, unop( Iop_64to32
, mkexpr( tmplow60
) ) );
12854 /* mid_50[49:0] = ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
12855 * ((frBI64_hi[17:0] << 14) | frBI64_lo[63:50])
12858 binop( Iop_32HLto64
,
12862 unop( Iop_64HIto32
, frBI64_hi
),
12866 unop( Iop_64to32
, frBI64_hi
),
12870 unop( Iop_64to32
, frBI64_hi
),
12873 unop( Iop_64HIto32
, frBI64_lo
),
12874 mkU8( 18 ) ) ) ) );
12876 /* Convert the 50 bit densely packed BCD string to a 60 bit
12879 assign( tmpmid60
, unop( Iop_DPBtoBCD
, mkexpr( mid_50
) ) );
12880 assign( *mid_60_u
, unop( Iop_64HIto32
, mkexpr( tmpmid60
) ) );
12881 assign( *mid_60_l
, unop( Iop_64to32
, mkexpr( tmpmid60
) ) );
12883 /* top_10[49:0] = frBI64_hi[45:36]) | */
12885 binop( Iop_32HLto64
,
12889 unop( Iop_64HIto32
, frBI64_hi
),
12891 mkU32( 0x3FF ) ) ) );
12893 /* Convert the 10 bit densely packed BCD string to a 12 bit
12896 assign( tmptop12
, unop( Iop_DPBtoBCD
, mkexpr( top_10
) ) );
12897 assign( top_12_u
, unop( Iop_64HIto32
, mkexpr( tmptop12
) ) );
12898 assign( *top_12_l
, unop( Iop_64to32
, mkexpr( tmptop12
) ) );
12901 static void Count_zeros( int start
, IRExpr
* init_cnt
, IRExpr
* init_flag
,
12902 IRTemp
* final_cnt
, IRTemp
* final_flag
,
12905 IRTemp cnt
[MAX_DIGITS_IN_STRING
+ 1];IRTemp flag
[MAX_DIGITS_IN_STRING
+1];
12906 int digits
= MAX_DIGITS_IN_STRING
;
12909 cnt
[start
-1] = newTemp( Ity_I8
);
12910 flag
[start
-1] = newTemp( Ity_I8
);
12911 assign( cnt
[start
-1], init_cnt
);
12912 assign( flag
[start
-1], init_flag
);
12914 for ( i
= start
; i
<= digits
; i
++) {
12915 cnt
[i
] = newTemp( Ity_I8
);
12916 flag
[i
] = newTemp( Ity_I8
);
12919 mkexpr( cnt
[i
-1] ),
12926 ( ( digits
- i
) * 4) ) ),
12928 binop( Iop_Xor8
, /* complement flag */
12929 mkexpr( flag
[i
- 1] ),
12930 mkU8( 0xFF ) ) ) ) );
12932 /* set flag to 1 if digit was not a zero */
12940 ( (digits
- i
) * 4) ) ),
12942 mkexpr( flag
[i
- 1] ) ) );
12945 *final_cnt
= cnt
[digits
];
12946 *final_flag
= flag
[digits
];
12949 static IRExpr
* Count_leading_zeros_60( IRExpr
* lmd
, IRExpr
* upper_28
,
12952 IRTemp num_lmd
= newTemp( Ity_I8
);
12953 IRTemp num_upper
= newTemp( Ity_I8
);
12954 IRTemp num_low
= newTemp( Ity_I8
);
12955 IRTemp lmd_flag
= newTemp( Ity_I8
);
12956 IRTemp upper_flag
= newTemp( Ity_I8
);
12957 IRTemp low_flag
= newTemp( Ity_I8
);
12959 assign( num_lmd
, unop( Iop_1Uto8
, binop( Iop_CmpEQ32
, lmd
, mkU32( 0 ) ) ) );
12960 assign( lmd_flag
, unop( Iop_Not8
, mkexpr( num_lmd
) ) );
12964 mkexpr( lmd_flag
),
12970 mkexpr( num_upper
),
12971 mkexpr( upper_flag
),
12976 return mkexpr( num_low
);
12979 static IRExpr
* Count_leading_zeros_128( IRExpr
* lmd
, IRExpr
* top_12_l
,
12980 IRExpr
* mid_60_u
, IRExpr
* mid_60_l
,
12981 IRExpr
* low_60_u
, IRExpr
* low_60_l
)
12983 IRTemp num_lmd
= newTemp( Ity_I8
);
12984 IRTemp num_top
= newTemp( Ity_I8
);
12985 IRTemp num_mid_u
= newTemp( Ity_I8
);
12986 IRTemp num_mid_l
= newTemp( Ity_I8
);
12987 IRTemp num_low_u
= newTemp( Ity_I8
);
12988 IRTemp num_low_l
= newTemp( Ity_I8
);
12990 IRTemp lmd_flag
= newTemp( Ity_I8
);
12991 IRTemp top_flag
= newTemp( Ity_I8
);
12992 IRTemp mid_u_flag
= newTemp( Ity_I8
);
12993 IRTemp mid_l_flag
= newTemp( Ity_I8
);
12994 IRTemp low_u_flag
= newTemp( Ity_I8
);
12995 IRTemp low_l_flag
= newTemp( Ity_I8
);
12997 /* Check the LMD, digit 34, to see if it is zero. */
12998 assign( num_lmd
, unop( Iop_1Uto8
, binop( Iop_CmpEQ32
, lmd
, mkU32( 0 ) ) ) );
13000 assign( lmd_flag
, unop( Iop_Not8
, mkexpr( num_lmd
) ) );
13004 mkexpr( lmd_flag
),
13011 mkexpr( top_flag
),
13015 binop( Iop_Shl32
, mid_60_u
, mkU8( 2 ) ),
13016 binop( Iop_Shr32
, mid_60_l
, mkU8( 30 ) ) ) );
13019 mkexpr( num_mid_u
),
13020 mkexpr( mid_u_flag
),
13026 mkexpr( num_mid_l
),
13027 mkexpr( mid_l_flag
),
13031 binop( Iop_Shl32
, low_60_u
, mkU8( 2 ) ),
13032 binop( Iop_Shr32
, low_60_l
, mkU8( 30 ) ) ) );
13035 mkexpr( num_low_u
),
13036 mkexpr( low_u_flag
),
13041 return mkexpr( num_low_l
);
13044 static IRExpr
* Check_unordered(IRExpr
* val
)
13046 IRTemp gfield0to5
= newTemp( Ity_I32
);
13048 /* Extract G[0:4] */
13049 assign( gfield0to5
,
13051 binop( Iop_Shr32
, unop( Iop_64HIto32
, val
), mkU8( 26 ) ),
13054 /* Check for unordered, return all 1'x if true */
13055 return binop( Iop_Or32
, /* QNaN check */
13057 binop( Iop_CmpEQ32
,
13058 mkexpr( gfield0to5
),
13060 unop( Iop_1Sto32
, /* SNaN check */
13061 binop( Iop_CmpEQ32
,
13062 mkexpr( gfield0to5
),
13063 mkU32( 0x1F ) ) ) );
13076 /*------------------------------------------------------------*/
13077 /*--- Decimal Floating Point (DFP) instruction translation ---*/
13078 /*------------------------------------------------------------*/
13080 /* DFP Arithmetic instructions */
13081 static Bool
dis_dfp_arith(UInt theInstr
)
13083 UInt opc2
= ifieldOPClo10( theInstr
);
13084 UChar frS_addr
= ifieldRegDS( theInstr
);
13085 UChar frA_addr
= ifieldRegA( theInstr
);
13086 UChar frB_addr
= ifieldRegB( theInstr
);
13087 UChar flag_rC
= ifieldBIT0( theInstr
);
13089 IRTemp frA
= newTemp( Ity_D64
);
13090 IRTemp frB
= newTemp( Ity_D64
);
13091 IRTemp frS
= newTemp( Ity_D64
);
13092 IRExpr
* round
= get_IR_roundingmode_DFP();
13094 /* By default, if flag_RC is set, we will clear cr1 after the
13095 * operation. In reality we should set cr1 to indicate the
13096 * exception status of the operation, but since we're not
13097 * simulating exceptions, the exception status will appear to be
13098 * zero. Hence cr1 should be cleared if this is a . form insn.
13100 Bool clear_CR1
= True
;
13102 assign( frA
, getDReg( frA_addr
) );
13103 assign( frB
, getDReg( frB_addr
) );
13107 DIP( "dadd%s fr%u,fr%u,fr%u\n",
13108 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13109 assign( frS
, triop( Iop_AddD64
, round
, mkexpr( frA
), mkexpr( frB
) ) );
13111 case 0x202: // dsub
13112 DIP( "dsub%s fr%u,fr%u,fr%u\n",
13113 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13114 assign( frS
, triop( Iop_SubD64
, round
, mkexpr( frA
), mkexpr( frB
) ) );
13117 DIP( "dmul%s fr%u,fr%u,fr%u\n",
13118 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13119 assign( frS
, triop( Iop_MulD64
, round
, mkexpr( frA
), mkexpr( frB
) ) );
13121 case 0x222: // ddiv
13122 DIP( "ddiv%s fr%u,fr%u,fr%u\n",
13123 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13124 assign( frS
, triop( Iop_DivD64
, round
, mkexpr( frA
), mkexpr( frB
) ) );
13128 putDReg( frS_addr
, mkexpr( frS
) );
13130 if (flag_rC
&& clear_CR1
) {
13131 putCR321( 1, mkU8( 0 ) );
13132 putCR0( 1, mkU8( 0 ) );
13138 /* Quad DFP Arithmetic instructions */
13139 static Bool
dis_dfp_arithq(UInt theInstr
)
13141 UInt opc2
= ifieldOPClo10( theInstr
);
13142 UChar frS_addr
= ifieldRegDS( theInstr
);
13143 UChar frA_addr
= ifieldRegA( theInstr
);
13144 UChar frB_addr
= ifieldRegB( theInstr
);
13145 UChar flag_rC
= ifieldBIT0( theInstr
);
13147 IRTemp frA
= newTemp( Ity_D128
);
13148 IRTemp frB
= newTemp( Ity_D128
);
13149 IRTemp frS
= newTemp( Ity_D128
);
13150 IRExpr
* round
= get_IR_roundingmode_DFP();
13152 /* By default, if flag_RC is set, we will clear cr1 after the
13153 * operation. In reality we should set cr1 to indicate the
13154 * exception status of the operation, but since we're not
13155 * simulating exceptions, the exception status will appear to be
13156 * zero. Hence cr1 should be cleared if this is a . form insn.
13158 Bool clear_CR1
= True
;
13160 assign( frA
, getDReg_pair( frA_addr
) );
13161 assign( frB
, getDReg_pair( frB_addr
) );
13165 DIP( "daddq%s fr%u,fr%u,fr%u\n",
13166 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13167 assign( frS
, triop( Iop_AddD128
, round
, mkexpr( frA
), mkexpr( frB
) ) );
13169 case 0x202: // dsubq
13170 DIP( "dsubq%s fr%u,fr%u,fr%u\n",
13171 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13172 assign( frS
, triop( Iop_SubD128
, round
, mkexpr( frA
), mkexpr( frB
) ) );
13174 case 0x22: // dmulq
13175 DIP( "dmulq%s fr%u,fr%u,fr%u\n",
13176 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13177 assign( frS
, triop( Iop_MulD128
, round
, mkexpr( frA
), mkexpr( frB
) ) );
13179 case 0x222: // ddivq
13180 DIP( "ddivq%s fr%u,fr%u,fr%u\n",
13181 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13182 assign( frS
, triop( Iop_DivD128
, round
, mkexpr( frA
), mkexpr( frB
) ) );
13186 putDReg_pair( frS_addr
, mkexpr( frS
) );
13188 if (flag_rC
&& clear_CR1
) {
13189 putCR321( 1, mkU8( 0 ) );
13190 putCR0( 1, mkU8( 0 ) );
13196 /* DFP 64-bit logical shift instructions */
13197 static Bool
dis_dfp_shift(UInt theInstr
) {
13198 UInt opc2
= ifieldOPClo9( theInstr
);
13199 UChar frS_addr
= ifieldRegDS( theInstr
);
13200 UChar frA_addr
= ifieldRegA( theInstr
);
13201 UChar shift_val
= IFIELD(theInstr
, 10, 6);
13202 UChar flag_rC
= ifieldBIT0( theInstr
);
13204 IRTemp frA
= newTemp( Ity_D64
);
13205 IRTemp frS
= newTemp( Ity_D64
);
13206 Bool clear_CR1
= True
;
13208 assign( frA
, getDReg( frA_addr
) );
13211 case 0x42: // dscli
13212 DIP( "dscli%s fr%u,fr%u,%u\n",
13213 flag_rC
? ".":"", frS_addr
, frA_addr
, shift_val
);
13214 assign( frS
, binop( Iop_ShlD64
, mkexpr( frA
), mkU8( shift_val
) ) );
13216 case 0x62: // dscri
13217 DIP( "dscri%s fr%u,fr%u,%u\n",
13218 flag_rC
? ".":"", frS_addr
, frA_addr
, shift_val
);
13219 assign( frS
, binop( Iop_ShrD64
, mkexpr( frA
), mkU8( shift_val
) ) );
13223 putDReg( frS_addr
, mkexpr( frS
) );
13225 if (flag_rC
&& clear_CR1
) {
13226 putCR321( 1, mkU8( 0 ) );
13227 putCR0( 1, mkU8( 0 ) );
13233 /* Quad DFP logical shift instructions */
13234 static Bool
dis_dfp_shiftq(UInt theInstr
) {
13235 UInt opc2
= ifieldOPClo9( theInstr
);
13236 UChar frS_addr
= ifieldRegDS( theInstr
);
13237 UChar frA_addr
= ifieldRegA( theInstr
);
13238 UChar shift_val
= IFIELD(theInstr
, 10, 6);
13239 UChar flag_rC
= ifieldBIT0( theInstr
);
13241 IRTemp frA
= newTemp( Ity_D128
);
13242 IRTemp frS
= newTemp( Ity_D128
);
13243 Bool clear_CR1
= True
;
13245 assign( frA
, getDReg_pair( frA_addr
) );
13248 case 0x42: // dscliq
13249 DIP( "dscliq%s fr%u,fr%u,%u\n",
13250 flag_rC
? ".":"", frS_addr
, frA_addr
, shift_val
);
13251 assign( frS
, binop( Iop_ShlD128
, mkexpr( frA
), mkU8( shift_val
) ) );
13253 case 0x62: // dscriq
13254 DIP( "dscriq%s fr%u,fr%u,%u\n",
13255 flag_rC
? ".":"", frS_addr
, frA_addr
, shift_val
);
13256 assign( frS
, binop( Iop_ShrD128
, mkexpr( frA
), mkU8( shift_val
) ) );
13260 putDReg_pair( frS_addr
, mkexpr( frS
) );
13262 if (flag_rC
&& clear_CR1
) {
13263 putCR321( 1, mkU8( 0 ) );
13264 putCR0( 1, mkU8( 0 ) );
13270 /* DFP 64-bit format conversion instructions */
13271 static Bool
dis_dfp_fmt_conv(UInt theInstr
) {
13272 UInt opc2
= ifieldOPClo10( theInstr
);
13273 UChar frS_addr
= ifieldRegDS( theInstr
);
13274 UChar frB_addr
= ifieldRegB( theInstr
);
13275 IRExpr
* round
= get_IR_roundingmode_DFP();
13276 UChar flag_rC
= ifieldBIT0( theInstr
);
13279 Bool clear_CR1
= True
;
13282 case 0x102: //dctdp
13283 DIP( "dctdp%s fr%u,fr%u\n",
13284 flag_rC
? ".":"", frS_addr
, frB_addr
);
13286 frB
= newTemp( Ity_D32
);
13287 frS
= newTemp( Ity_D64
);
13288 assign( frB
, getDReg32( frB_addr
) );
13289 assign( frS
, unop( Iop_D32toD64
, mkexpr( frB
) ) );
13290 putDReg( frS_addr
, mkexpr( frS
) );
13292 case 0x302: // drsp
13293 DIP( "drsp%s fr%u,fr%u\n",
13294 flag_rC
? ".":"", frS_addr
, frB_addr
);
13295 frB
= newTemp( Ity_D64
);
13296 frS
= newTemp( Ity_D32
);
13297 assign( frB
, getDReg( frB_addr
) );
13298 assign( frS
, binop( Iop_D64toD32
, round
, mkexpr( frB
) ) );
13299 putDReg32( frS_addr
, mkexpr( frS
) );
13301 case 0x122: // dctfix
13303 IRTemp tmp
= newTemp( Ity_I64
);
13305 DIP( "dctfix%s fr%u,fr%u\n",
13306 flag_rC
? ".":"", frS_addr
, frB_addr
);
13307 frB
= newTemp( Ity_D64
);
13308 frS
= newTemp( Ity_D64
);
13309 assign( frB
, getDReg( frB_addr
) );
13310 assign( tmp
, binop( Iop_D64toI64S
, round
, mkexpr( frB
) ) );
13311 assign( frS
, unop( Iop_ReinterpI64asD64
, mkexpr( tmp
) ) );
13312 putDReg( frS_addr
, mkexpr( frS
) );
13315 case 0x322: // dcffix
13316 DIP( "dcffix%s fr%u,fr%u\n",
13317 flag_rC
? ".":"", frS_addr
, frB_addr
);
13318 frB
= newTemp( Ity_D64
);
13319 frS
= newTemp( Ity_D64
);
13320 assign( frB
, getDReg( frB_addr
) );
13321 assign( frS
, binop( Iop_I64StoD64
,
13323 unop( Iop_ReinterpD64asI64
, mkexpr( frB
) ) ) );
13324 putDReg( frS_addr
, mkexpr( frS
) );
13328 if (flag_rC
&& clear_CR1
) {
13329 putCR321( 1, mkU8( 0 ) );
13330 putCR0( 1, mkU8( 0 ) );
13336 /* Quad DFP format conversion instructions */
13337 static Bool
dis_dfp_fmt_convq(UInt theInstr
) {
13338 UInt opc2
= ifieldOPClo10( theInstr
);
13339 UChar frS_addr
= ifieldRegDS( theInstr
);
13340 UChar frB_addr
= ifieldRegB( theInstr
);
13341 IRExpr
* round
= get_IR_roundingmode_DFP();
13342 IRTemp frB64
= newTemp( Ity_D64
);
13343 IRTemp frB128
= newTemp( Ity_D128
);
13344 IRTemp frS64
= newTemp( Ity_D64
);
13345 IRTemp frS128
= newTemp( Ity_D128
);
13346 UChar flag_rC
= ifieldBIT0( theInstr
);
13347 Bool clear_CR1
= True
;
13350 case 0x102: // dctqpq
13351 DIP( "dctqpq%s fr%u,fr%u\n",
13352 flag_rC
? ".":"", frS_addr
, frB_addr
);
13353 assign( frB64
, getDReg( frB_addr
) );
13354 assign( frS128
, unop( Iop_D64toD128
, mkexpr( frB64
) ) );
13355 putDReg_pair( frS_addr
, mkexpr( frS128
) );
13357 case 0x122: // dctfixq
13359 IRTemp tmp
= newTemp( Ity_I64
);
13361 DIP( "dctfixq%s fr%u,fr%u\n",
13362 flag_rC
? ".":"", frS_addr
, frB_addr
);
13363 assign( frB128
, getDReg_pair( frB_addr
) );
13364 assign( tmp
, binop( Iop_D128toI64S
, round
, mkexpr( frB128
) ) );
13365 assign( frS64
, unop( Iop_ReinterpI64asD64
, mkexpr( tmp
) ) );
13366 putDReg( frS_addr
, mkexpr( frS64
) );
13369 case 0x302: //drdpq
13370 DIP( "drdpq%s fr%u,fr%u\n",
13371 flag_rC
? ".":"", frS_addr
, frB_addr
);
13372 assign( frB128
, getDReg_pair( frB_addr
) );
13373 assign( frS64
, binop( Iop_D128toD64
, round
, mkexpr( frB128
) ) );
13374 putDReg( frS_addr
, mkexpr( frS64
) );
13376 case 0x322: // dcffixq
13378 /* Have to introduce an IOP for this instruction so it will work
13379 * on POWER 6 because emulating the instruction requires a POWER 7
13380 * DFP instruction in the emulation code.
13382 DIP( "dcffixq%s fr%u,fr%u\n",
13383 flag_rC
? ".":"", frS_addr
, frB_addr
);
13384 assign( frB64
, getDReg( frB_addr
) );
13385 assign( frS128
, unop( Iop_I64StoD128
,
13386 unop( Iop_ReinterpD64asI64
,
13387 mkexpr( frB64
) ) ) );
13388 putDReg_pair( frS_addr
, mkexpr( frS128
) );
13393 if (flag_rC
&& clear_CR1
) {
13394 putCR321( 1, mkU8( 0 ) );
13395 putCR0( 1, mkU8( 0 ) );
13401 static Bool
dis_dfp_round( UInt theInstr
) {
13402 UChar frS_addr
= ifieldRegDS(theInstr
);
13403 UChar R
= IFIELD(theInstr
, 16, 1);
13404 UChar RMC
= IFIELD(theInstr
, 9, 2);
13405 UChar frB_addr
= ifieldRegB( theInstr
);
13406 UChar flag_rC
= ifieldBIT0( theInstr
);
13407 IRTemp frB
= newTemp( Ity_D64
);
13408 IRTemp frS
= newTemp( Ity_D64
);
13409 UInt opc2
= ifieldOPClo8( theInstr
);
13410 Bool clear_CR1
= True
;
13413 /* drintn, is the same as drintx. The only difference is this
13414 * instruction does not generate an exception for an inexact operation.
13415 * Currently not supporting inexact exceptions.
13417 case 0x63: // drintx
13418 case 0xE3: // drintn
13419 DIP( "drintx/drintn%s fr%u,fr%u\n",
13420 flag_rC
? ".":"", frS_addr
, frB_addr
);
13422 /* NOTE, this instruction takes a DFP value and rounds to the
13423 * neares floating point integer value, i.e. fractional part
13424 * is zero. The result is a floating point number.
13426 /* pass the value of R and RMC in the same field */
13427 assign( frB
, getDReg( frB_addr
) );
13428 assign( frS
, binop( Iop_RoundD64toInt
,
13429 mkU32( ( R
<< 3 ) | RMC
),
13431 putDReg( frS_addr
, mkexpr( frS
) );
13434 vex_printf("dis_dfp_round(ppc)(opc2)\n");
13438 if (flag_rC
&& clear_CR1
) {
13439 putCR321( 1, mkU8( 0 ) );
13440 putCR0( 1, mkU8( 0 ) );
13446 static Bool
dis_dfp_roundq(UInt theInstr
) {
13447 UChar frS_addr
= ifieldRegDS( theInstr
);
13448 UChar frB_addr
= ifieldRegB( theInstr
);
13449 UChar R
= IFIELD(theInstr
, 16, 1);
13450 UChar RMC
= IFIELD(theInstr
, 9, 2);
13451 UChar flag_rC
= ifieldBIT0( theInstr
);
13452 IRTemp frB
= newTemp( Ity_D128
);
13453 IRTemp frS
= newTemp( Ity_D128
);
13454 Bool clear_CR1
= True
;
13455 UInt opc2
= ifieldOPClo8( theInstr
);
13458 /* drintnq, is the same as drintxq. The only difference is this
13459 * instruction does not generate an exception for an inexact operation.
13460 * Currently not supporting inexact exceptions.
13462 case 0x63: // drintxq
13463 case 0xE3: // drintnq
13464 DIP( "drintxq/drintnq%s fr%u,fr%u\n",
13465 flag_rC
? ".":"", frS_addr
, frB_addr
);
13467 /* pass the value of R and RMC in the same field */
13468 assign( frB
, getDReg_pair( frB_addr
) );
13469 assign( frS
, binop( Iop_RoundD128toInt
,
13470 mkU32( ( R
<< 3 ) | RMC
),
13472 putDReg_pair( frS_addr
, mkexpr( frS
) );
13475 vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
13479 if (flag_rC
&& clear_CR1
) {
13480 putCR321( 1, mkU8( 0 ) );
13481 putCR0( 1, mkU8( 0 ) );
13487 static Bool
dis_dfp_quantize_sig_rrnd(UInt theInstr
) {
13488 UInt opc2
= ifieldOPClo8( theInstr
);
13489 UChar frS_addr
= ifieldRegDS( theInstr
);
13490 UChar frA_addr
= ifieldRegA( theInstr
);
13491 UChar frB_addr
= ifieldRegB( theInstr
);
13492 UChar flag_rC
= ifieldBIT0( theInstr
);
13493 UInt TE_value
= IFIELD(theInstr
, 16, 4);
13494 UInt TE_sign
= IFIELD(theInstr
, 20, 1);
13495 UInt RMC
= IFIELD(theInstr
, 9, 2);
13496 IRTemp frA
= newTemp( Ity_D64
);
13497 IRTemp frB
= newTemp( Ity_D64
);
13498 IRTemp frS
= newTemp( Ity_D64
);
13499 Bool clear_CR1
= True
;
13501 assign( frB
, getDReg( frB_addr
) );
13504 case 0x43: // dquai
13505 DIP( "dquai%s fr%u,fr%u,fr%u\n",
13506 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13507 IRTemp TE_I64
= newTemp( Ity_I64
);
13509 /* Generate a reference DFP value frA with the desired exponent
13510 * given by TE using significand from frB. Need to add the bias
13511 * 398 to TE. TE is stored as a 2's complement number.
13513 if (TE_sign
== 1) {
13514 /* Take 2's complement of the 5-bit value and subtract from bias.
13515 * Bias is adjusted for the +1 required when taking 2's complement.
13519 binop( Iop_Sub32
, mkU32( 397 ),
13520 binop( Iop_And32
, mkU32( 0xF ),
13521 unop( Iop_Not32
, mkU32( TE_value
) )
13527 binop( Iop_Add32
, mkU32( 398 ), mkU32( TE_value
) )
13531 assign( frA
, binop( Iop_InsertExpD64
, mkexpr( TE_I64
),
13532 unop( Iop_ReinterpI64asD64
, mkU64( 1 ) ) ) );
13534 assign( frS
, triop( Iop_QuantizeD64
,
13541 DIP( "dqua%s fr%u,fr%u,fr%u\n",
13542 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13543 assign( frA
, getDReg( frA_addr
) );
13544 assign( frS
, triop( Iop_QuantizeD64
,
13549 case 0x23: // drrnd
13551 IRTemp tmp
= newTemp( Ity_I8
);
13553 DIP( "drrnd%s fr%u,fr%u,fr%u\n",
13554 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13555 assign( frA
, getDReg( frA_addr
) );
13556 /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
13557 assign( tmp
, unop( Iop_32to8
,
13559 unop( Iop_ReinterpD64asI64
,
13560 mkexpr( frA
) ) ) ) );
13561 assign( frS
, triop( Iop_SignificanceRoundD64
,
13568 vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
13571 putDReg( frS_addr
, mkexpr( frS
) );
13573 if (flag_rC
&& clear_CR1
) {
13574 putCR321( 1, mkU8( 0 ) );
13575 putCR0( 1, mkU8( 0 ) );
13581 static Bool
dis_dfp_quantize_sig_rrndq(UInt theInstr
) {
13582 UInt opc2
= ifieldOPClo8( theInstr
);
13583 UChar frS_addr
= ifieldRegDS( theInstr
);
13584 UChar frA_addr
= ifieldRegA( theInstr
);
13585 UChar frB_addr
= ifieldRegB( theInstr
);
13586 UChar flag_rC
= ifieldBIT0( theInstr
);
13587 UInt TE_value
= IFIELD(theInstr
, 16, 4);
13588 UInt TE_sign
= IFIELD(theInstr
, 20, 1);
13589 UInt RMC
= IFIELD(theInstr
, 9, 2);
13590 IRTemp frA
= newTemp( Ity_D128
);
13591 IRTemp frB
= newTemp( Ity_D128
);
13592 IRTemp frS
= newTemp( Ity_D128
);
13593 Bool clear_CR1
= True
;
13595 assign( frB
, getDReg_pair( frB_addr
) );
13598 case 0x43: // dquaiq
13599 DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
13600 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13601 IRTemp TE_I64
= newTemp( Ity_I64
);
13603 /* Generate a reference DFP value frA with the desired exponent
13604 * given by TE using significand of 1. Need to add the bias
13607 if (TE_sign
== 1) {
13608 /* Take 2's complement of the 5-bit value and subtract from bias.
13609 * Bias adjusted for the +1 required when taking 2's complement.
13613 binop( Iop_Sub32
, mkU32( 6175 ),
13614 binop( Iop_And32
, mkU32( 0xF ),
13615 unop( Iop_Not32
, mkU32( TE_value
) )
13623 mkU32( TE_value
) ) ) );
13627 binop( Iop_InsertExpD128
, mkexpr( TE_I64
),
13628 unop( Iop_D64toD128
,
13629 unop( Iop_ReinterpI64asD64
, mkU64( 1 ) ) ) ) );
13630 assign( frS
, triop( Iop_QuantizeD128
,
13636 DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
13637 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13638 assign( frA
, getDReg_pair( frA_addr
) );
13639 assign( frS
, triop( Iop_QuantizeD128
,
13644 case 0x23: // drrndq
13646 IRTemp tmp
= newTemp( Ity_I8
);
13648 DIP( "drrndq%s fr%u,fr%u,fr%u\n",
13649 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13650 assign( frA
, getDReg_pair( frA_addr
) );
13651 assign( tmp
, unop( Iop_32to8
,
13653 unop( Iop_ReinterpD64asI64
,
13654 unop( Iop_D128HItoD64
,
13655 mkexpr( frA
) ) ) ) ) );
13656 assign( frS
, triop( Iop_SignificanceRoundD128
,
13663 vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
13666 putDReg_pair( frS_addr
, mkexpr( frS
) );
13668 if (flag_rC
&& clear_CR1
) {
13669 putCR321( 1, mkU8( 0 ) );
13670 putCR0( 1, mkU8( 0 ) );
13676 static Bool
dis_dfp_extract_insert(UInt theInstr
) {
13677 UInt opc2
= ifieldOPClo10( theInstr
);
13678 UChar frS_addr
= ifieldRegDS( theInstr
);
13679 UChar frA_addr
= ifieldRegA( theInstr
);
13680 UChar frB_addr
= ifieldRegB( theInstr
);
13681 UChar flag_rC
= ifieldBIT0( theInstr
);
13682 Bool clear_CR1
= True
;
13684 IRTemp frA
= newTemp( Ity_D64
);
13685 IRTemp frB
= newTemp( Ity_D64
);
13686 IRTemp frS
= newTemp( Ity_D64
);
13687 IRTemp tmp
= newTemp( Ity_I64
);
13689 assign( frA
, getDReg( frA_addr
) );
13690 assign( frB
, getDReg( frB_addr
) );
13693 case 0x162: // dxex
13694 DIP( "dxex%s fr%u,fr%u,fr%u\n",
13695 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13696 assign( tmp
, unop( Iop_ExtractExpD64
, mkexpr( frB
) ) );
13697 assign( frS
, unop( Iop_ReinterpI64asD64
, mkexpr( tmp
) ) );
13699 case 0x362: // diex
13700 DIP( "diex%s fr%u,fr%u,fr%u\n",
13701 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13702 assign( frS
, binop( Iop_InsertExpD64
,
13703 unop( Iop_ReinterpD64asI64
,
13708 vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
13712 putDReg( frS_addr
, mkexpr( frS
) );
13714 if (flag_rC
&& clear_CR1
) {
13715 putCR321( 1, mkU8( 0 ) );
13716 putCR0( 1, mkU8( 0 ) );
13722 static Bool
dis_dfp_extract_insertq(UInt theInstr
) {
13723 UInt opc2
= ifieldOPClo10( theInstr
);
13724 UChar frS_addr
= ifieldRegDS( theInstr
);
13725 UChar frA_addr
= ifieldRegA( theInstr
);
13726 UChar frB_addr
= ifieldRegB( theInstr
);
13727 UChar flag_rC
= ifieldBIT0( theInstr
);
13729 IRTemp frA
= newTemp( Ity_D64
);
13730 IRTemp frB
= newTemp( Ity_D128
);
13731 IRTemp frS64
= newTemp( Ity_D64
);
13732 IRTemp frS
= newTemp( Ity_D128
);
13733 IRTemp tmp
= newTemp( Ity_I64
);
13734 Bool clear_CR1
= True
;
13736 assign( frB
, getDReg_pair( frB_addr
) );
13739 case 0x162: // dxexq
13740 DIP( "dxexq%s fr%u,fr%u\n",
13741 flag_rC
? ".":"", frS_addr
, frB_addr
);
13742 /* Instruction actually returns a 64-bit result. So as to be
13743 * consistent and not have to add a new struct, the emulation returns
13744 * the 64-bit result in the upper and lower register.
13746 assign( tmp
, unop( Iop_ExtractExpD128
, mkexpr( frB
) ) );
13747 assign( frS64
, unop( Iop_ReinterpI64asD64
, mkexpr( tmp
) ) );
13748 putDReg( frS_addr
, mkexpr( frS64
) );
13750 case 0x362: // diexq
13751 DIP( "diexq%s fr%u,fr%u,fr%u\n",
13752 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
13753 assign( frA
, getDReg( frA_addr
) );
13754 assign( frS
, binop( Iop_InsertExpD128
,
13755 unop( Iop_ReinterpD64asI64
, mkexpr( frA
) ),
13757 putDReg_pair( frS_addr
, mkexpr( frS
) );
13760 vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
13764 if (flag_rC
&& clear_CR1
) {
13765 putCR321( 1, mkU8( 0 ) );
13766 putCR0( 1, mkU8( 0 ) );
13772 /* DFP 64-bit comparison instructions */
13773 static Bool
dis_dfp_compare(UInt theInstr
) {
13775 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) ); // AKA BF
13776 UChar frA_addr
= ifieldRegA( theInstr
);
13777 UChar frB_addr
= ifieldRegB( theInstr
);
13778 UInt opc1
= ifieldOPC( theInstr
);
13782 IRTemp ccIR
= newTemp( Ity_I32
);
13783 IRTemp ccPPC32
= newTemp( Ity_I32
);
13786 /* Note: Differences between dcmpu and dcmpo are only in exception
13787 flag settings, which aren't supported anyway. */
13789 case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
13790 DIP( "dcmpo %u,fr%u,fr%u\n", crfD
, frA_addr
, frB_addr
);
13791 frA
= newTemp( Ity_D64
);
13792 frB
= newTemp( Ity_D64
);
13794 assign( frA
, getDReg( frA_addr
) );
13795 assign( frB
, getDReg( frB_addr
) );
13797 assign( ccIR
, binop( Iop_CmpD64
, mkexpr( frA
), mkexpr( frB
) ) );
13799 case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
13800 DIP( "dcmpoq %u,fr%u,fr%u\n", crfD
, frA_addr
, frB_addr
);
13801 frA
= newTemp( Ity_D128
);
13802 frB
= newTemp( Ity_D128
);
13804 assign( frA
, getDReg_pair( frA_addr
) );
13805 assign( frB
, getDReg_pair( frB_addr
) );
13806 assign( ccIR
, binop( Iop_CmpD128
, mkexpr( frA
), mkexpr( frB
) ) );
13809 vex_printf("dis_dfp_compare(ppc)(opc2)\n");
13813 /* Map compare result from IR to PPC32 */
13815 FP cmp result | PPC | IR
13816 --------------------------
13840 mkU32( 1 ) ) ) ) ) );
13842 putGST_field( PPC_GST_CR
, mkexpr( ccPPC32
), crfD
);
13843 putFPCC( mkexpr( ccPPC32
) );
13847 /* Test class/group/exponent/significance instructions. */
13848 static Bool
dis_dfp_exponent_test ( UInt theInstr
)
13850 UChar frA_addr
= ifieldRegA( theInstr
);
13851 UChar frB_addr
= ifieldRegB( theInstr
);
13852 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
13853 IRTemp frA
= newTemp( Ity_D64
);
13854 IRTemp frB
= newTemp( Ity_D64
);
13855 IRTemp frA128
= newTemp( Ity_D128
);
13856 IRTemp frB128
= newTemp( Ity_D128
);
13857 UInt opc1
= ifieldOPC( theInstr
);
13858 IRTemp gfield_A
= newTemp( Ity_I32
);
13859 IRTemp gfield_B
= newTemp( Ity_I32
);
13860 IRTemp gfield_mask
= newTemp( Ity_I32
);
13861 IRTemp exponent_A
= newTemp( Ity_I32
);
13862 IRTemp exponent_B
= newTemp( Ity_I32
);
13863 IRTemp A_NaN_true
= newTemp( Ity_I32
);
13864 IRTemp B_NaN_true
= newTemp( Ity_I32
);
13865 IRTemp A_inf_true
= newTemp( Ity_I32
);
13866 IRTemp B_inf_true
= newTemp( Ity_I32
);
13867 IRTemp A_equals_B
= newTemp( Ity_I32
);
13868 IRTemp finite_number
= newTemp( Ity_I32
);
13869 IRTemp cc0
= newTemp( Ity_I32
);
13870 IRTemp cc1
= newTemp( Ity_I32
);
13871 IRTemp cc2
= newTemp( Ity_I32
);
13872 IRTemp cc3
= newTemp( Ity_I32
);
13873 IRTemp cc
= newTemp( Ity_I32
);
13875 /* The dtstex and dtstexg instructions only differ in the size of the
13876 * exponent field. The following switch statement takes care of the size
13877 * specific setup. Once the value of the exponents, the G-field shift
13878 * and mask is setup the remaining code is identical.
13881 case 0x3b: // dtstex Extended instruction setup
13882 DIP("dtstex %u,r%u,r%d\n", crfD
, frA_addr
, frB_addr
);
13883 assign( frA
, getDReg( frA_addr
) );
13884 assign( frB
, getDReg( frB_addr
) );
13885 assign( gfield_mask
, mkU32( DFP_G_FIELD_LONG_MASK
) );
13886 assign(exponent_A
, unop( Iop_64to32
,
13887 unop( Iop_ExtractExpD64
,
13888 mkexpr( frA
) ) ) );
13889 assign(exponent_B
, unop( Iop_64to32
,
13890 unop( Iop_ExtractExpD64
,
13891 mkexpr( frB
) ) ) );
13894 case 0x3F: // dtstexq Quad instruction setup
13895 DIP("dtstexq %u,r%u,r%d\n", crfD
, frA_addr
, frB_addr
);
13896 assign( frA128
, getDReg_pair( frA_addr
) );
13897 assign( frB128
, getDReg_pair( frB_addr
) );
13898 assign( frA
, unop( Iop_D128HItoD64
, mkexpr( frA128
) ) );
13899 assign( frB
, unop( Iop_D128HItoD64
, mkexpr( frB128
) ) );
13900 assign( gfield_mask
, mkU32( DFP_G_FIELD_EXTND_MASK
) );
13901 assign( exponent_A
, unop( Iop_64to32
,
13902 unop( Iop_ExtractExpD128
,
13903 mkexpr( frA128
) ) ) );
13904 assign( exponent_B
, unop( Iop_64to32
,
13905 unop( Iop_ExtractExpD128
,
13906 mkexpr( frB128
) ) ) );
13909 vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
13913 /* Extract the Gfield */
13914 assign( gfield_A
, binop( Iop_And32
,
13915 mkexpr( gfield_mask
),
13916 unop( Iop_64HIto32
,
13917 unop( Iop_ReinterpD64asI64
,
13918 mkexpr(frA
) ) ) ) );
13920 assign( gfield_B
, binop( Iop_And32
,
13921 mkexpr( gfield_mask
),
13922 unop( Iop_64HIto32
,
13923 unop( Iop_ReinterpD64asI64
,
13924 mkexpr(frB
) ) ) ) );
13926 /* check for NAN */
13927 assign( A_NaN_true
, binop(Iop_Or32
,
13929 binop( Iop_CmpEQ32
,
13930 mkexpr( gfield_A
),
13931 mkU32( 0x7C000000 ) ) ),
13933 binop( Iop_CmpEQ32
,
13934 mkexpr( gfield_A
),
13935 mkU32( 0x7E000000 ) )
13937 assign( B_NaN_true
, binop(Iop_Or32
,
13939 binop( Iop_CmpEQ32
,
13940 mkexpr( gfield_B
),
13941 mkU32( 0x7C000000 ) ) ),
13943 binop( Iop_CmpEQ32
,
13944 mkexpr( gfield_B
),
13945 mkU32( 0x7E000000 ) )
13948 /* check for infinity */
13949 assign( A_inf_true
,
13951 binop( Iop_CmpEQ32
,
13952 mkexpr( gfield_A
),
13953 mkU32( 0x78000000 ) ) ) );
13955 assign( B_inf_true
,
13957 binop( Iop_CmpEQ32
,
13958 mkexpr( gfield_B
),
13959 mkU32( 0x78000000 ) ) ) );
13961 assign( finite_number
,
13965 mkexpr( A_NaN_true
),
13966 mkexpr( B_NaN_true
) ),
13968 mkexpr( A_inf_true
),
13969 mkexpr( B_inf_true
) ) ) ) );
13971 /* Calculate the condition code bits
13972 * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
13973 * regardless of the value of the comparisons and cc3 is 1. Otherwise,
13974 * cc0, cc1 and cc0 reflect the results of the comparisons.
13976 assign( A_equals_B
,
13979 binop( Iop_CmpEQ32
,
13980 mkexpr( exponent_A
),
13981 mkexpr( exponent_B
) ) ),
13984 mkexpr( A_inf_true
),
13985 mkexpr( B_inf_true
) ),
13987 mkexpr( A_NaN_true
),
13988 mkexpr( B_NaN_true
) ) ) ) );
13990 assign( cc0
, binop( Iop_And32
,
13991 mkexpr( finite_number
),
13994 binop( Iop_CmpLT32U
,
13995 mkexpr( exponent_A
),
13996 mkexpr( exponent_B
) ) ),
13999 assign( cc1
, binop( Iop_And32
,
14000 mkexpr( finite_number
),
14003 binop( Iop_CmpLT32U
,
14004 mkexpr( exponent_B
),
14005 mkexpr( exponent_A
) ) ),
14008 assign( cc2
, binop( Iop_Shl32
,
14010 mkexpr( A_equals_B
),
14014 assign( cc3
, binop( Iop_And32
,
14015 unop( Iop_Not32
, mkexpr( A_equals_B
) ),
14020 mkexpr ( A_inf_true
),
14021 mkexpr ( B_inf_true
) ),
14023 mkexpr ( A_NaN_true
),
14024 mkexpr ( B_NaN_true
) ) )
14027 /* store the condition code */
14028 assign( cc
, binop( Iop_Or32
,
14034 mkexpr( cc3
) ) ) ) );
14035 putGST_field( PPC_GST_CR
, mkexpr( cc
), crfD
);
14036 putFPCC( mkexpr( cc
) );
14040 /* Test class/group/exponent/significance instructions. */
14041 static Bool
dis_dfp_class_test ( UInt theInstr
)
14043 UChar frA_addr
= ifieldRegA( theInstr
);
14044 IRTemp frA
= newTemp( Ity_D64
);
14045 IRTemp abs_frA
= newTemp( Ity_D64
);
14046 IRTemp frAI64_hi
= newTemp( Ity_I64
);
14047 IRTemp frAI64_lo
= newTemp( Ity_I64
);
14048 UInt opc1
= ifieldOPC( theInstr
);
14049 UInt opc2
= ifieldOPClo9( theInstr
);
14050 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) ); // AKA BF
14051 UInt DCM
= IFIELD( theInstr
, 10, 6 );
14052 IRTemp DCM_calc
= newTemp( Ity_I32
);
14055 IRTemp min_subnormalD64
= newTemp( Ity_D64
);
14056 IRTemp min_subnormalD128
= newTemp( Ity_D128
);
14057 IRTemp significand64
= newTemp( Ity_D64
);
14058 IRTemp significand128
= newTemp( Ity_D128
);
14059 IRTemp exp_min_normal
= newTemp( Ity_I64
);
14060 IRTemp exponent
= newTemp( Ity_I32
);
14062 IRTemp infinity_true
= newTemp( Ity_I32
);
14063 IRTemp SNaN_true
= newTemp( Ity_I32
);
14064 IRTemp QNaN_true
= newTemp( Ity_I32
);
14065 IRTemp subnormal_true
= newTemp( Ity_I32
);
14066 IRTemp normal_true
= newTemp( Ity_I32
);
14067 IRTemp extreme_true
= newTemp( Ity_I32
);
14068 IRTemp lmd
= newTemp( Ity_I32
);
14069 IRTemp lmd_zero_true
= newTemp( Ity_I32
);
14070 IRTemp zero_true
= newTemp( Ity_I32
);
14071 IRTemp sign
= newTemp( Ity_I32
);
14072 IRTemp field
= newTemp( Ity_I32
);
14073 IRTemp ccIR_zero
= newTemp( Ity_I32
);
14074 IRTemp ccIR_subnormal
= newTemp( Ity_I32
);
14076 /* UInt size = DFP_LONG; JRS:unused */
14077 IRTemp gfield
= newTemp( Ity_I32
);
14078 IRTemp gfield_0_4_shift
= newTemp( Ity_I8
);
14079 IRTemp gfield_mask
= newTemp( Ity_I32
);
14080 IRTemp dcm0
= newTemp( Ity_I32
);
14081 IRTemp dcm1
= newTemp( Ity_I32
);
14082 IRTemp dcm2
= newTemp( Ity_I32
);
14083 IRTemp dcm3
= newTemp( Ity_I32
);
14084 IRTemp dcm4
= newTemp( Ity_I32
);
14085 IRTemp dcm5
= newTemp( Ity_I32
);
14087 /* The only difference between the dtstdc and dtstdcq instructions is
14088 * size of the T and G fields. The calculation of the 4 bit field
14089 * is the same. Setup the parameters and values that are DFP size
14090 * specific. The rest of the code is independent of the DFP size.
14092 * The Io_CmpD64 is used below. The instruction sets the ccIR values.
14093 * The interpretation of the ccIR values is as follows:
14095 * DFP cmp result | IR
14096 * --------------------------
14103 assign( frA
, getDReg( frA_addr
) );
14104 assign( frAI64_hi
, unop( Iop_ReinterpD64asI64
, mkexpr( frA
) ) );
14106 assign( abs_frA
, unop( Iop_ReinterpI64asD64
,
14108 unop( Iop_ReinterpD64asI64
,
14110 mkU64( 0x7FFFFFFFFFFFFFFFULL
) ) ) );
14111 assign( gfield_0_4_shift
, mkU8( 31 - 5 ) ); // G-field[0:4]
14113 case 0x3b: // dtstdc, dtstdg
14114 DIP("dtstd%s %u,r%u,%u\n", opc2
== 0xc2 ? "c" : "g",
14115 crfD
, frA_addr
, DCM
);
14116 /* setup the parameters for the long format of the two instructions */
14117 assign( frAI64_lo
, mkU64( 0 ) );
14118 assign( gfield_mask
, mkU32( DFP_G_FIELD_LONG_MASK
) );
14119 max_exp
= DFP_LONG_EXP_MAX
;
14120 min_exp
= DFP_LONG_EXP_MIN
;
14122 assign( exponent
, unop( Iop_64to32
,
14123 unop( Iop_ExtractExpD64
,
14124 mkexpr( frA
) ) ) );
14125 assign( significand64
,
14126 unop( Iop_ReinterpI64asD64
,
14127 mkU64( 0x2234000000000001ULL
) ) ); // dfp 1.0
14128 assign( exp_min_normal
,mkU64( 398 - 383 ) );
14129 assign( min_subnormalD64
,
14130 binop( Iop_InsertExpD64
,
14131 mkexpr( exp_min_normal
),
14132 mkexpr( significand64
) ) );
14134 assign( ccIR_subnormal
,
14137 mkexpr( min_subnormalD64
) ) );
14139 /* compare absolute value of frA with zero */
14143 unop( Iop_ReinterpI64asD64
,
14144 mkU64( 0x2238000000000000ULL
) ) ) );
14146 /* size = DFP_LONG; JRS: unused */
14149 case 0x3F: // dtstdcq, dtstdgq
14150 DIP("dtstd%sq %u,r%u,%u\n", opc2
== 0xc2 ? "c" : "g",
14151 crfD
, frA_addr
, DCM
);
14152 /* setup the parameters for the extended format of the
14155 assign( frAI64_lo
, unop( Iop_ReinterpD64asI64
,
14156 getDReg( frA_addr
+1 ) ) );
14158 assign( gfield_mask
, mkU32( DFP_G_FIELD_EXTND_MASK
) );
14159 max_exp
= DFP_EXTND_EXP_MAX
;
14160 min_exp
= DFP_EXTND_EXP_MIN
;
14161 assign( exponent
, unop( Iop_64to32
,
14162 unop( Iop_ExtractExpD128
,
14163 getDReg_pair( frA_addr
) ) ) );
14165 /* create quand exponent for minimum normal number */
14166 assign( exp_min_normal
, mkU64( 6176 - 6143 ) );
14167 assign( significand128
,
14168 unop( Iop_D64toD128
,
14169 unop( Iop_ReinterpI64asD64
,
14170 mkU64( 0x2234000000000001ULL
) ) ) ); // dfp 1.0
14172 assign( min_subnormalD128
,
14173 binop( Iop_InsertExpD128
,
14174 mkexpr( exp_min_normal
),
14175 mkexpr( significand128
) ) );
14177 assign( ccIR_subnormal
,
14178 binop( Iop_CmpD128
,
14179 binop( Iop_D64HLtoD128
,
14180 unop( Iop_ReinterpI64asD64
,
14182 unop( Iop_ReinterpD64asI64
,
14184 mkU64( 0x7FFFFFFFFFFFFFFFULL
) ) ),
14185 getDReg( frA_addr
+1 ) ),
14186 mkexpr( min_subnormalD128
) ) );
14188 binop( Iop_CmpD128
,
14189 binop( Iop_D64HLtoD128
,
14191 getDReg( frA_addr
+1 ) ),
14192 unop( Iop_D64toD128
,
14193 unop( Iop_ReinterpI64asD64
,
14194 mkU64( 0x0ULL
) ) ) ) );
14196 /* size = DFP_EXTND; JRS:unused */
14199 vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
14203 /* The G-field is in the upper 32-bits. The I64 logical operations
14204 * do not seem to be supported in 32-bit mode so keep things as 32-bit
14207 assign( gfield
, binop( Iop_And32
,
14208 mkexpr( gfield_mask
),
14209 unop( Iop_64HIto32
,
14210 mkexpr(frAI64_hi
) ) ) );
14212 /* There is a lot of code that is the same to do the class and group
14213 * instructions. Later there is an if statement to handle the specific
14216 * Will be using I32 values, compares, shifts and logical operations for
14217 * this code as the 64-bit compare, shifts, logical operations are not
14218 * supported in 32-bit mode.
14221 /* Check the bits for Infinity, QNaN or Signaling NaN */
14222 assign( infinity_true
,
14224 binop( Iop_CmpEQ32
,
14226 mkU32( 0x7C000000 ),
14227 mkexpr( gfield
) ),
14228 mkU32( 0x78000000 ) ) ) );
14232 binop( Iop_CmpEQ32
,
14234 mkU32( 0x7E000000 ),
14235 mkexpr( gfield
) ),
14236 mkU32( 0x7E000000 ) ) ) );
14241 binop( Iop_CmpEQ32
,
14243 mkU32( 0x7E000000 ),
14244 mkexpr( gfield
) ),
14245 mkU32( 0x7C000000 ) ) ),
14247 mkexpr( SNaN_true
) ) ) );
14252 binop( Iop_CmpEQ32
,
14253 mkexpr( ccIR_zero
),
14254 mkU32( 0x40 ) ) ), // ccIR code for Equal
14257 mkexpr( infinity_true
),
14259 mkexpr( QNaN_true
),
14260 mkexpr( SNaN_true
) ) ) ) ) );
14262 /* Do compare of frA the minimum normal value. Comparison is size
14263 * depenent and was done above to get the ccIR value.
14265 assign( subnormal_true
,
14269 binop( Iop_CmpEQ32
,
14270 mkexpr( ccIR_subnormal
),
14271 mkU32( 0x40 ) ) ), // ccIR code for Equal
14273 binop( Iop_CmpEQ32
,
14274 mkexpr( ccIR_subnormal
),
14275 mkU32( 0x1 ) ) ) ), // ccIR code for LT
14279 mkexpr( infinity_true
),
14280 mkexpr( zero_true
) ),
14282 mkexpr( QNaN_true
),
14283 mkexpr( SNaN_true
) ) ) ) ) );
14285 /* Normal number is not subnormal, infinity, NaN or Zero */
14286 assign( normal_true
,
14290 mkexpr( infinity_true
),
14291 mkexpr( zero_true
) ),
14293 mkexpr( subnormal_true
),
14295 mkexpr( QNaN_true
),
14296 mkexpr( SNaN_true
) ) ) ) ) );
14298 /* Calculate the DCM bit field based on the tests for the specific
14301 if (opc2
== 0xC2) { // dtstdc, dtstdcq
14302 /* DCM[0:5] Bit Data Class definition
14311 assign( dcm0
, binop( Iop_Shl32
,
14312 mkexpr( zero_true
),
14314 assign( dcm1
, binop( Iop_Shl32
,
14316 mkexpr( subnormal_true
),
14319 assign( dcm2
, binop( Iop_Shl32
,
14321 mkexpr( normal_true
),
14324 assign( dcm3
, binop( Iop_Shl32
,
14326 mkexpr( infinity_true
),
14329 assign( dcm4
, binop( Iop_Shl32
,
14331 mkexpr( QNaN_true
),
14334 assign( dcm5
, binop( Iop_And32
, mkexpr( SNaN_true
), mkU32( 1 ) ) );
14336 } else if (opc2
== 0xE2) { // dtstdg, dtstdgq
14337 /* check if the exponent is extreme */
14338 assign( extreme_true
, binop( Iop_Or32
,
14340 binop( Iop_CmpEQ32
,
14341 mkexpr( exponent
),
14342 mkU32( max_exp
) ) ),
14344 binop( Iop_CmpEQ32
,
14345 mkexpr( exponent
),
14346 mkU32( min_exp
) ) ) ) );
14348 /* Check if LMD is zero */
14349 Get_lmd( &lmd
, binop( Iop_Shr32
,
14350 mkexpr( gfield
), mkU8( 31 - 5 ) ) );
14352 assign( lmd_zero_true
, unop( Iop_1Sto32
,
14353 binop( Iop_CmpEQ32
,
14357 /* DCM[0:5] Bit Data Class definition
14358 * 0 Zero with non-extreme exponent
14359 * 1 Zero with extreme exponent
14360 * 2 Subnormal or (Normal with extreme exponent)
14361 * 3 Normal with non-extreme exponent and
14362 * leftmost zero digit in significand
14363 * 4 Normal with non-extreme exponent and
14364 * leftmost nonzero digit in significand
14365 * 5 Special symbol (Infinity, QNaN, or SNaN)
14367 assign( dcm0
, binop( Iop_Shl32
,
14371 mkexpr( extreme_true
) ),
14372 mkexpr( zero_true
) ),
14376 assign( dcm1
, binop( Iop_Shl32
,
14379 mkexpr( extreme_true
),
14380 mkexpr( zero_true
) ),
14384 assign( dcm2
, binop( Iop_Shl32
,
14388 mkexpr( extreme_true
),
14389 mkexpr( normal_true
) ),
14390 mkexpr( subnormal_true
) ),
14394 assign( dcm3
, binop( Iop_Shl32
,
14399 mkexpr( extreme_true
) ),
14400 mkexpr( normal_true
) ),
14402 binop( Iop_CmpEQ32
,
14408 assign( dcm4
, binop( Iop_Shl32
,
14413 mkexpr( extreme_true
) ),
14414 mkexpr( normal_true
) ),
14416 binop( Iop_CmpNE32
,
14422 assign( dcm5
, binop( Iop_And32
,
14424 mkexpr( SNaN_true
),
14426 mkexpr( QNaN_true
),
14427 mkexpr( infinity_true
) ) ),
14431 /* create DCM field */
14443 mkexpr( dcm5
) ) ) ) ) ) );
14445 /* Get the sign of the DFP number, ignore sign for QNaN */
14448 binop( Iop_CmpEQ32
,
14450 unop( Iop_64HIto32
, mkexpr( frAI64_hi
) ),
14454 /* This instruction generates a four bit field to be stored in the
14455 * condition code register. The condition code register consists of 7
14456 * fields. The field to be written to is specified by the BF (AKA crfD)
14459 * The field layout is as follows:
14462 * 0000 Operand positive with no match
14463 * 0100 Operand positive with at least one match
14464 * 0001 Operand negative with no match
14465 * 0101 Operand negative with at least one match
14467 assign( field
, binop( Iop_Or32
,
14473 binop( Iop_CmpNE32
,
14476 mkexpr( DCM_calc
) ),
14480 putGST_field( PPC_GST_CR
, mkexpr( field
), crfD
);
14481 putFPCC( mkexpr( field
) );
14485 static Bool
dis_dfp_bcd(UInt theInstr
) {
14486 UInt opc2
= ifieldOPClo10( theInstr
);
14487 ULong sp
= IFIELD(theInstr
, 19, 2);
14488 ULong s
= IFIELD(theInstr
, 20, 1);
14489 UChar frT_addr
= ifieldRegDS( theInstr
);
14490 UChar frB_addr
= ifieldRegB( theInstr
);
14491 IRTemp frB
= newTemp( Ity_D64
);
14492 IRTemp frBI64
= newTemp( Ity_I64
);
14493 IRTemp result
= newTemp( Ity_I64
);
14494 IRTemp resultD64
= newTemp( Ity_D64
);
14495 IRTemp bcd64
= newTemp( Ity_I64
);
14496 IRTemp bcd_u
= newTemp( Ity_I32
);
14497 IRTemp bcd_l
= newTemp( Ity_I32
);
14498 IRTemp dbcd_u
= newTemp( Ity_I32
);
14499 IRTemp dbcd_l
= newTemp( Ity_I32
);
14500 IRTemp lmd
= newTemp( Ity_I32
);
14502 assign( frB
, getDReg( frB_addr
) );
14503 assign( frBI64
, unop( Iop_ReinterpD64asI64
, mkexpr( frB
) ) );
14506 case 0x142: // ddedpd DFP Decode DPD to BCD
14507 DIP( "ddedpd %llu,r%u,r%u\n", sp
, frT_addr
, frB_addr
);
14509 assign( bcd64
, unop( Iop_DPBtoBCD
, mkexpr( frBI64
) ) );
14510 assign( bcd_u
, unop( Iop_64HIto32
, mkexpr( bcd64
) ) );
14511 assign( bcd_l
, unop( Iop_64to32
, mkexpr( bcd64
) ) );
14513 if ( ( sp
== 0 ) || ( sp
== 1 ) ) {
14514 /* Unsigned BCD string */
14517 unop( Iop_64HIto32
, mkexpr( frBI64
) ),
14518 mkU8( 31 - 5 ) ) ); // G-field[0:4]
14521 binop( Iop_32HLto64
,
14523 binop( Iop_Shl32
, mkexpr( lmd
), mkU8( 28 ) ),
14525 mkexpr( bcd_l
) ) );
14528 /* Signed BCD string, the cases for sp 2 and 3 only differ in how
14529 * the positive and negative values are encoded in the least
14530 * significant bits.
14532 IRTemp sign
= newTemp( Ity_I32
);
14535 /* Positive sign = 0xC, negative sign = 0xD */
14540 unop( Iop_64HIto32
, mkexpr( frBI64
) ),
14544 } else if ( sp
== 3 ) {
14545 /* Positive sign = 0xF, negative sign = 0xD */
14546 IRTemp tmp32
= newTemp( Ity_I32
);
14548 /* Complement sign bit then OR into bit position 1 */
14552 unop( Iop_64HIto32
, mkexpr( frBI64
) ),
14556 assign( sign
, binop( Iop_Or32
, mkexpr( tmp32
), mkU32( 0xD ) ) );
14559 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
14562 /* Put sign in bottom 4 bits, move most significant 4-bits from
14566 binop( Iop_32HLto64
,
14581 putDReg( frT_addr
, unop( Iop_ReinterpI64asD64
, mkexpr( result
) ) );
14584 case 0x342: // denbcd DFP Encode BCD to DPD
14586 IRTemp valid_mask
= newTemp( Ity_I32
);
14587 IRTemp invalid_mask
= newTemp( Ity_I32
);
14588 IRTemp without_lmd
= newTemp( Ity_I64
);
14589 IRTemp tmp64
= newTemp( Ity_I64
);
14590 IRTemp dbcd64
= newTemp( Ity_I64
);
14591 IRTemp left_exp
= newTemp( Ity_I32
);
14592 IRTemp g0_4
= newTemp( Ity_I32
);
14594 DIP( "denbcd %llu,r%u,r%u\n", s
, frT_addr
, frB_addr
);
14597 /* Unsigned BCD string */
14598 assign( dbcd64
, unop( Iop_BCDtoDPB
, mkexpr(frBI64
) ) );
14599 assign( dbcd_u
, unop( Iop_64HIto32
, mkexpr( dbcd64
) ) );
14600 assign( dbcd_l
, unop( Iop_64to32
, mkexpr( dbcd64
) ) );
14605 unop( Iop_64HIto32
, mkexpr( frBI64
) ),
14606 mkU32( 0xF0000000 ) ),
14609 assign( invalid_mask
,
14610 bcd_digit_inval( unop( Iop_64HIto32
, mkexpr( frBI64
) ),
14611 unop( Iop_64to32
, mkexpr( frBI64
) ) ) );
14612 assign( valid_mask
, unop( Iop_Not32
, mkexpr( invalid_mask
) ) );
14614 assign( without_lmd
,
14615 unop( Iop_ReinterpD64asI64
,
14616 binop( Iop_InsertExpD64
,
14617 mkU64( DFP_LONG_BIAS
),
14618 unop( Iop_ReinterpI64asD64
,
14619 binop( Iop_32HLto64
,
14621 mkexpr( dbcd_l
) ) ) ) ) );
14625 unop( Iop_64HIto32
, mkexpr( without_lmd
) ),
14626 mkU32( 0x60000000 ) ),
14631 Gfield_encoding( mkexpr( left_exp
), mkexpr( lmd
) ),
14635 binop( Iop_32HLto64
,
14638 unop( Iop_64HIto32
,
14639 mkexpr( without_lmd
) ),
14640 mkU32( 0x83FFFFFF ) ),
14642 unop( Iop_64to32
, mkexpr( without_lmd
) ) ) );
14644 } else if ( s
== 1 ) {
14645 IRTemp sign
= newTemp( Ity_I32
);
14646 IRTemp sign_bit
= newTemp( Ity_I32
);
14647 IRTemp pos_sign_mask
= newTemp( Ity_I32
);
14648 IRTemp neg_sign_mask
= newTemp( Ity_I32
);
14649 IRTemp tmp
= newTemp( Ity_I64
);
14651 /* Signed BCD string, least significant 4 bits are sign bits
14652 * positive sign = 0xC, negative sign = 0xD
14654 assign( tmp
, unop( Iop_BCDtoDPB
,
14655 binop( Iop_32HLto64
,
14657 unop( Iop_64HIto32
,
14658 mkexpr( frBI64
) ),
14663 mkexpr( frBI64
) ),
14666 unop( Iop_64HIto32
,
14667 mkexpr( frBI64
) ),
14668 mkU8( 28 ) ) ) ) ) );
14670 assign( dbcd_u
, unop( Iop_64HIto32
, mkexpr( tmp
) ) );
14671 assign( dbcd_l
, unop( Iop_64to32
, mkexpr( tmp
) ) );
14673 /* Get the sign of the BCD string. */
14676 unop( Iop_64to32
, mkexpr( frBI64
) ),
14679 assign( neg_sign_mask
, Generate_neg_sign_mask( mkexpr( sign
) ) );
14680 assign( pos_sign_mask
, Generate_pos_sign_mask( mkexpr( sign
) ) );
14682 Generate_sign_bit( mkexpr( pos_sign_mask
),
14683 mkexpr( neg_sign_mask
) ) );
14685 /* Check for invalid sign and BCD digit. Don't check the bottom
14686 * four bits of bcd_l as that is the sign value.
14688 assign( invalid_mask
,
14690 bcd_digit_inval( unop( Iop_64HIto32
,
14691 mkexpr( frBI64
) ),
14694 mkexpr( frBI64
) ),
14696 mkexpr( pos_sign_mask
),
14697 mkexpr( neg_sign_mask
) ) );
14699 assign( valid_mask
, unop( Iop_Not32
, mkexpr( invalid_mask
) ) );
14701 /* Generate the result assuming the sign value was valid. */
14703 unop( Iop_ReinterpD64asI64
,
14704 binop( Iop_InsertExpD64
,
14705 mkU64( DFP_LONG_BIAS
),
14706 unop( Iop_ReinterpI64asD64
,
14707 binop( Iop_32HLto64
,
14710 mkexpr( sign_bit
) ),
14711 mkexpr( dbcd_l
) ) ) ) ) );
14714 /* Generate the value to store depending on the validity of the
14715 * sign value and the validity of the BCD digits.
14718 unop( Iop_ReinterpI64asD64
,
14719 binop( Iop_32HLto64
,
14722 mkexpr( valid_mask
),
14723 unop( Iop_64HIto32
,
14724 mkexpr( tmp64
) ) ),
14726 mkU32( 0x7C000000 ),
14727 mkexpr( invalid_mask
) ) ),
14730 mkexpr( valid_mask
),
14731 unop( Iop_64to32
, mkexpr( tmp64
) ) ),
14734 mkexpr( invalid_mask
) ) ) ) ) );
14735 putDReg( frT_addr
, mkexpr( resultD64
) );
14739 vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
14745 static Bool
dis_dfp_bcdq( UInt theInstr
)
14747 UInt opc2
= ifieldOPClo10( theInstr
);
14748 ULong sp
= IFIELD(theInstr
, 19, 2);
14749 ULong s
= IFIELD(theInstr
, 20, 1);
14750 IRTemp frB_hi
= newTemp( Ity_D64
);
14751 IRTemp frB_lo
= newTemp( Ity_D64
);
14752 IRTemp frBI64_hi
= newTemp( Ity_I64
);
14753 IRTemp frBI64_lo
= newTemp( Ity_I64
);
14754 UChar frT_addr
= ifieldRegDS( theInstr
);
14755 UChar frB_addr
= ifieldRegB( theInstr
);
14757 IRTemp lmd
= newTemp( Ity_I32
);
14758 IRTemp result_hi
= newTemp( Ity_I64
);
14759 IRTemp result_lo
= newTemp( Ity_I64
);
14761 assign( frB_hi
, getDReg( frB_addr
) );
14762 assign( frB_lo
, getDReg( frB_addr
+ 1 ) );
14763 assign( frBI64_hi
, unop( Iop_ReinterpD64asI64
, mkexpr( frB_hi
) ) );
14764 assign( frBI64_lo
, unop( Iop_ReinterpD64asI64
, mkexpr( frB_lo
) ) );
14767 case 0x142: // ddedpdq DFP Decode DPD to BCD
14769 IRTemp low_60_u
= newTemp( Ity_I32
);
14770 IRTemp low_60_l
= newTemp( Ity_I32
);
14771 IRTemp mid_60_u
= newTemp( Ity_I32
);
14772 IRTemp mid_60_l
= newTemp( Ity_I32
);
14773 IRTemp top_12_l
= newTemp( Ity_I32
);
14775 DIP( "ddedpdq %llu,r%u,r%u\n", sp
, frT_addr
, frB_addr
);
14777 /* Note, instruction only stores the lower 32 BCD digits in
14780 Generate_132_bit_bcd_string( mkexpr( frBI64_hi
),
14781 mkexpr( frBI64_lo
),
14788 if ( ( sp
== 0 ) || ( sp
== 1 ) ) {
14789 /* Unsigned BCD string */
14791 binop( Iop_32HLto64
,
14794 mkexpr( top_12_l
),
14797 mkexpr( mid_60_u
),
14801 mkexpr( mid_60_u
),
14804 mkexpr( mid_60_l
),
14808 binop( Iop_32HLto64
,
14811 mkexpr( mid_60_l
),
14813 mkexpr( low_60_u
) ),
14814 mkexpr( low_60_l
) ) );
14817 /* Signed BCD string, the cases for sp 2 and 3 only differ in how
14818 * the positive and negative values are encoded in the least
14819 * significant bits.
14821 IRTemp sign
= newTemp( Ity_I32
);
14824 /* Positive sign = 0xC, negative sign = 0xD */
14828 unop( Iop_64HIto32
, mkexpr( frBI64_hi
) ),
14832 } else if ( sp
== 3 ) {
14833 IRTemp tmp32
= newTemp( Ity_I32
);
14835 /* Positive sign = 0xF, negative sign = 0xD.
14836 * Need to complement sign bit then OR into bit position 1.
14841 unop( Iop_64HIto32
, mkexpr( frBI64_hi
) ),
14845 assign( sign
, binop( Iop_Or32
, mkexpr( tmp32
), mkU32( 0xD ) ) );
14848 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
14852 binop( Iop_32HLto64
,
14855 mkexpr( top_12_l
),
14857 mkexpr( mid_60_u
) ),
14858 mkexpr( mid_60_l
) ) );
14861 binop( Iop_32HLto64
,
14864 mkexpr( low_60_u
),
14867 mkexpr( low_60_l
),
14871 mkexpr( low_60_l
),
14873 mkexpr( sign
) ) ) );
14876 putDReg( frT_addr
, unop( Iop_ReinterpI64asD64
, mkexpr( result_hi
) ) );
14877 putDReg( frT_addr
+ 1,
14878 unop( Iop_ReinterpI64asD64
, mkexpr( result_lo
) ) );
14881 case 0x342: // denbcdq DFP Encode BCD to DPD
14883 IRTemp valid_mask
= newTemp( Ity_I32
);
14884 IRTemp invalid_mask
= newTemp( Ity_I32
);
14885 IRTemp result128
= newTemp( Ity_D128
);
14886 IRTemp dfp_significand
= newTemp( Ity_D128
);
14887 IRTemp tmp_hi
= newTemp( Ity_I64
);
14888 IRTemp tmp_lo
= newTemp( Ity_I64
);
14889 IRTemp dbcd_top_l
= newTemp( Ity_I32
);
14890 IRTemp dbcd_mid_u
= newTemp( Ity_I32
);
14891 IRTemp dbcd_mid_l
= newTemp( Ity_I32
);
14892 IRTemp dbcd_low_u
= newTemp( Ity_I32
);
14893 IRTemp dbcd_low_l
= newTemp( Ity_I32
);
14894 IRTemp bcd_top_8
= newTemp( Ity_I64
);
14895 IRTemp bcd_mid_60
= newTemp( Ity_I64
);
14896 IRTemp bcd_low_60
= newTemp( Ity_I64
);
14897 IRTemp sign_bit
= newTemp( Ity_I32
);
14898 IRTemp tmptop10
= newTemp( Ity_I64
);
14899 IRTemp tmpmid50
= newTemp( Ity_I64
);
14900 IRTemp tmplow50
= newTemp( Ity_I64
);
14901 IRTemp inval_bcd_digit_mask
= newTemp( Ity_I32
);
14903 DIP( "denbcd %llu,r%u,r%u\n", s
, frT_addr
, frB_addr
);
14906 /* Unsigned BCD string */
14907 assign( sign_bit
, mkU32( 0 ) ); // set to zero for unsigned string
14910 binop( Iop_32HLto64
,
14914 unop( Iop_64HIto32
,
14915 mkexpr( frBI64_hi
) ),
14917 mkU32( 0xFF ) ) ) );
14918 assign( bcd_mid_60
,
14919 binop( Iop_32HLto64
,
14923 mkexpr( frBI64_hi
) ),
14926 unop( Iop_64HIto32
,
14927 mkexpr( frBI64_hi
) ),
14932 mkexpr( frBI64_hi
) ),
14935 unop( Iop_64HIto32
,
14936 mkexpr( frBI64_lo
) ),
14937 mkU8( 28 ) ) ) ) );
14939 /* Note, the various helper functions ignores top 4-bits */
14940 assign( bcd_low_60
, mkexpr( frBI64_lo
) );
14942 assign( tmptop10
, unop( Iop_BCDtoDPB
, mkexpr( bcd_top_8
) ) );
14943 assign( dbcd_top_l
, unop( Iop_64to32
, mkexpr( tmptop10
) ) );
14945 assign( tmpmid50
, unop( Iop_BCDtoDPB
, mkexpr( bcd_mid_60
) ) );
14946 assign( dbcd_mid_u
, unop( Iop_64HIto32
, mkexpr( tmpmid50
) ) );
14947 assign( dbcd_mid_l
, unop( Iop_64to32
, mkexpr( tmpmid50
) ) );
14949 assign( tmplow50
, unop( Iop_BCDtoDPB
, mkexpr( bcd_low_60
) ) );
14950 assign( dbcd_low_u
, unop( Iop_64HIto32
, mkexpr( tmplow50
) ) );
14951 assign( dbcd_low_l
, unop( Iop_64to32
, mkexpr( tmplow50
) ) );
14953 /* The entire BCD string fits in lower 110-bits. The LMD = 0,
14954 * value is not part of the final result. Only the right most
14955 * BCD digits are stored.
14957 assign( lmd
, mkU32( 0 ) );
14959 assign( invalid_mask
,
14961 bcd_digit_inval( mkU32( 0 ),
14963 mkexpr( bcd_top_8
) ) ),
14965 bcd_digit_inval( unop( Iop_64HIto32
,
14966 mkexpr( bcd_mid_60
) ),
14968 mkexpr( bcd_mid_60
) ) ),
14969 bcd_digit_inval( unop( Iop_64HIto32
,
14970 mkexpr( bcd_low_60
) ),
14972 mkexpr( bcd_low_60
) )
14975 } else if ( s
== 1 ) {
14976 IRTemp sign
= newTemp( Ity_I32
);
14977 IRTemp zero
= newTemp( Ity_I32
);
14978 IRTemp pos_sign_mask
= newTemp( Ity_I32
);
14979 IRTemp neg_sign_mask
= newTemp( Ity_I32
);
14981 /* The sign of the BCD string is stored in lower 4 bits */
14984 unop( Iop_64to32
, mkexpr( frBI64_lo
) ),
14986 assign( neg_sign_mask
, Generate_neg_sign_mask( mkexpr( sign
) ) );
14987 assign( pos_sign_mask
, Generate_pos_sign_mask( mkexpr( sign
) ) );
14989 Generate_sign_bit( mkexpr( pos_sign_mask
),
14990 mkexpr( neg_sign_mask
) ) );
14992 /* Generate the value assuminig the sign and BCD digits are vaild */
14994 binop( Iop_32HLto64
,
14997 unop( Iop_64HIto32
, mkexpr( frBI64_hi
) ),
15000 /* The various helper routines ignore the upper 4-bits */
15001 assign( bcd_mid_60
, mkexpr( frBI64_hi
) );
15003 /* Remove bottom four sign bits */
15004 assign( bcd_low_60
,
15005 binop( Iop_32HLto64
,
15007 unop( Iop_64HIto32
,
15008 mkexpr( frBI64_lo
) ),
15012 unop( Iop_64HIto32
,
15013 mkexpr( frBI64_lo
) ),
15017 mkexpr( frBI64_lo
) ),
15019 assign( tmptop10
, unop( Iop_BCDtoDPB
, mkexpr(bcd_top_8
) ) );
15020 assign( dbcd_top_l
, unop( Iop_64to32
, mkexpr( tmptop10
) ) );
15022 assign( tmpmid50
, unop( Iop_BCDtoDPB
, mkexpr(bcd_mid_60
) ) );
15023 assign( dbcd_mid_u
, unop( Iop_64HIto32
, mkexpr( tmpmid50
) ) );
15024 assign( dbcd_mid_l
, unop( Iop_64to32
, mkexpr( tmpmid50
) ) );
15026 assign( tmplow50
, unop( Iop_BCDtoDPB
, mkexpr( bcd_low_60
) ) );
15027 assign( dbcd_low_u
, unop( Iop_64HIto32
, mkexpr( tmplow50
) ) );
15028 assign( dbcd_low_l
, unop( Iop_64to32
, mkexpr( tmplow50
) ) );
15030 /* The entire BCD string fits in lower 110-bits. The LMD value
15031 * is not stored in the final result for the DFP Long instruction.
15033 assign( lmd
, mkU32( 0 ) );
15035 /* Check for invalid sign and invalid BCD digit. Don't check the
15036 * bottom four bits of frBI64_lo as that is the sign value.
15038 assign( zero
, mkU32( 0 ) );
15039 assign( inval_bcd_digit_mask
,
15041 bcd_digit_inval( mkexpr( zero
),
15043 mkexpr( bcd_top_8
) ) ),
15045 bcd_digit_inval( unop( Iop_64HIto32
,
15046 mkexpr( bcd_mid_60
) ),
15048 mkexpr( bcd_mid_60
) ) ),
15049 bcd_digit_inval( unop( Iop_64HIto32
,
15050 mkexpr( frBI64_lo
) ),
15053 mkexpr( frBI64_lo
) ),
15054 mkU8( 4 ) ) ) ) ) );
15055 assign( invalid_mask
,
15056 Generate_inv_mask( mkexpr( inval_bcd_digit_mask
),
15057 mkexpr( pos_sign_mask
),
15058 mkexpr( neg_sign_mask
) ) );
15062 assign( valid_mask
, unop( Iop_Not32
, mkexpr( invalid_mask
) ) );
15064 /* Calculate the value of the result assuming sign and BCD digits
15067 assign( dfp_significand
,
15068 binop( Iop_D64HLtoD128
,
15069 unop( Iop_ReinterpI64asD64
,
15070 binop( Iop_32HLto64
,
15072 mkexpr( sign_bit
),
15073 mkexpr( dbcd_top_l
) ),
15076 mkexpr( dbcd_mid_u
),
15079 mkexpr( dbcd_mid_l
),
15080 mkU8( 14 ) ) ) ) ),
15081 unop( Iop_ReinterpI64asD64
,
15082 binop( Iop_32HLto64
,
15084 mkexpr( dbcd_low_u
),
15086 mkexpr( dbcd_mid_l
),
15088 mkexpr( dbcd_low_l
) ) ) ) );
15090 /* Break the result back down to 32-bit chunks and replace chunks.
15091 * If there was an invalid BCD digit or invalid sign value, replace
15092 * the calculated result with the invalid bit string.
15095 binop( Iop_InsertExpD128
,
15096 mkU64( DFP_EXTND_BIAS
),
15097 mkexpr( dfp_significand
) ) );
15100 unop( Iop_ReinterpD64asI64
,
15101 unop( Iop_D128HItoD64
, mkexpr( result128
) ) ) );
15104 unop( Iop_ReinterpD64asI64
,
15105 unop( Iop_D128LOtoD64
, mkexpr( result128
) ) ) );
15108 binop( Iop_32HLto64
,
15111 mkexpr( valid_mask
),
15112 unop( Iop_64HIto32
, mkexpr( tmp_hi
) ) ),
15114 mkU32( 0x7C000000 ),
15115 mkexpr( invalid_mask
) ) ),
15118 mkexpr( valid_mask
),
15119 unop( Iop_64to32
, mkexpr( tmp_hi
) ) ),
15122 mkexpr( invalid_mask
) ) ) ) );
15125 binop( Iop_32HLto64
,
15128 mkexpr( valid_mask
),
15129 unop( Iop_64HIto32
, mkexpr( tmp_lo
) ) ),
15132 mkexpr( invalid_mask
) ) ),
15135 mkexpr( valid_mask
),
15136 unop( Iop_64to32
, mkexpr( tmp_lo
) ) ),
15139 mkexpr( invalid_mask
) ) ) ) );
15141 putDReg( frT_addr
, unop( Iop_ReinterpI64asD64
, mkexpr( result_hi
) ) );
15142 putDReg( frT_addr
+ 1,
15143 unop( Iop_ReinterpI64asD64
, mkexpr( result_lo
) ) );
15148 vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
15154 static Bool
dis_dfp_significant_digits( UInt theInstr
)
15156 UInt opc1
= ifieldOPC( theInstr
);
15157 UInt opc2
= ifieldOPClo10(theInstr
);
15158 UChar frA_addr
= ifieldRegA( theInstr
);
15159 UChar frB_addr
= ifieldRegB( theInstr
);
15160 IRTemp frA
= newTemp( Ity_D64
);
15161 IRTemp B_sig
= newTemp( Ity_I8
);
15162 IRTemp K
= newTemp( Ity_I8
);
15163 IRTemp lmd_B
= newTemp( Ity_I32
);
15164 IRTemp field
= newTemp( Ity_I32
);
15165 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) ); // AKA BF
15166 IRTemp Unordered_true
= newTemp( Ity_I32
);
15167 IRTemp Eq_true_mask
= newTemp( Ity_I32
);
15168 IRTemp Lt_true_mask
= newTemp( Ity_I32
);
15169 IRTemp Gt_true_mask
= newTemp( Ity_I32
);
15170 IRTemp KisZero_true_mask
= newTemp( Ity_I32
);
15171 IRTemp KisZero_false_mask
= newTemp( Ity_I32
);
15172 IRTemp cc
= newTemp( Ity_I32
);
15173 UChar UIM
= toUChar( IFIELD( theInstr
, 16, 6 ) );
15174 IRTemp BCD_valid
= newTemp( Ity_I32
);
15176 if (opc2
== 0x2A2) { // dtstsf DFP Test Significance
15177 // dtstsfq DFP Test Significance Quad
15178 /* Get the reference singificance stored in frA */
15179 assign( frA
, getDReg( frA_addr
) );
15181 /* Convert from 64 bit to 8 bits in two steps. The Iop_64to8 is not
15182 * supported in 32-bit mode.
15184 assign( K
, unop( Iop_32to8
,
15187 unop( Iop_ReinterpD64asI64
,
15189 mkU32( 0x3F ) ) ) );
15191 } else if (opc2
== 0x2A3) { // dtstsfi DFP Test Significance Immediate
15192 // dtstsfiq DFP Test Significance Quad Immediate
15193 /* get the significane from the immediate field */
15194 assign( K
, mkU8( UIM
) );
15197 vex_printf("dis_dfp_significant_digits(ppc)(opc2) wrong\n");
15202 case 0x3b: // dtstsf DFP Test Significance
15203 // dtstsfi DFP Test Significance Immediate
15205 IRTemp frB
= newTemp( Ity_D64
);
15206 IRTemp frBI64
= newTemp( Ity_I64
);
15207 IRTemp B_bcd_u
= newTemp( Ity_I32
);
15208 IRTemp B_bcd_l
= newTemp( Ity_I32
);
15209 IRTemp tmp64
= newTemp( Ity_I64
);
15211 if (opc2
== 0x2A2) {
15212 DIP( "dtstsf %u,r%u,r%u\n", crfD
, frA_addr
, frB_addr
);
15214 DIP( "dtstsfi %u,%u,r%u\n", crfD
, UIM
, frB_addr
);
15217 assign( frB
, getDReg( frB_addr
) );
15218 assign( frBI64
, unop( Iop_ReinterpD64asI64
, mkexpr( frB
) ) );
15220 /* Get the BCD string for the value stored in a series of I32 values.
15221 * Count the number of leading zeros. Subtract the number of leading
15222 * zeros from 16 (maximum number of significant digits in DFP
15227 unop( Iop_64HIto32
, mkexpr( frBI64
) ),
15228 mkU8( 31 - 5 ) ) ); // G-field[0:4]
15230 assign( tmp64
, unop( Iop_DPBtoBCD
, mkexpr( frBI64
) ) );
15231 assign( B_bcd_u
, unop( Iop_64HIto32
, mkexpr( tmp64
) ) );
15232 assign( B_bcd_l
, unop( Iop_64to32
, mkexpr( tmp64
) ) );
15236 mkU8( DFP_LONG_MAX_SIG_DIGITS
),
15237 Count_leading_zeros_60( mkexpr( lmd_B
),
15239 mkexpr( B_bcd_l
) ) ) );
15243 bcd_digit_inval( mkexpr( B_bcd_u
), mkexpr( B_bcd_l
) ),
15244 bcd_digit_inval( mkexpr( lmd_B
), mkU32( 0 ) ) ) );
15246 /* Set unordered to True if the number is NaN, Inf or an invalid
15249 assign( Unordered_true
,
15251 Check_unordered( mkexpr( frBI64
) ),
15252 mkexpr( BCD_valid
) ) );
15255 case 0x3F: // dtstsfq DFP Test Significance
15256 // dtstsfqi DFP Test Significance Immediate
15258 IRTemp frB_hi
= newTemp( Ity_D64
);
15259 IRTemp frB_lo
= newTemp( Ity_D64
);
15260 IRTemp frBI64_hi
= newTemp( Ity_I64
);
15261 IRTemp frBI64_lo
= newTemp( Ity_I64
);
15262 IRTemp B_low_60_u
= newTemp( Ity_I32
);
15263 IRTemp B_low_60_l
= newTemp( Ity_I32
);
15264 IRTemp B_mid_60_u
= newTemp( Ity_I32
);
15265 IRTemp B_mid_60_l
= newTemp( Ity_I32
);
15266 IRTemp B_top_12_l
= newTemp( Ity_I32
);
15268 if (opc2
== 0x2A2) {
15269 DIP( "dtstsfq %u,r%u,r%u\n", crfD
, frA_addr
, frB_addr
);
15271 DIP( "dtstsfiq %u,%u,r%u\n", crfD
, UIM
, frB_addr
);
15274 assign( frB_hi
, getDReg( frB_addr
) );
15275 assign( frB_lo
, getDReg( frB_addr
+ 1 ) );
15277 assign( frBI64_hi
, unop( Iop_ReinterpD64asI64
, mkexpr( frB_hi
) ) );
15278 assign( frBI64_lo
, unop( Iop_ReinterpD64asI64
, mkexpr( frB_lo
) ) );
15280 /* Get the BCD string for the value stored in a series of I32 values.
15281 * Count the number of leading zeros. Subtract the number of leading
15282 * zeros from 32 (maximum number of significant digits in DFP
15287 unop( Iop_64HIto32
, mkexpr( frBI64_hi
) ),
15288 mkU8( 31 - 5 ) ) ); // G-field[0:4]
15290 Generate_132_bit_bcd_string( mkexpr( frBI64_hi
),
15291 mkexpr( frBI64_lo
),
15301 bcd_digit_inval( mkexpr( lmd_B
),
15302 mkexpr( B_top_12_l
) ),
15303 bcd_digit_inval( mkexpr( B_mid_60_u
),
15304 mkexpr( B_mid_60_l
) ) ),
15305 bcd_digit_inval( mkexpr( B_low_60_u
),
15306 mkexpr( B_low_60_l
) ) ) );
15310 mkU8( DFP_EXTND_MAX_SIG_DIGITS
),
15311 Count_leading_zeros_128( mkexpr( lmd_B
),
15312 mkexpr( B_top_12_l
),
15313 mkexpr( B_mid_60_u
),
15314 mkexpr( B_mid_60_l
),
15315 mkexpr( B_low_60_u
),
15316 mkexpr( B_low_60_l
) ) ) );
15318 /* Set unordered to True if the number is NaN, Inf or an invalid
15321 assign( Unordered_true
,
15323 Check_unordered( mkexpr( frBI64_hi
) ),
15324 mkexpr( BCD_valid
) ) );
15329 /* Compare (16 - cnt[0]) against K and set the condition code field
15332 * The field layout is as follows:
15334 * bit[3:0] Description
15335 * 3 K != 0 and K < Number of significant digits if FRB
15336 * 2 K != 0 and K > Number of significant digits if FRB OR K = 0
15337 * 1 K != 0 and K = Number of significant digits if FRB
15338 * 0 K ? Number of significant digits if FRB
15340 assign( Eq_true_mask
,
15342 binop( Iop_CmpEQ32
,
15343 unop( Iop_8Uto32
, mkexpr( K
) ),
15344 unop( Iop_8Uto32
, mkexpr( B_sig
) ) ) ) );
15345 assign( Lt_true_mask
,
15347 binop( Iop_CmpLT32U
,
15348 unop( Iop_8Uto32
, mkexpr( K
) ),
15349 unop( Iop_8Uto32
, mkexpr( B_sig
) ) ) ) );
15350 assign( Gt_true_mask
,
15352 binop( Iop_CmpLT32U
,
15353 unop( Iop_8Uto32
, mkexpr( B_sig
) ),
15354 unop( Iop_8Uto32
, mkexpr( K
) ) ) ) );
15356 assign( KisZero_true_mask
,
15358 binop( Iop_CmpEQ32
,
15359 unop( Iop_8Uto32
, mkexpr( K
) ),
15361 assign( KisZero_false_mask
,
15363 binop( Iop_CmpNE32
,
15364 unop( Iop_8Uto32
, mkexpr( K
) ),
15370 mkexpr( KisZero_false_mask
),
15373 mkexpr( Lt_true_mask
),
15377 mkexpr( Gt_true_mask
),
15380 mkexpr( Eq_true_mask
),
15381 mkU32( 0x2 ) ) ) ) ),
15383 mkexpr( KisZero_true_mask
),
15384 mkU32( 0x4 ) ) ) );
15386 assign( cc
, binop( Iop_Or32
,
15388 mkexpr( Unordered_true
),
15391 unop( Iop_Not32
, mkexpr( Unordered_true
) ),
15392 mkexpr( field
) ) ) );
15394 putGST_field( PPC_GST_CR
, mkexpr( cc
), crfD
);
15395 putFPCC( mkexpr( cc
) );
15399 /*------------------------------------------------------------*/
15400 /*--- AltiVec Instruction Translation ---*/
15401 /*------------------------------------------------------------*/
15404 Altivec Cache Control Instructions (Data Streams)
15406 static Bool
dis_av_datastream ( UInt theInstr
)
15409 UChar opc1
= ifieldOPC(theInstr
);
15410 UChar flag_T
= toUChar( IFIELD( theInstr
, 25, 1 ) );
15411 UChar flag_A
= flag_T
;
15412 UChar b23to24
= toUChar( IFIELD( theInstr
, 23, 2 ) );
15413 UChar STRM
= toUChar( IFIELD( theInstr
, 21, 2 ) );
15414 UChar rA_addr
= ifieldRegA(theInstr
);
15415 UChar rB_addr
= ifieldRegB(theInstr
);
15416 UInt opc2
= ifieldOPClo10(theInstr
);
15417 UChar b0
= ifieldBIT0(theInstr
);
15419 if (opc1
!= 0x1F || b23to24
!= 0 || b0
!= 0) {
15420 vex_printf("dis_av_datastream(ppc)(instr)\n");
15425 case 0x156: // dst (Data Stream Touch, AV p115)
15426 DIP("dst%s r%u,r%u,%d\n", flag_T
? "t" : "",
15427 rA_addr
, rB_addr
, STRM
);
15430 case 0x176: // dstst (Data Stream Touch for Store, AV p117)
15431 DIP("dstst%s r%u,r%u,%d\n", flag_T
? "t" : "",
15432 rA_addr
, rB_addr
, STRM
);
15435 case 0x336: // dss (Data Stream Stop, AV p114)
15436 if (rA_addr
!= 0 || rB_addr
!= 0) {
15437 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
15441 DIP("dss %d\n", STRM
);
15448 vex_printf("dis_av_datastream(ppc)(opc2)\n");
15455 AltiVec Processor Control Instructions
15457 static Bool
dis_av_procctl ( UInt theInstr
)
15460 UChar opc1
= ifieldOPC(theInstr
);
15461 UChar vD_addr
= ifieldRegDS(theInstr
);
15462 UChar vA_addr
= ifieldRegA(theInstr
);
15463 UChar vB_addr
= ifieldRegB(theInstr
);
15464 UInt opc2
= IFIELD( theInstr
, 0, 11 );
15467 vex_printf("dis_av_procctl(ppc)(instr)\n");
15472 case 0x604: // mfvscr (Move from VSCR, AV p129)
15473 if (vA_addr
!= 0 || vB_addr
!= 0) {
15474 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
15477 DIP("mfvscr v%d\n", vD_addr
);
15478 putVReg( vD_addr
, unop(Iop_32UtoV128
, getGST( PPC_GST_VSCR
)) );
15481 case 0x644: { // mtvscr (Move to VSCR, AV p130)
15482 IRTemp vB
= newTemp(Ity_V128
);
15483 if (vD_addr
!= 0 || vA_addr
!= 0) {
15484 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
15487 DIP("mtvscr v%d\n", vB_addr
);
15488 assign( vB
, getVReg(vB_addr
));
15489 putGST( PPC_GST_VSCR
, unop(Iop_V128to32
, mkexpr(vB
)) );
15493 vex_printf("dis_av_procctl(ppc)(opc2)\n");
15500 Vector Extend Sign Instructions
15502 static Bool
dis_av_extend_sign_count_zero ( UInt theInstr
, UInt allow_isa_3_0
)
15504 /* VX-Form, sort of, the A register field is used to select the specific
15505 * sign extension instruction or count leading/trailing zero LSB
15509 UChar opc1
= ifieldOPC( theInstr
);
15510 UChar rT_addr
= ifieldRegDS (theInstr
);
15511 UChar rA_addr
= ifieldRegA( theInstr
);
15512 UChar vB_addr
= ifieldRegB( theInstr
);
15513 UInt opc2
= IFIELD( theInstr
, 0, 11 );
15515 IRTemp vB
= newTemp( Ity_V128
);
15516 IRTemp vT
= newTemp( Ity_V128
);
15518 assign( vB
, getVReg ( vB_addr
) );
15520 if ( ( opc1
!= 0x4 ) && ( opc2
!= 0x602 ) ) {
15521 vex_printf("dis_av_extend_sign(ppc)(instr)\n");
15525 switch ( rA_addr
) {
15531 IRTemp bit_zero
[16];
15532 IRTemp byte_mask
[17];
15534 /* These instructions store the result in the general purpose
15535 * register in the rT_addr field.
15538 byte_mask
[0] = newTemp( Ity_I32
);
15539 count
[0] = newTemp( Ity_I32
);
15540 assign( count
[0], mkU32( 0 ) );
15541 assign( byte_mask
[0], mkU32( 0x1 ) );
15543 if ( rA_addr
== 0 ) {
15544 // vclzlsbb (Vector Count Leading Zero Least-Significant Bits Byte)
15545 DIP("vclzlsbb %d,v%d\n", rT_addr
, vB_addr
);
15548 // vctzlsbb (Vector Count Trailing Zero Least-Significant Bits Byte)
15549 DIP("vctzlsbb %d,v%d\n", rT_addr
, vB_addr
);
15552 for( i
= 0; i
< 16; i
++ ) {
15553 byte_mask
[i
+1] = newTemp( Ity_I32
);
15554 count
[i
+1] = newTemp( Ity_I32
);
15555 bit_zero
[i
] = newTemp( Ity_I1
);
15557 /* bit_zero[i] = 0x0 until the first 1 bit is found in lsb of
15558 * byte. When the first 1 bit is found it causes the byte_mask
15559 * to change from 0x1 to 0x0. Thus the AND of the lsb and byte_mask
15560 * will be zero which will be equal to the zero byte_mask causing
15561 * the value of bit_zero[i] to be equal to 0x1 for all remaining bits.
15564 if ( rA_addr
== 0 )
15565 /* leading zero bit in byte count,
15566 work bytes from left to right
15568 assign( bit_zero
[i
],
15569 binop( Iop_CmpEQ32
,
15571 unop( Iop_V128to32
,
15572 binop( Iop_ShrV128
,
15574 mkU8( ( 15 - i
) * 8 ) ) ),
15575 mkexpr( byte_mask
[i
] ) ),
15576 mkexpr( byte_mask
[i
] ) ) );
15578 else if ( rA_addr
== 1 )
15579 /* trailing zero bit in byte count,
15580 * work bytes from right to left
15582 assign( bit_zero
[i
],
15583 binop( Iop_CmpEQ32
,
15585 unop( Iop_V128to32
,
15586 binop( Iop_ShrV128
,
15589 mkexpr( byte_mask
[i
] ) ),
15590 mkexpr( byte_mask
[i
] ) ) );
15592 /* Increment count as long as bit_zero = 0 */
15593 assign( count
[i
+1], binop( Iop_Add32
,
15594 mkexpr( count
[i
] ),
15597 mkexpr( bit_zero
[i
] ) ) ) ) );
15599 /* If comparison fails to find a zero bit, set the byte_mask to zero
15600 * for all future comparisons so there will be no more matches.
15602 assign( byte_mask
[i
+1],
15606 mkexpr( bit_zero
[i
] ) ) ),
15607 mkexpr( byte_mask
[i
] ) ) );
15609 putIReg( rT_addr
, unop( Iop_32Uto64
, mkexpr( count
[16] ) ) );
15613 case 6: // vnegw, Vector Negate Word
15614 DIP("vnegw v%d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
15616 /* multiply each word by -1 */
15617 assign( vT
, binop( Iop_Mul32x4
, mkexpr( vB
), mkV128( 0xFFFF ) ) );
15620 case 7: // vnegd, Vector Negate Doubleword
15621 DIP("vnegd v%d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
15623 /* multiply each word by -1 */
15624 assign( vT
, binop( Iop_64HLtoV128
,
15626 unop( Iop_V128HIto64
,
15628 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
15630 unop( Iop_V128to64
,
15632 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) );
15635 case 8: // vprtybw, Vector Parity Byte Word
15636 case 9: // vprtybd, Vector Parity Byte Doubleword
15637 case 10: // vprtybq, Vector Parity Byte Quadword
15640 IRTemp bit_in_byte
[16];
15641 IRTemp word_parity
[4];
15643 for( i
= 0; i
< 16; i
++ ) {
15644 bit_in_byte
[i
] = newTemp( Ity_I32
);
15645 assign( bit_in_byte
[i
],
15647 unop( Iop_V128to32
,
15648 binop( Iop_ShrV128
,
15650 mkU8( ( 15 - i
) * 8 ) ) ),
15654 for( i
= 0; i
< 4; i
++ ) {
15655 word_parity
[i
] = newTemp(Ity_I32
);
15656 assign( word_parity
[i
],
15657 mkXOr4_32( bit_in_byte
[0 + i
* 4],
15658 bit_in_byte
[1 + i
* 4],
15659 bit_in_byte
[2 + i
* 4],
15660 bit_in_byte
[3 + i
* 4] ) );
15663 if ( rA_addr
== 8 ) {
15664 DIP("vprtybw v%d,v%d", rT_addr
, vB_addr
);
15666 assign( vT
, mkV128from32( word_parity
[0], word_parity
[1],
15667 word_parity
[2], word_parity
[3] ) );
15669 } else if ( rA_addr
== 9 ) {
15670 DIP("vprtybd v%d,v%d", rT_addr
, vB_addr
);
15673 binop( Iop_64HLtoV128
,
15674 binop( Iop_32HLto64
,
15677 mkexpr( word_parity
[0] ),
15678 mkexpr( word_parity
[1] ) ) ),
15679 binop( Iop_32HLto64
,
15682 mkexpr( word_parity
[2] ),
15683 mkexpr( word_parity
[3] ) ) ) ) );
15685 } else if ( rA_addr
== 10 ) {
15686 DIP("vprtybq v%d,v%d", rT_addr
, vB_addr
);
15689 binop( Iop_64HLtoV128
,
15692 mkXOr4_32( word_parity
[0],
15695 word_parity
[3] ) ) ) );
15700 case 16: // vextsb2w, Vector Extend Sign Byte to Word
15701 DIP("vextsb2w v%d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
15703 /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to
15704 * two byte sign extended result. Then do a two byte to four byte sign
15705 * extended multiply. Note contents of upper three bytes in word are
15706 * "over written". So just take source and multiply by 1.
15708 assign( vT
, binop( Iop_MullEven16Sx8
,
15709 binop( Iop_64HLtoV128
,
15710 mkU64( 0x0000000100000001 ),
15711 mkU64( 0x0000000100000001 ) ),
15712 binop( Iop_MullEven8Sx16
,
15714 binop( Iop_64HLtoV128
,
15715 mkU64( 0x0001000100010001 ),
15716 mkU64( 0x0001000100010001 ) ) ) ) );
15719 case 17: // vextsh2w, Vector Extend Sign Halfword to Word
15720 DIP("vextsh2w v%d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
15722 /* Iop_MullEven16Sx8 does a signed widening multiply of four byte
15723 * 8 bytes. Note contents of upper two bytes in word are
15724 * "over written". So just take source and multiply by 1.
15726 assign( vT
, binop( Iop_MullEven16Sx8
,
15727 binop( Iop_64HLtoV128
,
15728 mkU64( 0x0000000100000001 ),
15729 mkU64( 0x0000000100000001 ) ),
15734 case 24: // vextsb2d, Vector Extend Sign Byte to Doubleword
15735 DIP("vextsb2d v%d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
15737 /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to
15738 * two byte sign extended result. Then do a two byte to four byte sign
15739 * extended multiply. Then do four byte to eight byte multiply.
15741 assign( vT
, binop( Iop_MullEven32Sx4
,
15742 binop( Iop_64HLtoV128
,
15743 mkU64( 0x0000000000000001 ),
15744 mkU64( 0x0000000000000001 ) ),
15745 binop( Iop_MullEven16Sx8
,
15746 binop( Iop_64HLtoV128
,
15747 mkU64( 0x0000000100000001 ),
15748 mkU64( 0x0000000100000001 ) ),
15749 binop( Iop_MullEven8Sx16
,
15750 binop( Iop_64HLtoV128
,
15751 mkU64( 0x0001000100010001 ),
15752 mkU64( 0x0001000100010001 ) ),
15753 mkexpr( vB
) ) ) ) );
15756 case 25: // vextsh2d, Vector Extend Sign Halfword to Doubleword
15757 DIP("vextsh2d v%d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
15759 assign( vT
, binop( Iop_MullEven32Sx4
,
15760 binop( Iop_64HLtoV128
,
15761 mkU64( 0x0000000000000001 ),
15762 mkU64( 0x0000000000000001 ) ),
15763 binop( Iop_MullEven16Sx8
,
15764 binop( Iop_64HLtoV128
,
15765 mkU64( 0x0000000100000001 ),
15766 mkU64( 0x0000000100000001 ) ),
15767 mkexpr( vB
) ) ) );
15770 case 26: // vextsw2d, Vector Extend Sign Word to Doubleword
15771 DIP("vextsw2d v%d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
15773 assign( vT
, binop( Iop_MullEven32Sx4
,
15774 binop( Iop_64HLtoV128
,
15775 mkU64( 0x0000000000000001 ),
15776 mkU64( 0x0000000000000001 ) ),
15780 case 28: // vctzb, Vector Count Trailing Zeros Byte
15782 DIP("vctzb v%d,v%d", rT_addr
, vB_addr
);
15784 /* This instruction is only available in the ISA 3.0 */
15785 if ( !mode64
|| !allow_isa_3_0
) {
15786 vex_printf("\n vctzb instruction not supported on non ISA 3.0 platform\n\n");
15789 assign( vT
, unop( Iop_Ctz8x16
, mkexpr( vB
) ) );
15793 case 29: // vctzh, Vector Count Trailing Zeros Halfword
15795 DIP("vctzh v%d,v%d", rT_addr
, vB_addr
);
15797 /* This instruction is only available in the ISA 3.0 */
15798 if ( !mode64
|| !allow_isa_3_0
) {
15799 vex_printf("\n vctzh instruction not supported on non ISA 3.0 platform\n\n");
15802 assign( vT
, unop( Iop_Ctz16x8
, mkexpr( vB
) ) );
15806 case 30: // vctzw, Vector Count Trailing Zeros Word
15808 DIP("vctzw v%d,v%d", rT_addr
, vB_addr
);
15810 /* This instruction is only available in the ISA 3.0 */
15811 if ( !mode64
|| !allow_isa_3_0
) {
15812 vex_printf("\n vctzw instruction not supported on non ISA 3.0 platform\n\n");
15815 assign( vT
, unop( Iop_Ctz32x4
, mkexpr( vB
) ) );
15819 case 31: // vctzd, Vector Count Trailing Zeros Double word
15821 DIP("vctzd v%d,v%d", rT_addr
, vB_addr
);
15823 /* This instruction is only available in the ISA 3.0 */
15824 if ( !mode64
|| !allow_isa_3_0
) {
15825 vex_printf("\n vctzd instruction not supported on non ISA 3.0 platform\n\n");
15828 assign( vT
, unop( Iop_Ctz64x2
, mkexpr( vB
) ) );
15833 vex_printf("dis_av_extend_sign(ppc)(Unsupported vector extend sign instruction)\n");
15837 putVReg( rT_addr
, mkexpr( vT
) );
15842 Vector Rotate Instructions
15844 static Bool
dis_av_rotate ( UInt theInstr
)
15848 UChar opc1
= ifieldOPC( theInstr
);
15849 UChar vT_addr
= ifieldRegDS( theInstr
);
15850 UChar vA_addr
= ifieldRegA( theInstr
);
15851 UChar vB_addr
= ifieldRegB( theInstr
);
15852 UInt opc2
= IFIELD( theInstr
, 0, 11 );
15854 IRTemp vA
= newTemp( Ity_V128
);
15855 IRTemp vB
= newTemp( Ity_V128
);
15856 IRTemp src3
= newTemp( Ity_V128
);
15857 IRTemp vT
= newTemp( Ity_V128
);
15858 IRTemp field_mask
= newTemp( Ity_V128
);
15859 IRTemp mask128
= newTemp( Ity_V128
);
15861 IRTemp left_bits
[4];
15862 IRTemp right_bits
[4];
15867 IRTemp tmp_mask
[4];
15868 IRTemp invert_mask
[4];
15873 unsigned long long word_mask
;
15875 if ( opc1
!= 0x4 ) {
15876 vex_printf("dis_av_rotate(ppc)(instr)\n");
15880 assign( vA
, getVReg( vA_addr
) );
15881 assign( vB
, getVReg( vB_addr
) );
15884 case 0x85: // vrlwmi, Vector Rotate Left Word then Mask Insert
15885 case 0x185: // vrlwnm, Vector Rotate Left Word then AND with Mask
15888 assign( field_mask
, binop( Iop_64HLtoV128
,
15891 word_mask
= 0xFFFFFFFF;
15894 case 0x0C5: // vrldmi, Vector Rotate Left Doubleword then Mask Insert
15895 case 0x1C5: // vrldnm, Vector Rotate Left Doubleword then AND with Mask
15898 assign( field_mask
, binop( Iop_64HLtoV128
,
15901 word_mask
= 0xFFFFFFFFFFFFFFFFULL
;
15904 vex_printf("dis_av_rotate(ppc)(opc2)\n");
15908 for( i
= 0; i
< num_words
; i
++ ) {
15909 left_bits
[i
] = newTemp( Ity_I8
);
15910 right_bits
[i
] = newTemp( Ity_I8
);
15911 shift
[i
] = newTemp( Ity_I8
);
15912 mb
[i
] = newTemp( Ity_I64
);
15913 me
[i
] = newTemp( Ity_I64
);
15914 tmp_mask
[i
] = newTemp( Ity_I64
);
15915 invert_mask
[i
] = newTemp( Ity_I64
);
15916 mask
[i
] = newTemp( Ity_V128
);
15917 tmp128
[i
] = newTemp( Ity_V128
);
15918 vA_word
[i
] = newTemp( Ity_V128
);
15922 unop( Iop_V128to64
,
15923 binop( Iop_AndV128
,
15924 binop( Iop_ShrV128
,
15926 mkU8( (num_words
- 1 - i
)
15928 mkexpr( field_mask
) ) ) ) );
15930 assign( mb
[i
], unop( Iop_V128to64
,
15931 binop( Iop_AndV128
,
15932 binop( Iop_ShrV128
,
15934 mkU8( ( num_words
- 1 - i
)
15935 * word_size
+ 16 ) ),
15936 mkexpr( field_mask
) ) ) );
15938 assign( me
[i
], unop( Iop_V128to64
,
15939 binop( Iop_AndV128
,
15940 binop( Iop_ShrV128
,
15942 mkU8( ( num_words
- 1 - i
)
15943 * word_size
+ 8 ) ),
15944 mkexpr( field_mask
) ) ) );
15946 /* If me < mb, we have to flip things around and invert the mask */
15947 assign( invert_mask
[i
],
15948 unop( Iop_1Sto64
, binop( Iop_CmpLT64U
,
15949 mkexpr( me
[i
] ), mkexpr( mb
[i
] ) ) ) );
15951 /* left_bits = 63 - mb. Tells us how many bits to the left
15952 * of mb to clear. Note for a word left_bits = 32+mb, for a double
15953 * word left_bits = mb
15955 assign( left_bits
[i
],
15958 binop( Iop_And64
, // mb < me
15959 unop( Iop_Not64
, mkexpr( invert_mask
[i
] ) ),
15961 mkU64( 64 - word_size
),
15962 mkexpr( mb
[i
] ) ) ),
15963 binop( Iop_And64
, // me < mb
15964 mkexpr( invert_mask
[i
] ),
15966 mkU64( 64 + 1 - word_size
),
15967 mkexpr( me
[i
] ) ) ) ) ) );
15969 /* right_bits = 63 - me. Tells us how many bits to the right
15970 * of me to clear. Note for a word, left_bits = me+32, for a double
15971 * word left_bits = me
15973 assign( right_bits
[i
],
15976 binop( Iop_And64
, // mb < me
15977 unop( Iop_Not64
, mkexpr( invert_mask
[i
] ) ),
15979 mkU64( word_size
- 1 ),
15980 mkexpr( me
[i
] ) ) ),
15981 binop( Iop_And64
, // me < mb
15982 mkexpr( invert_mask
[i
] ),
15984 mkU64( word_size
- 1 + 1),
15985 mkexpr( mb
[i
] ) ) ) ) ) );
15987 /* create mask for 32-bit word or 64-bit word */
15988 assign( tmp_mask
[i
],
15993 mkU64( 0xFFFFFFFFFFFFFFFF ),
15994 mkexpr( left_bits
[i
] ) ),
15995 mkexpr( left_bits
[i
] ) ),
15996 mkexpr( right_bits
[i
] ) ),
15997 mkexpr( right_bits
[i
] ) ) );
16000 binop( Iop_64HLtoV128
,
16004 unop( Iop_Not64
, mkexpr( invert_mask
[i
] ) ),
16005 mkexpr( tmp_mask
[i
] ) ),
16007 mkexpr( invert_mask
[i
] ),
16008 /* Need to make sure mask is only the size
16011 mkU64( word_mask
),
16013 mkexpr( tmp_mask
[i
] ) ) ) ))));
16015 /* Need to rotate vA using a left and right shift of vA OR'd together
16016 * then ANDed with the mask.
16018 assign( vA_word
[i
], binop( Iop_AndV128
,
16020 binop( Iop_ShlV128
,
16021 binop( Iop_64HLtoV128
,
16023 mkU64( word_mask
) ),
16024 mkU8( ( num_words
- 1 - i
)
16025 * word_size
) ) ) );
16027 binop( Iop_AndV128
,
16028 binop( Iop_ShlV128
,
16030 mkU8( ( num_words
- 1 - i
) * word_size
) ),
16032 binop( Iop_ShlV128
,
16033 mkexpr( vA_word
[i
] ),
16034 mkexpr( shift
[i
] ) ),
16035 binop( Iop_ShrV128
,
16036 mkexpr( vA_word
[i
] ),
16039 mkU32( word_size
),
16041 mkexpr( shift
[i
] ) ) )
16046 case 0x85: // vrlwmi, Vector Rotate Left Word then Mask Insert
16047 DIP("vrlwmi %d,%d,v%d", vT_addr
, vA_addr
, vB_addr
);
16049 assign( src3
, getVReg( vT_addr
) );
16050 assign( mask128
, unop( Iop_NotV128
,
16051 mkOr4_V128_expr( binop( Iop_ShlV128
,
16054 binop( Iop_ShlV128
,
16057 binop( Iop_ShlV128
,
16060 mkexpr( mask
[3] ) ) ) );
16061 assign( vT
, binop( Iop_OrV128
,
16062 binop( Iop_AndV128
,
16064 mkexpr( mask128
) ),
16065 mkOr4_V128( tmp128
[0], tmp128
[1],
16066 tmp128
[2], tmp128
[3] ) ) );
16069 case 0xC5: // vrldmi, Vector Rotate Left Double word then Mask Insert
16070 DIP("vrldmi %d,%d,v%d", vT_addr
, vA_addr
, vB_addr
);
16072 assign( src3
, getVReg( vT_addr
) );
16073 assign( mask128
, unop( Iop_NotV128
,
16075 binop( Iop_ShlV128
,
16078 mkexpr( mask
[1] ) ) ) );
16080 assign( vT
, binop( Iop_OrV128
,
16081 binop( Iop_AndV128
,
16083 mkexpr( mask128
) ),
16085 mkexpr( tmp128
[0] ),
16086 mkexpr( tmp128
[1] ) ) ) );
16089 case 0x185: // vrlwnm, Vector Rotate Left Word then AND with Mask
16090 DIP("vrlwnm %d,%d,v%d", vT_addr
, vA_addr
, vB_addr
);
16091 assign( vT
, mkOr4_V128( tmp128
[0], tmp128
[1], tmp128
[2], tmp128
[3] ) );
16094 case 0x1C5: // vrldnm, Vector Rotate Left Doubleword then AND with Mask
16095 DIP("vrldnm %d,%d,v%d", vT_addr
, vA_addr
, vB_addr
);
16096 assign( vT
, binop( Iop_OrV128
,
16097 mkexpr( tmp128
[0] ),
16098 mkexpr( tmp128
[1] ) ) );
16102 putVReg( vT_addr
, mkexpr( vT
) );
16107 AltiVec Vector Extract Element Instructions
16109 static Bool
dis_av_extract_element ( UInt theInstr
)
16112 * sorta destination and first source are GPR not vector registers
16115 UChar opc1
= ifieldOPC( theInstr
);
16116 UChar rT_addr
= ifieldRegDS( theInstr
);
16117 UChar rA_addr
= ifieldRegA( theInstr
);
16118 UChar vB_addr
= ifieldRegB( theInstr
);
16119 UInt opc2
= IFIELD( theInstr
, 0, 11 );
16121 IRTemp vB
= newTemp( Ity_V128
);
16122 IRTemp rA
= newTemp( Ity_I64
);
16123 IRTemp rT
= newTemp( Ity_I64
);
16125 assign( vB
, getVReg( vB_addr
) );
16126 assign( rA
, getIReg( rA_addr
) );
16128 if ( opc1
!= 0x4 ) {
16129 vex_printf("dis_av_extract_element(ppc)(instr)\n");
16134 case 0x60D: // vextublx, vector extract unsigned Byte Left-indexed
16135 DIP("vextublx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
16137 assign( rT
, extract_field_from_vector( vB
,
16145 case 0x64D: // vextuhlx, vector extract unsigned Halfword Left-indexed
16146 DIP("vextuhlx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
16148 assign( rT
, extract_field_from_vector( vB
,
16155 case 0x68D: // vextuwlx, vector extract unsigned Word Left-indexed
16156 DIP("vextuwlx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
16158 assign( rT
, extract_field_from_vector( vB
,
16165 case 0x70D: // vextubrx, vector extract unsigned Byte Right-indexed
16166 DIP("vextubrx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
16168 assign( rT
, extract_field_from_vector( vB
, mkexpr( rA
), 0xFF ) );
16171 case 0x74D: // vextuhrx, vector extract unsigned Halfword Right-indexed
16172 DIP("vextuhrx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
16174 assign( rT
, extract_field_from_vector( vB
, mkexpr( rA
), 0xFFFF ) );
16177 case 0x78D: // vextuwrx, vector extract unsigned Word Right-indexed
16178 DIP("vextuwrx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
16180 assign( rT
, extract_field_from_vector( vB
, mkexpr( rA
), 0xFFFFFFFF ) );
16184 vex_printf("dis_av_extract_element(ppc)(opc2)\n");
16187 putIReg( rT_addr
, mkexpr( rT
) );
16192 * VSX scalar and vector convert instructions
16195 dis_vx_conv ( UInt theInstr
, UInt opc2
)
16198 UChar opc1
= ifieldOPC( theInstr
);
16199 UChar XT
= ifieldRegXT( theInstr
);
16200 UChar XB
= ifieldRegXB( theInstr
);
16202 IRTemp b3
, b2
, b1
, b0
;
16203 xB
= xB2
= IRTemp_INVALID
;
16205 if (opc1
!= 0x3C) {
16206 vex_printf( "dis_vx_conv(ppc)(instr)\n" );
16210 /* Create and assign temps only as needed for the given instruction. */
16212 // scalar double-precision floating point argument
16213 case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
16214 xB
= newTemp(Ity_F64
);
16216 unop( Iop_ReinterpI64asF64
,
16217 unop( Iop_V128HIto64
, getVSReg( XB
) ) ) );
16219 // vector double-precision floating point arguments
16220 case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
16222 xB
= newTemp(Ity_F64
);
16223 xB2
= newTemp(Ity_F64
);
16225 unop( Iop_ReinterpI64asF64
,
16226 unop( Iop_V128HIto64
, getVSReg( XB
) ) ) );
16228 unop( Iop_ReinterpI64asF64
,
16229 unop( Iop_V128to64
, getVSReg( XB
) ) ) );
16231 // vector single precision or [un]signed integer word arguments
16232 case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
16233 case 0x1f0: case 0x1d0:
16234 b3
= b2
= b1
= b0
= IRTemp_INVALID
;
16235 breakV128to4x32(getVSReg(XB
), &b3
, &b2
, &b1
, &b0
);
16237 // vector [un]signed integer doubleword argument
16238 case 0x3f0: case 0x370: case 0x3d0: case 0x350:
16239 xB
= newTemp(Ity_I64
);
16240 assign( xB
, unop( Iop_V128HIto64
, getVSReg( XB
) ) );
16241 xB2
= newTemp(Ity_I64
);
16242 assign( xB2
, unop( Iop_V128to64
, getVSReg( XB
) ) );
16244 // scalar [un]signed integer doubleword argument
16245 case 0x250: case 0x270: case 0x2D0: case 0x2F0:
16246 xB
= newTemp(Ity_I64
);
16247 assign( xB
, unop( Iop_V128HIto64
, getVSReg( XB
) ) );
16249 // scalar single precision argument
16250 case 0x292: // xscvspdp
16251 xB
= newTemp(Ity_I32
);
16253 assign( xB
, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32
,
16254 unop( Iop_V128HIto64
,
16255 getVSReg( XB
) ) ) ) );
16257 case 0x296: // xscvspdpn (non signaling version of xscvpdp)
16258 xB
= newTemp(Ity_I32
);
16260 unop( Iop_64HIto32
, unop( Iop_V128HIto64
, getVSReg( XB
) ) ) );
16263 /* Certain instructions have their complete implementation in the main switch statement
16264 * that follows this one; thus we have a "do nothing" case for those instructions here.
16266 case 0x170: case 0x150:
16267 break; // do nothing
16270 vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
16277 // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
16278 // to Signed Integer Doubleword format with Saturate)
16279 DIP("xscvdpsxds v%u,v%u\n", XT
, XB
);
16281 binop( Iop_64HLtoV128
, binop( Iop_F64toI64S
,
16282 mkU32( Irrm_ZERO
),
16283 mkexpr( xB
) ), mkU64( 0 ) ) );
16285 case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
16286 // Convert to Signed Integer Word format with Saturate)
16287 DIP("xscvdpsxws v%u,v%u\n", XT
, XB
);
16289 binop( Iop_64HLtoV128
,
16291 binop( Iop_F64toI32S
,
16292 mkU32( Irrm_ZERO
),
16296 case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
16297 // to Unsigned Integer Doubleword format with Saturate)
16298 DIP("xscvdpuxds v%u,v%u\n", XT
, XB
);
16300 binop( Iop_64HLtoV128
,
16301 binop( Iop_F64toI64U
,
16302 mkU32( Irrm_ZERO
),
16307 // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
16308 // to Single-Precision format)
16309 DIP("xscvsxdsp v%u,v%u\n", XT
, XB
);
16311 binop( Iop_64HLtoV128
,
16312 unop( Iop_ReinterpF64asI64
,
16313 binop( Iop_RoundF64toF32
,
16314 get_IR_roundingmode(),
16315 binop( Iop_I64StoF64
,
16316 get_IR_roundingmode(),
16317 mkexpr( xB
) ) ) ),
16321 // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
16322 // Double-Precision format)
16323 DIP("xscvsxddp v%u,v%u\n", XT
, XB
);
16325 binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
16326 binop( Iop_I64StoF64
, get_IR_roundingmode(),
16331 // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
16332 // Doubleword to Singel-Precision format)
16333 DIP("xscvuxdsp v%u,v%u\n", XT
, XB
);
16335 binop( Iop_64HLtoV128
,
16336 unop( Iop_ReinterpF64asI64
,
16337 binop( Iop_RoundF64toF32
,
16338 get_IR_roundingmode(),
16339 binop( Iop_I64UtoF64
,
16340 get_IR_roundingmode(),
16341 mkexpr( xB
) ) ) ),
16345 // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
16346 // Double-Precision format)
16347 DIP("xscvuxddp v%u,v%u\n", XT
, XB
);
16349 binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
16350 binop( Iop_I64UtoF64
, get_IR_roundingmode(),
16354 case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
16355 // to Signed Integer Word format with Saturate)
16356 case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
16357 // Convert to Unsigned Integer Word format with Saturate)
16359 IRTemp value_f64
[2];
16360 IRTemp Result_32
[2];
16361 IRTemp Result_32_tmp
[2];
16362 IRTemp nan_mask
[2];
16363 IRTemp underflow_mask
[2];
16364 IRTemp overflow_mask
[2];
16365 IRTemp error_mask
[2];
16366 IRTemp error_value
[2];
16370 Int underflow_value
;
16371 Int overflow_value
;
16372 IRExpr
* rmZero
= mkU32(Irrm_ZERO
);
16374 value_f64
[0] = newTemp(Ity_F64
);
16375 assign( value_f64
[0], mkexpr( xB
) );
16377 value_f64
[1] = newTemp(Ity_F64
);
16378 assign( value_f64
[1], mkexpr( xB2
) );
16380 for ( i
= 0; i
< 2; i
++) {
16381 Result_32
[i
] = newTemp(Ity_I32
);
16382 Result_32_tmp
[i
] = newTemp(Ity_I32
);
16383 nan_mask
[i
] = newTemp(Ity_I32
);
16384 underflow_mask
[i
] = newTemp(Ity_I32
);
16385 overflow_mask
[i
] = newTemp(Ity_I32
);
16386 error_mask
[i
] = newTemp(Ity_I32
);
16387 error_value
[i
] = newTemp(Ity_I32
);
16388 tmp_64
[i
] = newTemp(Ity_I64
);
16390 if ( opc2
== 0x1b0 ) { // xvcvdpsxws
16391 assign(Result_32_tmp
[i
], binop(Iop_F64toI32S
,
16392 rmZero
, mkexpr( value_f64
[i
] ) ) );
16394 /* result of Iop_CmpF64 is 0x01 if A < -2^31. */
16395 assign( underflow_mask
[i
],
16399 mkexpr( value_f64
[i
] ),
16400 unop( Iop_ReinterpI64asF64
,
16401 mkU64( 0xC1E0000000000000 ))))));
16402 overflow_value
= 0x7FFFFFFF;
16403 underflow_value
= 0x80000000;
16405 } else { // xvcvdpuxws
16406 assign( Result_32_tmp
[i
],
16407 binop( Iop_F64toI32U
,
16408 mkU32( Irrm_ZERO
),
16409 mkexpr( value_f64
[i
] ) ) );
16411 /* result of Iop_CmpF64 is 0x01 if A < 0. */
16412 assign( underflow_mask
[i
],
16416 mkexpr( value_f64
[i
] ),
16417 unop( Iop_ReinterpI64asF64
,
16418 mkU64( 0x0 ) ) ) ) ) );
16419 overflow_value
= 0xFFFFFFFF;
16420 underflow_value
= 0;
16423 /* Check if input is NaN, output is 0x80000000.
16424 if input < -2^31, output is 0x80000000.
16425 if input > 2^31 - 1, output is 0x7FFFFFFF */
16426 assign( tmp_64
[i
], unop (Iop_ReinterpF64asI64
,
16427 mkexpr( value_f64
[i
] ) ) );
16429 assign( nan_mask
[i
], unop( Iop_1Sto32
,
16430 is_NaN( Ity_I64
, tmp_64
[i
] ) ) );
16432 /* result of Iop_CmpF64 is 0x00 if A > 2^31 - 1. */
16433 assign( overflow_mask
[i
],
16435 binop( Iop_CmpEQ32
,
16438 mkexpr( value_f64
[i
] ),
16439 unop( Iop_ReinterpI64asF64
,
16440 mkU64( 0x41DFFFFFFFC00000 ))))));
16442 assign( error_mask
[i
], binop( Iop_Or32
, mkexpr( overflow_mask
[i
] ),
16444 mkexpr( underflow_mask
[i
] ),
16445 mkexpr( nan_mask
[i
] ) ) ) );
16447 if ( opc2
== 0x1b0 ) { // xvcvdpsxws
16448 /* NaN takes precedence over underflow/overflow for vxcvdpsxws */
16449 assign( error_value
[i
],
16452 unop( Iop_Not32
, mkexpr( nan_mask
[i
] ) ),
16455 mkexpr( overflow_mask
[i
] ),
16456 mkU32( overflow_value
) ),
16458 mkexpr( underflow_mask
[i
] ),
16459 mkU32( underflow_value
) ) ) ),
16461 mkexpr( nan_mask
[i
] ),
16462 mkU32( 0x80000000 ) ) ) );
16464 /* Less then zeo takes precedence over NaN/overflow
16465 for vxcvdpuxws in the hardware. Matching the HW here
16466 but it does not appear to match ISA. */
16467 assign( error_value
[i
],
16471 mkexpr( underflow_mask
[i
] ) ),
16474 mkexpr( overflow_mask
[i
] ),
16475 mkU32( overflow_value
) ),
16477 mkexpr( nan_mask
[i
] ),
16478 mkU32( 0x80000000 ) ) ) ),
16480 mkexpr( underflow_mask
[i
] ),
16481 mkU32( underflow_value
) ) ) );
16484 assign( Result_32
[i
], binop( Iop_Or32
,
16486 mkexpr( Result_32_tmp
[i
] ),
16488 mkexpr( error_mask
[i
] ) ) ),
16490 mkexpr( error_value
[i
] ),
16491 mkexpr( error_mask
[i
] ) ) ) );
16494 if ( opc2
== 0x1b0 ) {
16495 DIP("xvcvdpsxws v%u,v%u\n", XT
, XB
);
16498 DIP("xvcvdpuxws v%u,v%u", XT
, XB
);
16501 /* Result is put in the hi and low 32-bits of the double word result. */
16503 binop( Iop_64HLtoV128
,
16504 binop( Iop_32HLto64
,
16505 mkexpr( Result_32
[0] ),
16506 mkexpr( Result_32
[0] ) ),
16507 binop( Iop_32HLto64
,
16508 mkexpr( Result_32
[1] ),
16509 mkexpr( Result_32
[1] ) ) ) );
16512 case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
16513 // (VSX Vector truncate Single-Precision to integer and
16514 // Convert to [Un]signed Integer Word format with Saturate)
16516 IRExpr
* b0_result
, * b1_result
, * b2_result
, * b3_result
;
16517 IRTemp tempResult
= newTemp(Ity_V128
);
16518 IRTemp res0
= newTemp(Ity_I32
);
16519 IRTemp res1
= newTemp(Ity_I32
);
16520 IRTemp res2
= newTemp(Ity_I32
);
16521 IRTemp res3
= newTemp(Ity_I32
);
16522 IRTemp hi64
= newTemp(Ity_I64
);
16523 IRTemp lo64
= newTemp(Ity_I64
);
16524 Bool un_signed
= (opc2
== 0x110);
16525 IROp op
= un_signed
? Iop_QF32toI32Ux4_RZ
: Iop_QF32toI32Sx4_RZ
;
16527 DIP("xvcvsp%sxws v%u,v%u\n", un_signed
? "u" : "s", XT
, XB
);
16528 /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
16529 * then result is set to 0x80000000. */
16530 assign(tempResult
, unop(op
, getVSReg(XB
)));
16531 assign( hi64
, unop(Iop_V128HIto64
, mkexpr(tempResult
)) );
16532 assign( lo64
, unop(Iop_V128to64
, mkexpr(tempResult
)) );
16533 assign( res3
, unop(Iop_64HIto32
, mkexpr(hi64
)) );
16534 assign( res2
, unop(Iop_64to32
, mkexpr(hi64
)) );
16535 assign( res1
, unop(Iop_64HIto32
, mkexpr(lo64
)) );
16536 assign( res0
, unop(Iop_64to32
, mkexpr(lo64
)) );
16538 b3_result
= IRExpr_ITE(is_NaN(Ity_I32
, b3
),
16539 // then: result is 0x{8|0}80000000
16540 mkU32(un_signed
? 0x00000000 : 0x80000000),
16541 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16543 b2_result
= IRExpr_ITE(is_NaN(Ity_I32
, b2
),
16544 // then: result is 0x{8|0}80000000
16545 mkU32(un_signed
? 0x00000000 : 0x80000000),
16546 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16548 b1_result
= IRExpr_ITE(is_NaN(Ity_I32
, b1
),
16549 // then: result is 0x{8|0}80000000
16550 mkU32(un_signed
? 0x00000000 : 0x80000000),
16551 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16553 b0_result
= IRExpr_ITE(is_NaN(Ity_I32
, b0
),
16554 // then: result is 0x{8|0}80000000
16555 mkU32(un_signed
? 0x00000000 : 0x80000000),
16556 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16560 binop( Iop_64HLtoV128
,
16561 binop( Iop_32HLto64
, b3_result
, b2_result
),
16562 binop( Iop_32HLto64
, b1_result
, b0_result
) ) );
16565 case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
16566 // Convert to Single-Precision format
16567 // Apr 2019 update - write the result to both halves of the
16568 // target VSR. (see bug 401827,401828).
16569 DIP("xscvdpsp v%u,v%u\n", XT
, XB
);
16570 IRTemp ResultI32a
= newTemp(Ity_I32
);
16571 assign(ResultI32a
, unop( Iop_ReinterpF32asI32
,
16572 unop( Iop_TruncF64asF32
,
16573 binop( Iop_RoundF64toF32
,
16574 get_IR_roundingmode(),
16575 mkexpr( xB
) ) ) ) );
16577 binop( Iop_64HLtoV128
,
16578 binop( Iop_32HLto64
,
16579 mkexpr(ResultI32a
),
16580 mkexpr(ResultI32a
) ),
16583 case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
16584 vector Single-Precision non-signalling */
16585 // Apr 2019 update - write the result to both halves of the
16586 // target VSR. (see bug 401827,401828).
16587 DIP("xscvdpspn v%u,v%u\n", XT
, XB
);
16588 IRTemp ResultI32b
= newTemp(Ity_I32
);
16589 assign(ResultI32b
, unop( Iop_ReinterpF32asI32
,
16590 unop( Iop_TruncF64asF32
,
16591 mkexpr( xB
) ) ) );
16593 binop( Iop_64HLtoV128
,
16594 binop( Iop_32HLto64
,
16595 mkexpr(ResultI32b
),
16596 mkexpr(ResultI32b
) ),
16599 case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
16600 // and Convert to Unsigned Integer Word format with Saturate)
16601 DIP("xscvdpuxws v%u,v%u\n", XT
, XB
);
16603 binop( Iop_64HLtoV128
,
16604 binop( Iop_32HLto64
,
16606 binop( Iop_F64toI32U
,
16607 mkU32( Irrm_ZERO
),
16611 case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
16612 DIP("xscvspdp v%u,v%u\n", XT
, XB
);
16614 binop( Iop_64HLtoV128
,
16615 unop( Iop_ReinterpF64asI64
,
16616 unop( Iop_F32toF64
,
16617 unop( Iop_ReinterpI32asF32
, mkexpr( xB
) ) ) ),
16620 case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
16621 DIP("xscvspdpn v%u,v%u\n", XT
, XB
);
16623 binop( Iop_64HLtoV128
,
16624 unop( Iop_ReinterpF64asI64
,
16625 unop( Iop_F32toF64
,
16626 unop( Iop_ReinterpI32asF32
, mkexpr( xB
) ) ) ),
16629 case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
16630 // and Convert to Single-Precision format)
16631 DIP("xvcvdpsp v%u,v%u\n", XT
, XB
);
16633 /* Note, the 32-bit result is put into the upper and lower bits of the
16634 doubleword result. */
16636 binop( Iop_64HLtoV128
,
16637 binop( Iop_32HLto64
,
16638 unop( Iop_ReinterpF32asI32
,
16639 unop( Iop_TruncF64asF32
,
16640 binop( Iop_RoundF64toF32
,
16641 get_IR_roundingmode(),
16642 mkexpr( xB
) ) ) ),
16643 unop( Iop_ReinterpF32asI32
,
16644 unop( Iop_TruncF64asF32
,
16645 binop( Iop_RoundF64toF32
,
16646 get_IR_roundingmode(),
16647 mkexpr( xB
) ) ) ) ),
16648 binop( Iop_32HLto64
,
16649 unop( Iop_ReinterpF32asI32
,
16650 unop( Iop_TruncF64asF32
,
16651 binop( Iop_RoundF64toF32
,
16652 get_IR_roundingmode(),
16653 mkexpr( xB2
) ) ) ),
16654 unop( Iop_ReinterpF32asI32
,
16655 unop( Iop_TruncF64asF32
,
16656 binop( Iop_RoundF64toF32
,
16657 get_IR_roundingmode(),
16658 mkexpr( xB2
) ) ) ) ) ) );
16660 case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
16661 // and Convert to Unsigned Integer Doubleword format
16663 DIP("xvcvdpuxds v%u,v%u\n", XT
, XB
);
16665 binop( Iop_64HLtoV128
,
16666 binop( Iop_F64toI64U
, mkU32( Irrm_ZERO
), mkexpr( xB
) ),
16667 binop( Iop_F64toI64U
, mkU32( Irrm_ZERO
), mkexpr( xB2
) ) ) );
16669 case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
16670 DIP("xvcvspdp v%u,v%u\n", XT
, XB
);
16672 binop( Iop_64HLtoV128
,
16673 unop( Iop_ReinterpF64asI64
,
16674 unop( Iop_F32toF64
,
16675 unop( Iop_ReinterpI32asF32
,
16676 handle_SNaN_to_QNaN_32( mkexpr( b3
) ) ) ) ),
16677 unop( Iop_ReinterpF64asI64
,
16678 unop( Iop_F32toF64
,
16679 unop( Iop_ReinterpI32asF32
,
16680 handle_SNaN_to_QNaN_32( mkexpr( b1
) ) ) ) ) ) );
16682 case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
16683 // Convert to Signed Integer Doubleword format with Saturate)
16684 DIP("xvcvspsxds v%u,v%u\n", XT
, XB
);
16686 binop( Iop_64HLtoV128
,
16687 binop( Iop_F64toI64S
,
16688 mkU32( Irrm_ZERO
),
16689 unop( Iop_F32toF64
,
16690 unop( Iop_ReinterpI32asF32
, mkexpr( b3
) ) ) ),
16691 binop( Iop_F64toI64S
,
16692 mkU32( Irrm_ZERO
),
16693 unop( Iop_F32toF64
,
16694 unop( Iop_ReinterpI32asF32
, mkexpr( b1
) ) ) ) ) );
16696 case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
16697 // Convert to Unsigned Integer Doubleword format with Saturate)
16698 DIP("xvcvspuxds v%u,v%u\n", XT
, XB
);
16700 binop( Iop_64HLtoV128
,
16701 binop( Iop_F64toI64U
,
16702 mkU32( Irrm_ZERO
),
16703 unop( Iop_F32toF64
,
16704 unop( Iop_ReinterpI32asF32
, mkexpr( b3
) ) ) ),
16705 binop( Iop_F64toI64U
,
16706 mkU32( Irrm_ZERO
),
16707 unop( Iop_F32toF64
,
16708 unop( Iop_ReinterpI32asF32
, mkexpr( b1
) ) ) ) ) );
16710 case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
16711 // Convert to Signed Integer Doubleword format with Saturate)
16712 DIP("xvcvdpsxds v%u,v%u\n", XT
, XB
);
16714 binop( Iop_64HLtoV128
,
16715 binop( Iop_F64toI64S
, mkU32( Irrm_ZERO
), mkexpr( xB
) ),
16716 binop( Iop_F64toI64S
, mkU32( Irrm_ZERO
), mkexpr( xB2
) ) ) );
16718 case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
16719 // to Double-Precision format)
16720 DIP("xvcvsxddp v%u,v%u\n", XT
, XB
);
16722 binop( Iop_64HLtoV128
,
16723 unop( Iop_ReinterpF64asI64
,
16724 binop( Iop_I64StoF64
,
16725 get_IR_roundingmode(),
16727 unop( Iop_ReinterpF64asI64
,
16728 binop( Iop_I64StoF64
,
16729 get_IR_roundingmode(),
16730 mkexpr( xB2
) ) ) ) );
16732 case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
16733 // to Double-Precision format)
16734 DIP("xvcvuxddp v%u,v%u\n", XT
, XB
);
16736 binop( Iop_64HLtoV128
,
16737 unop( Iop_ReinterpF64asI64
,
16738 binop( Iop_I64UtoF64
,
16739 get_IR_roundingmode(),
16741 unop( Iop_ReinterpF64asI64
,
16742 binop( Iop_I64UtoF64
,
16743 get_IR_roundingmode(),
16744 mkexpr( xB2
) ) ) ) );
16747 case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
16748 // to Single-Precision format)
16750 IRTemp result32hi
= newTemp(Ity_I32
);
16751 IRTemp result32lo
= newTemp(Ity_I32
);
16753 DIP("xvcvsxdsp v%u,v%u\n", XT
, XB
);
16754 assign( result32hi
,
16755 unop( Iop_ReinterpF32asI32
,
16756 unop( Iop_TruncF64asF32
,
16757 binop( Iop_RoundF64toF32
,
16758 get_IR_roundingmode(),
16759 binop( Iop_I64StoF64
,
16760 get_IR_roundingmode(),
16761 mkexpr( xB
) ) ) ) ) );
16762 assign( result32lo
,
16763 unop( Iop_ReinterpF32asI32
,
16764 unop( Iop_TruncF64asF32
,
16765 binop( Iop_RoundF64toF32
,
16766 get_IR_roundingmode(),
16767 binop( Iop_I64StoF64
,
16768 get_IR_roundingmode(),
16769 mkexpr( xB2
) ) ) ) ) );
16772 binop( Iop_64HLtoV128
,
16773 binop( Iop_32HLto64
,
16774 mkexpr( result32hi
),
16775 mkexpr( result32hi
) ),
16776 binop( Iop_32HLto64
,
16777 mkexpr( result32lo
),
16778 mkexpr( result32lo
) ) ) );
16781 case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
16782 // to Single-Precision format)
16784 IRTemp result32hi
= newTemp(Ity_I32
);
16785 IRTemp result32lo
= newTemp(Ity_I32
);
16787 DIP("xvcvuxdsp v%u,v%u\n", XT
, XB
);
16788 assign( result32hi
,
16789 unop( Iop_ReinterpF32asI32
,
16790 unop( Iop_TruncF64asF32
,
16791 binop( Iop_RoundF64toF32
,
16792 get_IR_roundingmode(),
16793 binop( Iop_I64UtoF64
,
16794 get_IR_roundingmode(),
16795 mkexpr( xB
) ) ) ) ) );
16796 assign( result32lo
,
16797 unop( Iop_ReinterpF32asI32
,
16798 unop( Iop_TruncF64asF32
,
16799 binop( Iop_RoundF64toF32
,
16800 get_IR_roundingmode(),
16801 binop( Iop_I64UtoF64
,
16802 get_IR_roundingmode(),
16803 mkexpr( xB2
) ) ) ) ) );
16805 binop( Iop_64HLtoV128
,
16806 binop( Iop_32HLto64
,
16807 mkexpr( result32hi
),
16808 mkexpr( result32hi
) ),
16809 binop( Iop_32HLto64
,
16810 mkexpr( result32lo
),
16811 mkexpr( result32lo
) ) ) );
16815 case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
16816 DIP("xvcvsxwdp v%u,v%u\n", XT
, XB
);
16818 binop( Iop_64HLtoV128
,
16819 unop( Iop_ReinterpF64asI64
,
16820 binop( Iop_I64StoF64
, get_IR_roundingmode(),
16821 unop( Iop_32Sto64
, mkexpr( b3
) ) ) ),
16822 unop( Iop_ReinterpF64asI64
,
16823 binop( Iop_I64StoF64
, get_IR_roundingmode(),
16824 unop( Iop_32Sto64
, mkexpr( b1
) ) ) ) ) );
16826 case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
16827 DIP("xvcvuxwdp v%u,v%u\n", XT
, XB
);
16829 binop( Iop_64HLtoV128
,
16830 unop( Iop_ReinterpF64asI64
,
16831 binop( Iop_I64UtoF64
, get_IR_roundingmode(),
16832 unop( Iop_32Uto64
, mkexpr( b3
) ) ) ),
16833 unop( Iop_ReinterpF64asI64
,
16834 binop( Iop_I64UtoF64
, get_IR_roundingmode(),
16835 unop( Iop_32Uto64
, mkexpr( b1
) ) ) ) ) );
16837 case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
16838 DIP("xvcvsxwsp v%u,v%u\n", XT
, XB
);
16839 putVSReg( XT
, unop( Iop_I32StoF32x4_DEP
, getVSReg( XB
) ) );
16841 case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
16842 DIP("xvcvuxwsp v%u,v%u\n", XT
, XB
);
16843 putVSReg( XT
, unop( Iop_I32UtoF32x4_DEP
, getVSReg( XB
) ) );
16847 vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
16854 * VSX vector Double Precision Floating Point Arithmetic Instructions
16857 dis_vxv_dp_arith ( UInt theInstr
, UInt opc2
)
16860 UChar opc1
= ifieldOPC( theInstr
);
16861 UChar XT
= ifieldRegXT( theInstr
);
16862 UChar XA
= ifieldRegXA( theInstr
);
16863 UChar XB
= ifieldRegXB( theInstr
);
16864 IRExpr
* rm
= get_IR_roundingmode();
16865 IRTemp frA
= newTemp(Ity_F64
);
16866 IRTemp frB
= newTemp(Ity_F64
);
16867 IRTemp frA2
= newTemp(Ity_F64
);
16868 IRTemp frB2
= newTemp(Ity_F64
);
16870 if (opc1
!= 0x3C) {
16871 vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
16875 assign(frA
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XA
))));
16876 assign(frB
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XB
))));
16877 assign(frA2
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, getVSReg( XA
))));
16878 assign(frB2
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, getVSReg( XB
))));
16881 case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
16882 case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
16883 case 0x180: // xvadddp (VSX Vector Add Double-Precision)
16884 case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
16887 const HChar
* oper_name
;
16907 vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
16909 IRTemp hiResult
= newTemp(Ity_I64
);
16910 IRTemp loResult
= newTemp(Ity_I64
);
16911 DIP("xv%sdp v%d,v%d,v%d\n", oper_name
, XT
, XA
, XB
);
16914 unop( Iop_ReinterpF64asI64
,
16915 triop( mOp
, rm
, mkexpr( frA
), mkexpr( frB
) ) ) );
16917 unop( Iop_ReinterpF64asI64
,
16918 triop( mOp
, rm
, mkexpr( frA2
), mkexpr( frB2
) ) ) );
16920 binop( Iop_64HLtoV128
, mkexpr( hiResult
), mkexpr( loResult
) ) );
16923 case 0x196: // xvsqrtdp
16925 IRTemp hiResult
= newTemp(Ity_I64
);
16926 IRTemp loResult
= newTemp(Ity_I64
);
16927 DIP("xvsqrtdp v%d,v%d\n", XT
, XB
);
16930 unop( Iop_ReinterpF64asI64
,
16931 binop( Iop_SqrtF64
, rm
, mkexpr( frB
) ) ) );
16933 unop( Iop_ReinterpF64asI64
,
16934 binop( Iop_SqrtF64
, rm
, mkexpr( frB2
) ) ) );
16936 binop( Iop_64HLtoV128
, mkexpr( hiResult
), mkexpr( loResult
) ) );
16939 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
16940 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
16941 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
16942 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
16944 /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
16949 * and for xvm{add|sub}adp . . .
16955 IROp mOp
= Iop_INVALID
;
16956 const HChar
* oper_name
= NULL
;
16960 case 0x184: case 0x1A4:
16961 case 0x384: case 0x3A4:
16964 mdp
= (opc2
& 0x0FF) == 0x0A4;
16967 case 0x1C4: case 0x1E4:
16968 case 0x3C4: case 0x3E4:
16971 mdp
= (opc2
& 0x0FF) == 0x0E4;
16975 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
16979 case 0x384: case 0x3A4:
16980 case 0x3C4: case 0x3E4:
16986 IRTemp hiResult
= newTemp(Ity_I64
);
16987 IRTemp loResult
= newTemp(Ity_I64
);
16988 IRTemp frT
= newTemp(Ity_F64
);
16989 IRTemp frT2
= newTemp(Ity_F64
);
16990 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate
? "n" : "", oper_name
, mdp
? "mdp" : "adp",
16992 assign(frT
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XT
) ) ) );
16993 assign(frT2
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, getVSReg( XT
) ) ) );
16996 unop( Iop_ReinterpF64asI64
,
17000 mkexpr( mdp
? frT
: frB
),
17001 mkexpr( mdp
? frB
: frT
) ) ) );
17003 unop( Iop_ReinterpF64asI64
,
17007 mkexpr( mdp
? frT2
: frB2
),
17008 mkexpr( mdp
? frB2
: frT2
) ) ) );
17010 binop( Iop_64HLtoV128
,
17011 mkexpr( negate
? getNegatedResult( hiResult
)
17013 mkexpr( negate
? getNegatedResult( loResult
)
17017 case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
17019 IRTemp frBHi_I64
= newTemp(Ity_I64
);
17020 IRTemp frBLo_I64
= newTemp(Ity_I64
);
17021 IRTemp flagsHi
= newTemp(Ity_I32
);
17022 IRTemp flagsLo
= newTemp(Ity_I32
);
17023 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
17024 IRTemp fe_flagHi
, fg_flagHi
, fe_flagLo
, fg_flagLo
;
17025 fe_flagHi
= fg_flagHi
= fe_flagLo
= fg_flagLo
= IRTemp_INVALID
;
17027 DIP("xvtsqrtdp cr%d,v%d\n", crfD
, XB
);
17028 assign( frBHi_I64
, unop(Iop_V128HIto64
, getVSReg( XB
)) );
17029 assign( frBLo_I64
, unop(Iop_V128to64
, getVSReg( XB
)) );
17030 do_fp_tsqrt(frBHi_I64
, False
/*not single precision*/, &fe_flagHi
, &fg_flagHi
);
17031 do_fp_tsqrt(frBLo_I64
, False
/*not single precision*/, &fe_flagLo
, &fg_flagLo
);
17032 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
17033 * where fl_flag == 1 on ppc64.
17037 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17038 binop( Iop_Shl32
, mkexpr(fg_flagHi
), mkU8( 2 ) ) ),
17039 binop( Iop_Shl32
, mkexpr(fe_flagHi
), mkU8( 1 ) ) ) );
17042 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17043 binop( Iop_Shl32
, mkexpr(fg_flagLo
), mkU8( 2 ) ) ),
17044 binop( Iop_Shl32
, mkexpr(fe_flagLo
), mkU8( 1 ) ) ) );
17045 putGST_field( PPC_GST_CR
,
17046 binop( Iop_Or32
, mkexpr( flagsHi
), mkexpr( flagsLo
) ),
17050 case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
17052 IRTemp frBHi_I64
= newTemp(Ity_I64
);
17053 IRTemp frBLo_I64
= newTemp(Ity_I64
);
17054 IRTemp frAHi_I64
= newTemp(Ity_I64
);
17055 IRTemp frALo_I64
= newTemp(Ity_I64
);
17056 IRTemp flagsHi
= newTemp(Ity_I32
);
17057 IRTemp flagsLo
= newTemp(Ity_I32
);
17058 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
17059 IRTemp fe_flagHi
, fg_flagHi
, fe_flagLo
, fg_flagLo
;
17060 fe_flagHi
= fg_flagHi
= fe_flagLo
= fg_flagLo
= IRTemp_INVALID
;
17062 DIP("xvtdivdp cr%d,v%d,v%d\n", crfD
, XA
, XB
);
17063 assign( frAHi_I64
, unop(Iop_V128HIto64
, getVSReg( XA
)) );
17064 assign( frALo_I64
, unop(Iop_V128to64
, getVSReg( XA
)) );
17065 assign( frBHi_I64
, unop(Iop_V128HIto64
, getVSReg( XB
)) );
17066 assign( frBLo_I64
, unop(Iop_V128to64
, getVSReg( XB
)) );
17068 _do_fp_tdiv(frAHi_I64
, frBHi_I64
, False
/*dp*/, &fe_flagHi
, &fg_flagHi
);
17069 _do_fp_tdiv(frALo_I64
, frBLo_I64
, False
/*dp*/, &fe_flagLo
, &fg_flagLo
);
17070 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
17071 * where fl_flag == 1 on ppc64.
17075 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17076 binop( Iop_Shl32
, mkexpr(fg_flagHi
), mkU8( 2 ) ) ),
17077 binop( Iop_Shl32
, mkexpr(fe_flagHi
), mkU8( 1 ) ) ) );
17080 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17081 binop( Iop_Shl32
, mkexpr(fg_flagLo
), mkU8( 2 ) ) ),
17082 binop( Iop_Shl32
, mkexpr(fe_flagLo
), mkU8( 1 ) ) ) );
17083 putGST_field( PPC_GST_CR
,
17084 binop( Iop_Or32
, mkexpr( flagsHi
), mkexpr( flagsLo
) ),
17090 vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
17097 * VSX vector Single Precision Floating Point Arithmetic Instructions
17100 dis_vxv_sp_arith ( UInt theInstr
, UInt opc2
)
17103 UChar opc1
= ifieldOPC( theInstr
);
17104 UChar XT
= ifieldRegXT( theInstr
);
17105 UChar XA
= ifieldRegXA( theInstr
);
17106 UChar XB
= ifieldRegXB( theInstr
);
17107 IRExpr
* rm
= get_IR_roundingmode();
17108 IRTemp a3
, a2
, a1
, a0
;
17109 IRTemp b3
, b2
, b1
, b0
;
17110 IRTemp res0
= newTemp(Ity_I32
);
17111 IRTemp res1
= newTemp(Ity_I32
);
17112 IRTemp res2
= newTemp(Ity_I32
);
17113 IRTemp res3
= newTemp(Ity_I32
);
17115 a3
= a2
= a1
= a0
= IRTemp_INVALID
;
17116 b3
= b2
= b1
= b0
= IRTemp_INVALID
;
17118 if (opc1
!= 0x3C) {
17119 vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
17124 case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
17125 DIP("xvaddsp v%d,v%d,v%d\n", XT
, XA
, XB
);
17126 // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
17127 putVSReg( XT
, triop(Iop_Add32Fx4
, rm
,
17128 getVSReg( XA
), getVSReg( XB
)) );
17131 case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
17132 DIP("xvmulsp v%d,v%d,v%d\n", XT
, XA
, XB
);
17133 // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
17134 putVSReg( XT
, triop(Iop_Mul32Fx4
, rm
,
17135 getVSReg( XA
), getVSReg( XB
)) );
17138 case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
17139 DIP("xvsubsp v%d,v%d,v%d\n", XT
, XA
, XB
);
17140 // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
17141 putVSReg( XT
, triop(Iop_Sub32Fx4
, rm
,
17142 getVSReg( XA
), getVSReg( XB
)) );
17145 case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
17147 /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
17148 * So there are two choices:
17149 * 1. Implement the xvdivsp with a native insn; or
17150 * 2. Extract the 4 single precision floats from each vector
17151 * register inputs and perform fdivs on each pair
17152 * I will do the latter, due to the general philosophy of
17153 * reusing existing implementations when practical.
17155 DIP("xvdivsp v%d,v%d,v%d\n", XT
, XA
, XB
);
17156 breakV128to4xF64( getVSReg( XA
), &a3
, &a2
, &a1
, &a0
);
17157 breakV128to4xF64( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
17160 unop( Iop_ReinterpF32asI32
,
17161 unop( Iop_TruncF64asF32
,
17162 triop( Iop_DivF64r32
, rm
, mkexpr( a0
), mkexpr( b0
) ) ) ) );
17164 unop( Iop_ReinterpF32asI32
,
17165 unop( Iop_TruncF64asF32
,
17166 triop( Iop_DivF64r32
, rm
, mkexpr( a1
), mkexpr( b1
) ) ) ) );
17168 unop( Iop_ReinterpF32asI32
,
17169 unop( Iop_TruncF64asF32
,
17170 triop( Iop_DivF64r32
, rm
, mkexpr( a2
), mkexpr( b2
) ) ) ) );
17172 unop( Iop_ReinterpF32asI32
,
17173 unop( Iop_TruncF64asF32
,
17174 triop( Iop_DivF64r32
, rm
, mkexpr( a3
), mkexpr( b3
) ) ) ) );
17177 binop( Iop_64HLtoV128
,
17178 binop( Iop_32HLto64
, mkexpr( res3
), mkexpr( res2
) ),
17179 binop( Iop_32HLto64
, mkexpr( res1
), mkexpr( res0
) ) ) );
17182 case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
17184 DIP("xvsqrtsp v%d,v%d\n", XT
, XB
);
17185 breakV128to4xF64( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
17186 /* Note: The native xvsqrtsp insruction does not always give the same precision
17187 * as what we get with Iop_SqrtF64. But it doesn't seem worthwhile to implement
17188 * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
17189 * to the actual instruction.
17193 unop( Iop_ReinterpF32asI32
,
17194 unop( Iop_TruncF64asF32
,
17195 binop(Iop_SqrtF64
, rm
, mkexpr( b0
) ) ) ) );
17197 unop( Iop_ReinterpF32asI32
,
17198 unop( Iop_TruncF64asF32
,
17199 binop(Iop_SqrtF64
, rm
, mkexpr( b1
) ) ) ) );
17201 unop( Iop_ReinterpF32asI32
,
17202 unop( Iop_TruncF64asF32
,
17203 binop(Iop_SqrtF64
, rm
, mkexpr( b2
) ) ) ) );
17205 unop( Iop_ReinterpF32asI32
,
17206 unop( Iop_TruncF64asF32
,
17207 binop(Iop_SqrtF64
, rm
, mkexpr( b3
) ) ) ) );
17210 binop( Iop_64HLtoV128
,
17211 binop( Iop_32HLto64
, mkexpr( res3
), mkexpr( res2
) ),
17212 binop( Iop_32HLto64
, mkexpr( res1
), mkexpr( res0
) ) ) );
17216 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
17217 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
17218 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
17219 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
17221 IRTemp t3
, t2
, t1
, t0
;
17224 const HChar
* oper_name
= NULL
;
17225 IROp mOp
= Iop_INVALID
;
17227 case 0x104: case 0x124:
17228 case 0x304: case 0x324:
17229 msp
= (opc2
& 0x0FF) == 0x024;
17230 mOp
= Iop_MAddF64r32
;
17231 oper_name
= "madd";
17234 case 0x144: case 0x164:
17235 case 0x344: case 0x364:
17236 msp
= (opc2
& 0x0FF) == 0x064;
17237 mOp
= Iop_MSubF64r32
;
17242 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
17246 case 0x304: case 0x324:
17247 case 0x344: case 0x364:
17255 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate
? "n" : "", oper_name
,
17256 msp
? "msp" : "asp", XT
, XA
, XB
);
17258 t3
= t2
= t1
= t0
= IRTemp_INVALID
;
17259 breakV128to4xF64( getVSReg( XA
), &a3
, &a2
, &a1
, &a0
);
17260 breakV128to4xF64( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
17261 breakV128to4xF64( getVSReg( XT
), &t3
, &t2
, &t1
, &t0
);
17264 unop( Iop_ReinterpF32asI32
,
17265 unop( Iop_TruncF64asF32
,
17269 mkexpr( msp
? t0
: b0
),
17270 mkexpr( msp
? b0
: t0
) ) ) ) );
17272 unop( Iop_ReinterpF32asI32
,
17273 unop( Iop_TruncF64asF32
,
17277 mkexpr( msp
? t1
: b1
),
17278 mkexpr( msp
? b1
: t1
) ) ) ) );
17280 unop( Iop_ReinterpF32asI32
,
17281 unop( Iop_TruncF64asF32
,
17285 mkexpr( msp
? t2
: b2
),
17286 mkexpr( msp
? b2
: t2
) ) ) ) );
17288 unop( Iop_ReinterpF32asI32
,
17289 unop( Iop_TruncF64asF32
,
17293 mkexpr( msp
? t3
: b3
),
17294 mkexpr( msp
? b3
: t3
) ) ) ) );
17297 binop( Iop_64HLtoV128
,
17298 binop( Iop_32HLto64
, mkexpr( negate
? getNegatedResult_32( res3
) : res3
),
17299 mkexpr( negate
? getNegatedResult_32( res2
) : res2
) ),
17300 binop( Iop_32HLto64
, mkexpr( negate
? getNegatedResult_32( res1
) : res1
),
17301 mkexpr( negate
? getNegatedResult_32( res0
) : res0
) ) ) );
17305 case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
17307 IRTemp flags0
= newTemp(Ity_I32
);
17308 IRTemp flags1
= newTemp(Ity_I32
);
17309 IRTemp flags2
= newTemp(Ity_I32
);
17310 IRTemp flags3
= newTemp(Ity_I32
);
17311 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
17312 IRTemp fe_flag0
, fg_flag0
, fe_flag1
, fg_flag1
;
17313 IRTemp fe_flag2
, fg_flag2
, fe_flag3
, fg_flag3
;
17314 fe_flag0
= fg_flag0
= fe_flag1
= fg_flag1
= IRTemp_INVALID
;
17315 fe_flag2
= fg_flag2
= fe_flag3
= fg_flag3
= IRTemp_INVALID
;
17316 DIP("xvtsqrtsp cr%d,v%d\n", crfD
, XB
);
17318 breakV128to4x32( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
17319 do_fp_tsqrt(b0
, True
/* single precision*/, &fe_flag0
, &fg_flag0
);
17320 do_fp_tsqrt(b1
, True
/* single precision*/, &fe_flag1
, &fg_flag1
);
17321 do_fp_tsqrt(b2
, True
/* single precision*/, &fe_flag2
, &fg_flag2
);
17322 do_fp_tsqrt(b3
, True
/* single precision*/, &fe_flag3
, &fg_flag3
);
17324 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
17325 * where fl_flag == 1 on ppc64.
17329 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17330 binop( Iop_Shl32
, mkexpr(fg_flag0
), mkU8( 2 ) ) ),
17331 binop( Iop_Shl32
, mkexpr(fe_flag0
), mkU8( 1 ) ) ) );
17334 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17335 binop( Iop_Shl32
, mkexpr(fg_flag1
), mkU8( 2 ) ) ),
17336 binop( Iop_Shl32
, mkexpr(fe_flag1
), mkU8( 1 ) ) ) );
17339 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17340 binop( Iop_Shl32
, mkexpr(fg_flag2
), mkU8( 2 ) ) ),
17341 binop( Iop_Shl32
, mkexpr(fe_flag2
), mkU8( 1 ) ) ) );
17344 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17345 binop( Iop_Shl32
, mkexpr(fg_flag3
), mkU8( 2 ) ) ),
17346 binop( Iop_Shl32
, mkexpr(fe_flag3
), mkU8( 1 ) ) ) );
17347 putGST_field( PPC_GST_CR
,
17354 mkexpr( flags3
) ) ) ),
17359 case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
17361 IRTemp flags0
= newTemp(Ity_I32
);
17362 IRTemp flags1
= newTemp(Ity_I32
);
17363 IRTemp flags2
= newTemp(Ity_I32
);
17364 IRTemp flags3
= newTemp(Ity_I32
);
17365 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
17366 IRTemp fe_flag0
, fg_flag0
, fe_flag1
, fg_flag1
;
17367 IRTemp fe_flag2
, fg_flag2
, fe_flag3
, fg_flag3
;
17368 fe_flag0
= fg_flag0
= fe_flag1
= fg_flag1
= IRTemp_INVALID
;
17369 fe_flag2
= fg_flag2
= fe_flag3
= fg_flag3
= IRTemp_INVALID
;
17370 DIP("xvtdivsp cr%d,v%d,v%d\n", crfD
, XA
, XB
);
17372 breakV128to4x32( getVSReg( XA
), &a3
, &a2
, &a1
, &a0
);
17373 breakV128to4x32( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
17374 _do_fp_tdiv(a0
, b0
, True
/* single precision*/, &fe_flag0
, &fg_flag0
);
17375 _do_fp_tdiv(a1
, b1
, True
/* single precision*/, &fe_flag1
, &fg_flag1
);
17376 _do_fp_tdiv(a2
, b2
, True
/* single precision*/, &fe_flag2
, &fg_flag2
);
17377 _do_fp_tdiv(a3
, b3
, True
/* single precision*/, &fe_flag3
, &fg_flag3
);
17379 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
17380 * where fl_flag == 1 on ppc64.
17384 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17385 binop( Iop_Shl32
, mkexpr(fg_flag0
), mkU8( 2 ) ) ),
17386 binop( Iop_Shl32
, mkexpr(fe_flag0
), mkU8( 1 ) ) ) );
17389 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17390 binop( Iop_Shl32
, mkexpr(fg_flag1
), mkU8( 2 ) ) ),
17391 binop( Iop_Shl32
, mkexpr(fe_flag1
), mkU8( 1 ) ) ) );
17394 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17395 binop( Iop_Shl32
, mkexpr(fg_flag2
), mkU8( 2 ) ) ),
17396 binop( Iop_Shl32
, mkexpr(fe_flag2
), mkU8( 1 ) ) ) );
17399 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
17400 binop( Iop_Shl32
, mkexpr(fg_flag3
), mkU8( 2 ) ) ),
17401 binop( Iop_Shl32
, mkexpr(fe_flag3
), mkU8( 1 ) ) ) );
17402 putGST_field( PPC_GST_CR
,
17409 mkexpr( flags3
) ) ) ),
17416 vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
17423 * Vector Population Count/bit matrix transpose
17426 dis_av_count_bitTranspose ( UInt theInstr
, UInt opc2
)
17428 UChar vRB_addr
= ifieldRegB(theInstr
);
17429 UChar vRT_addr
= ifieldRegDS(theInstr
);
17430 UChar opc1
= ifieldOPC( theInstr
);
17431 IRTemp vB
= newTemp(Ity_V128
);
17432 assign( vB
, getVReg(vRB_addr
));
17435 vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
17440 case 0x702: // vclzb
17441 DIP("vclzb v%d,v%d\n", vRT_addr
, vRB_addr
);
17442 putVReg( vRT_addr
, unop(Iop_Clz8x16
, mkexpr( vB
) ) );
17445 case 0x742: // vclzh
17446 DIP("vclzh v%d,v%d\n", vRT_addr
, vRB_addr
);
17447 putVReg( vRT_addr
, unop(Iop_Clz16x8
, mkexpr( vB
) ) );
17450 case 0x782: // vclzw
17451 DIP("vclzw v%d,v%d\n", vRT_addr
, vRB_addr
);
17452 putVReg( vRT_addr
, unop(Iop_Clz32x4
, mkexpr( vB
) ) );
17455 case 0x7C2: // vclzd
17456 DIP("vclzd v%d,v%d\n", vRT_addr
, vRB_addr
);
17457 putVReg( vRT_addr
, unop(Iop_Clz64x2
, mkexpr( vB
) ) );
17460 case 0x703: // vpopcntb
17462 /* Break vector into 32-bit words and do the population count
17463 * on byte in the words
17465 IRType ty
= Ity_I32
;
17466 IRTemp bits0_31
, bits32_63
, bits64_95
, bits96_127
;
17467 bits0_31
= bits32_63
= bits64_95
= bits96_127
= IRTemp_INVALID
;
17468 IRTemp cnt_bits0_31
, cnt_bits32_63
, cnt_bits64_95
, cnt_bits96_127
;
17469 cnt_bits0_31
= cnt_bits32_63
= cnt_bits64_95
= cnt_bits96_127
= IRTemp_INVALID
;
17471 DIP("vpopcntb v%d,v%d\n", vRT_addr
, vRB_addr
);
17472 breakV128to4x32(mkexpr( vB
), &bits96_127
, &bits64_95
, &bits32_63
, &bits0_31
);
17473 cnt_bits0_31
= gen_POPCOUNT(ty
, bits0_31
, BYTE
);
17474 cnt_bits32_63
= gen_POPCOUNT(ty
, bits32_63
, BYTE
);
17475 cnt_bits64_95
= gen_POPCOUNT(ty
, bits64_95
, BYTE
);
17476 cnt_bits96_127
= gen_POPCOUNT(ty
, bits96_127
, BYTE
);
17478 putVReg( vRT_addr
, mkV128from32(cnt_bits96_127
, cnt_bits64_95
,
17479 cnt_bits32_63
, cnt_bits0_31
) );
17483 case 0x743: // vpopcnth
17485 /* Break vector into 32-bit words and do the population count
17486 * for each half word
17488 IRType ty
= Ity_I32
;
17489 IRTemp bits0_31
, bits32_63
, bits64_95
, bits96_127
;
17490 bits0_31
= bits32_63
= bits64_95
= bits96_127
= IRTemp_INVALID
;
17491 IRTemp cnt_bits0_31
, cnt_bits32_63
, cnt_bits64_95
, cnt_bits96_127
;
17492 cnt_bits0_31
= cnt_bits32_63
= cnt_bits64_95
= cnt_bits96_127
= IRTemp_INVALID
;
17494 DIP("vpopcnth v%d,v%d\n", vRT_addr
, vRB_addr
);
17495 breakV128to4x32(mkexpr( vB
), &bits96_127
, &bits64_95
, &bits32_63
, &bits0_31
);
17497 cnt_bits0_31
= gen_POPCOUNT(ty
, bits0_31
, HWORD
);
17498 cnt_bits32_63
= gen_POPCOUNT(ty
, bits32_63
, HWORD
);
17499 cnt_bits64_95
= gen_POPCOUNT(ty
, bits64_95
, HWORD
);
17500 cnt_bits96_127
= gen_POPCOUNT(ty
, bits96_127
, HWORD
);
17502 putVReg( vRT_addr
, mkV128from32(cnt_bits96_127
, cnt_bits64_95
,
17503 cnt_bits32_63
, cnt_bits0_31
) );
17507 case 0x783: // vpopcntw
17509 /* Break vector into 32-bit words and do the population count
17512 IRType ty
= Ity_I32
;
17513 IRTemp bits0_31
, bits32_63
, bits64_95
, bits96_127
;
17514 bits0_31
= bits32_63
= bits64_95
= bits96_127
= IRTemp_INVALID
;
17515 IRTemp cnt_bits0_31
, cnt_bits32_63
, cnt_bits64_95
, cnt_bits96_127
;
17516 cnt_bits0_31
= cnt_bits32_63
= cnt_bits64_95
= cnt_bits96_127
= IRTemp_INVALID
;
17518 DIP("vpopcntw v%d,v%d\n", vRT_addr
, vRB_addr
);
17519 breakV128to4x32(mkexpr( vB
), &bits96_127
, &bits64_95
, &bits32_63
, &bits0_31
);
17521 cnt_bits0_31
= gen_POPCOUNT(ty
, bits0_31
, WORD
);
17522 cnt_bits32_63
= gen_POPCOUNT(ty
, bits32_63
, WORD
);
17523 cnt_bits64_95
= gen_POPCOUNT(ty
, bits64_95
, WORD
);
17524 cnt_bits96_127
= gen_POPCOUNT(ty
, bits96_127
, WORD
);
17526 putVReg( vRT_addr
, mkV128from32(cnt_bits96_127
, cnt_bits64_95
,
17527 cnt_bits32_63
, cnt_bits0_31
) );
17531 case 0x7C3: // vpopcntd
17534 /* Break vector into 64-bit double words and do the population
17535 count on each double word.
17537 IRType ty
= Ity_I64
;
17538 IRTemp bits0_63
= newTemp(Ity_I64
);
17539 IRTemp bits64_127
= newTemp(Ity_I64
);
17540 IRTemp cnt_bits0_63
= newTemp(Ity_I64
);
17541 IRTemp cnt_bits64_127
= newTemp(Ity_I64
);
17543 DIP("vpopcntd v%d,v%d\n", vRT_addr
, vRB_addr
);
17545 assign(bits0_63
, unop( Iop_V128to64
, mkexpr( vB
) ) );
17546 assign(bits64_127
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
17547 cnt_bits0_63
= gen_POPCOUNT(ty
, bits0_63
, DWORD
);
17548 cnt_bits64_127
= gen_POPCOUNT(ty
, bits64_127
, DWORD
);
17550 putVReg( vRT_addr
, binop( Iop_64HLtoV128
,
17551 mkexpr( cnt_bits64_127
),
17552 mkexpr( cnt_bits0_63
) ) );
17554 /* Break vector into 32-bit words and do the population count
17555 on each 32-bit word.
17557 IRTemp bits0_31
, bits32_63
, bits64_95
, bits96_127
;
17558 bits0_31
= bits32_63
= bits64_95
= bits96_127
= IRTemp_INVALID
;
17559 IRTemp cnt_bits0_63
= newTemp(Ity_I64
);
17560 IRTemp cnt_bits64_127
= newTemp(Ity_I64
);
17562 DIP("vpopcntd v%d,v%d\n", vRT_addr
, vRB_addr
);
17563 breakV128to4x32(mkexpr( vB
), &bits96_127
, &bits64_95
,
17564 &bits32_63
, &bits0_31
);
17566 cnt_bits0_63
= gen_vpopcntd_mode32(bits0_31
, bits32_63
);
17567 cnt_bits64_127
= gen_vpopcntd_mode32(bits64_95
, bits96_127
);
17569 putVReg( vRT_addr
, binop( Iop_64HLtoV128
,
17570 mkexpr( cnt_bits64_127
),
17571 mkexpr( cnt_bits0_63
) ) );
17576 case 0x50C: // vgbbd Vector Gather Bits by Bytes by Doubleword
17577 DIP("vgbbd v%d,v%d\n", vRT_addr
, vRB_addr
);
17578 putVReg( vRT_addr
, unop( Iop_PwBitMtxXpose64x2
, mkexpr( vB
) ) );
17581 case 0x5CC: // vbpermd Vector Bit Permute Doubleword
17583 UChar vRA_addr
= ifieldRegA( theInstr
);
17584 IRTemp vA
= newTemp( Ity_V128
);
17586 IRTemp index_dword_hi
[8]; // index in double word
17587 IRTemp index_dword_lo
[8];
17588 IRTemp index_dword_hi_valid
[8];
17589 IRTemp index_dword_lo_valid
[8];
17590 IRTemp pb_dword_hi
[8]; // permute bit
17591 IRTemp pb_dword_lo
[8];
17595 DIP("vbpermd v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
17597 tmp_hi
[0] = newTemp( Ity_I64
);
17598 tmp_lo
[0] = newTemp( Ity_I64
);
17600 assign( vA
, getVReg(vRA_addr
) );
17601 assign( tmp_hi
[0], mkU64( 0 ) );
17602 assign( tmp_lo
[0], mkU64( 0 ) );
17604 for (j
=0; j
<8; j
++) {
17605 index_dword_hi
[j
] = newTemp( Ity_I64
);
17606 index_dword_lo
[j
] = newTemp( Ity_I64
);
17607 index_dword_hi_valid
[j
] = newTemp( Ity_I64
);
17608 index_dword_lo_valid
[j
] = newTemp( Ity_I64
);
17609 pb_dword_hi
[j
] = newTemp( Ity_I64
);
17610 pb_dword_lo
[j
] = newTemp( Ity_I64
);
17611 tmp_hi
[j
+1] = newTemp( Ity_I64
);
17612 tmp_lo
[j
+1] = newTemp( Ity_I64
);
17614 assign( index_dword_hi
[j
],
17617 unop( Iop_V128HIto64
,
17619 mkU8( ( 7 - j
) * 8 ) ),
17622 assign( index_dword_lo
[j
],
17625 unop( Iop_V128to64
,
17627 mkU8( ( 7 - j
) * 8 ) ),
17630 assign( index_dword_hi_valid
[j
],
17632 binop( Iop_CmpLT64U
,
17633 mkexpr( index_dword_hi
[j
] ),
17636 assign( index_dword_lo_valid
[j
],
17638 binop( Iop_CmpLT64U
,
17639 mkexpr( index_dword_lo
[j
] ),
17641 assign( pb_dword_hi
[j
],
17644 unop( Iop_V128HIto64
,
17649 mkexpr( index_dword_hi
[j
] )
17653 assign( pb_dword_lo
[j
],
17656 unop( Iop_V128to64
,
17661 mkexpr( index_dword_lo
[j
] )
17665 assign( tmp_hi
[j
+1],
17668 mkexpr( index_dword_hi_valid
[j
] ),
17670 mkexpr( pb_dword_hi
[j
] ),
17672 mkexpr( tmp_hi
[j
] ) ) );
17674 assign( tmp_lo
[j
+1],
17677 mkexpr( index_dword_lo_valid
[j
] ),
17679 mkexpr( pb_dword_lo
[j
] ),
17681 mkexpr( tmp_lo
[j
] ) ) );
17685 binop( Iop_64HLtoV128
,
17686 mkexpr( tmp_hi
[8] ),
17687 mkexpr( tmp_lo
[8] ) ) );
17692 vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
17708 This helper function takes as input the IRExpr returned
17709 from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
17710 in IR form. This helper function converts it to PPC form.
17712 Map compare result from IR to PPC
17714 FP cmp result | PPC | IR
17715 --------------------------
17721 condcode = Shl(1, (~(ccIR>>5) & 2)
17722 | ((ccIR ^ (ccIR>>6)) & 1)
17725 get_fp_cmp_CR_val (IRExpr
* ccIR_expr
)
17727 IRTemp condcode
= newTemp( Ity_I32
);
17728 IRTemp ccIR
= newTemp( Ity_I32
);
17730 assign(ccIR
, ccIR_expr
);
17748 mkU32( 1 ) ) ) ) ) );
17753 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
17754 * following these special rules:
17755 * - The max/min of a QNaN and any value is that value
17756 * (When two QNaNs are being compared, the frA QNaN is the return value.)
17757 * - The max/min of any value and an SNaN is that SNaN converted to a QNaN
17758 * (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
17760 static IRExpr
* _get_maxmin_fp_NaN(IRTemp frA_I64
, IRTemp frB_I64
)
17762 IRTemp frA_isNaN
= newTemp(Ity_I1
);
17763 IRTemp frB_isNaN
= newTemp(Ity_I1
);
17764 IRTemp frA_isSNaN
= newTemp(Ity_I1
);
17765 IRTemp frB_isSNaN
= newTemp(Ity_I1
);
17766 IRTemp frA_isQNaN
= newTemp(Ity_I1
);
17767 IRTemp frB_isQNaN
= newTemp(Ity_I1
);
17769 assign( frA_isNaN
, is_NaN( Ity_I64
, frA_I64
) );
17770 assign( frB_isNaN
, is_NaN( Ity_I64
, frB_I64
) );
17771 // If operand is a NAN and bit 12 is '0', then it's an SNaN
17772 assign( frA_isSNaN
,
17773 mkAND1( mkexpr(frA_isNaN
),
17774 binop( Iop_CmpEQ32
,
17776 unop( Iop_64HIto32
, mkexpr( frA_I64
) ),
17777 mkU32( 0x00080000 ) ),
17779 assign( frB_isSNaN
,
17780 mkAND1( mkexpr(frB_isNaN
),
17781 binop( Iop_CmpEQ32
,
17783 unop( Iop_64HIto32
, mkexpr( frB_I64
) ),
17784 mkU32( 0x00080000 ) ),
17786 assign( frA_isQNaN
,
17787 mkAND1( mkexpr( frA_isNaN
), unop( Iop_Not1
, mkexpr( frA_isSNaN
) ) ) );
17788 assign( frB_isQNaN
,
17789 mkAND1( mkexpr( frB_isNaN
), unop( Iop_Not1
, mkexpr( frB_isSNaN
) ) ) );
17791 /* Based on the rules specified in the function prologue, the algorithm is as follows:
17792 * <<<<<<<<<>>>>>>>>>>>>>>>>>>
17794 * result = frA converted to QNaN
17795 * else if frB is a SNaN
17799 * result = frB converted to QNaN
17800 * else if frB is a QNaN
17802 * // One of frA or frB was a NaN in order for this function to be called, so
17803 * // if we get to this point, we KNOW that frA must be a QNaN.
17804 * else // frA is a QNaN
17806 * <<<<<<<<<>>>>>>>>>>>>>>>>>>
17809 #define SNAN_MASK 0x0008000000000000ULL
17812 IRExpr_ITE(mkexpr(frA_isSNaN
),
17813 /* then: result = frA converted to QNaN */
17814 binop(Iop_Or64
, mkexpr(frA_I64
), mkU64(SNAN_MASK
)),
17815 /* else: if frB is a SNaN */
17816 IRExpr_ITE(mkexpr(frB_isSNaN
),
17817 IRExpr_ITE(mkexpr(frA_isQNaN
),
17818 /* then: result = frA */
17820 /* else: result = frB converted to QNaN */
17821 binop(Iop_Or64
, mkexpr(frB_I64
),
17822 mkU64(SNAN_MASK
))),
17823 /* else: if frB is a QNaN */
17824 IRExpr_ITE(mkexpr(frB_isQNaN
),
17825 /* then: result = frA */
17827 /* else: frA is a QNaN, so result = frB */
17828 mkexpr(frB_I64
))));
17832 * Helper function for get_max_min_fp.
17834 static IRExpr
* _get_maxmin_fp_cmp(IRTemp src1
, IRTemp src2
, Bool isMin
)
17836 IRTemp src1cmpsrc2
= get_fp_cmp_CR_val( binop( Iop_CmpF64
,
17837 unop( Iop_ReinterpI64asF64
,
17839 unop( Iop_ReinterpI64asF64
,
17840 mkexpr( src2
) ) ) );
17842 return IRExpr_ITE( binop( Iop_CmpEQ32
,
17843 mkexpr( src1cmpsrc2
),
17844 mkU32( isMin
? PPC_CMP_LT
: PPC_CMP_GT
) ),
17845 /* then: use src1 */
17847 /* else: use src2 */
17852 * Helper function for "Maximum/Minimum Double Precision" operations.
17853 * Arguments: frA and frb are Ity_I64
17854 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
17856 static IRExpr
* get_max_min_fp(IRTemp frA_I64
, IRTemp frB_I64
, Bool isMin
)
17858 /* There are three special cases where get_fp_cmp_CR_val is not helpful
17859 * for ascertaining the maximum between two doubles:
17860 * 1. The max/min of +0 and -0 is +0.
17861 * 2. The max/min of a QNaN and any value is that value.
17862 * 3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
17863 * We perform the check for [+/-]0 here in this function and use the
17864 * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
17865 * to do the standard comparison function.
17867 IRTemp anyNaN
= newTemp(Ity_I1
);
17868 IRTemp frA_isZero
= newTemp(Ity_I1
);
17869 IRTemp frB_isZero
= newTemp(Ity_I1
);
17870 assign( frA_isZero
, is_Zero( Ity_I64
, frA_I64
) );
17871 assign( frB_isZero
, is_Zero( Ity_I64
, frB_I64
) );
17872 assign( anyNaN
, mkOR1( is_NaN( Ity_I64
, frA_I64
),
17873 is_NaN(Ity_I64
, frB_I64
) ) );
17874 #define MINUS_ZERO 0x8000000000000000ULL
17876 return IRExpr_ITE( /* If both arguments are zero . . . */
17877 mkAND1( mkexpr( frA_isZero
), mkexpr( frB_isZero
) ),
17878 /* then: if frA is -0 and isMin==True, return -0;
17879 * else if frA is +0 and isMin==False; return +0;
17880 * otherwise, simply return frB. */
17881 IRExpr_ITE( binop( Iop_CmpEQ32
,
17882 unop( Iop_64HIto32
,
17883 mkexpr( frA_I64
) ),
17884 mkU32( isMin
? 0x80000000 : 0 ) ),
17885 mkU64( isMin
? MINUS_ZERO
: 0ULL ),
17886 mkexpr( frB_I64
) ),
17887 /* else: check if either input is a NaN*/
17888 IRExpr_ITE( mkexpr( anyNaN
),
17889 /* then: use "NaN helper" */
17890 _get_maxmin_fp_NaN( frA_I64
, frB_I64
),
17891 /* else: use "comparison helper" */
17892 _get_maxmin_fp_cmp( frB_I64
, frA_I64
, isMin
) ));
17895 static const HChar
* _get_vsx_rdpi_suffix(UInt opc2
)
17897 switch (opc2
& 0x7F) {
17909 default: // Impossible to get here
17910 vex_printf("Unrecognized opcode %x\n", opc2
);
17911 vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
17916 * Helper function for vector/scalar double precision fp round to integer instructions.
17918 static IRExpr
* _do_vsx_fp_roundToInt(IRTemp frB_I64
, UInt opc2
)
17921 /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
17922 IRTemp frB
= newTemp(Ity_F64
);
17923 IRTemp frD
= newTemp(Ity_F64
);
17924 IRTemp intermediateResult
= newTemp(Ity_I64
);
17925 IRTemp is_SNAN
= newTemp(Ity_I1
);
17928 switch (opc2
& 0x7F) {
17930 rxpi_rm
= mkU32(Irrm_NegINF
);
17933 rxpi_rm
= mkU32(Irrm_PosINF
);
17936 rxpi_rm
= get_IR_roundingmode();
17939 rxpi_rm
= mkU32(Irrm_ZERO
);
17942 rxpi_rm
= mkU32(Irrm_NEAREST
);
17945 default: // Impossible to get here
17946 vex_printf("Unrecognized opcode %x\n", opc2
);
17947 vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
17949 assign(frB
, unop(Iop_ReinterpI64asF64
, mkexpr(frB_I64
)));
17950 assign( intermediateResult
,
17951 binop( Iop_F64toI64S
, rxpi_rm
,
17954 /* don't use the rounded integer if frB is outside -9e18..9e18 */
17955 /* F64 has only log10(2**52) significant digits anyway */
17956 /* need to preserve sign of zero */
17957 /* frD = (fabs(frB) > 9e18) ? frB :
17958 (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult */
17964 IRExpr_Const( IRConst_F64( 9e18
) ),
17965 unop( Iop_AbsF64
, mkexpr( frB
) ) ) ),
17969 binop( Iop_CmpNE32
,
17971 unop( Iop_64HIto32
,
17972 mkexpr( frB_I64
) ),
17977 binop( Iop_I64StoF64
,
17979 mkexpr( intermediateResult
) ) ) ),
17980 binop( Iop_I64StoF64
,
17982 mkexpr( intermediateResult
) )
17987 /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
17988 * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
17990 #define SNAN_MASK 0x0008000000000000ULL
17991 hi32
= unop( Iop_64HIto32
, mkexpr(frB_I64
) );
17993 mkAND1( is_NaN( Ity_I64
, frB_I64
),
17994 binop( Iop_CmpEQ32
,
17995 binop( Iop_And32
, hi32
, mkU32( 0x00080000 ) ),
17998 return IRExpr_ITE( mkexpr( is_SNAN
),
17999 unop( Iop_ReinterpI64asF64
,
18001 mkU64( SNAN_MASK
),
18002 mkexpr( frB_I64
) ) ),
18007 * Miscellaneous VSX vector instructions
18010 dis_vxv_misc ( UInt theInstr
, UInt opc2
)
18013 UChar opc1
= ifieldOPC( theInstr
);
18014 UChar XT
= ifieldRegXT( theInstr
);
18015 UChar XB
= ifieldRegXB( theInstr
);
18017 if (opc1
!= 0x3C) {
18018 vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
18023 case 0x1B4: // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
18024 case 0x194: // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
18025 // Double-Precision)
18027 IRExpr
* ieee_one
= IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
18028 IRExpr
* rm
= get_IR_roundingmode();
18029 IRTemp frB
= newTemp(Ity_I64
);
18030 IRTemp frB2
= newTemp(Ity_I64
);
18031 Bool redp
= opc2
== 0x1B4;
18032 IRTemp sqrtHi
= newTemp(Ity_F64
);
18033 IRTemp sqrtLo
= newTemp(Ity_F64
);
18034 assign(frB
, unop(Iop_V128HIto64
, getVSReg( XB
)));
18035 assign(frB2
, unop(Iop_V128to64
, getVSReg( XB
)));
18037 DIP("%s v%d,v%d\n", redp
? "xvredp" : "xvrsqrtedp", XT
, XB
);
18041 binop( Iop_SqrtF64
,
18043 unop( Iop_ReinterpI64asF64
, mkexpr( frB
) ) ) );
18045 binop( Iop_SqrtF64
,
18047 unop( Iop_ReinterpI64asF64
, mkexpr( frB2
) ) ) );
18050 binop( Iop_64HLtoV128
,
18051 unop( Iop_ReinterpF64asI64
,
18055 redp
? unop( Iop_ReinterpI64asF64
,
18057 : mkexpr( sqrtHi
) ) ),
18058 unop( Iop_ReinterpF64asI64
,
18062 redp
? unop( Iop_ReinterpI64asF64
,
18064 : mkexpr( sqrtLo
) ) ) ) );
18068 case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
18069 case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
18071 IRTemp b3
, b2
, b1
, b0
;
18072 IRTemp res0
= newTemp(Ity_I32
);
18073 IRTemp res1
= newTemp(Ity_I32
);
18074 IRTemp res2
= newTemp(Ity_I32
);
18075 IRTemp res3
= newTemp(Ity_I32
);
18076 IRTemp sqrt3
= newTemp(Ity_F64
);
18077 IRTemp sqrt2
= newTemp(Ity_F64
);
18078 IRTemp sqrt1
= newTemp(Ity_F64
);
18079 IRTemp sqrt0
= newTemp(Ity_F64
);
18080 IRExpr
* rm
= get_IR_roundingmode();
18081 Bool resp
= opc2
== 0x134;
18083 IRExpr
* ieee_one
= IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
18085 b3
= b2
= b1
= b0
= IRTemp_INVALID
;
18086 DIP("%s v%d,v%d\n", resp
? "xvresp" : "xvrsqrtesp", XT
, XB
);
18087 breakV128to4xF64( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
18090 assign( sqrt3
, binop( Iop_SqrtF64
, rm
, mkexpr( b3
) ) );
18091 assign( sqrt2
, binop( Iop_SqrtF64
, rm
, mkexpr( b2
) ) );
18092 assign( sqrt1
, binop( Iop_SqrtF64
, rm
, mkexpr( b1
) ) );
18093 assign( sqrt0
, binop( Iop_SqrtF64
, rm
, mkexpr( b0
) ) );
18097 unop( Iop_ReinterpF32asI32
,
18098 unop( Iop_TruncF64asF32
,
18099 triop( Iop_DivF64r32
,
18102 resp
? mkexpr( b0
) : mkexpr( sqrt0
) ) ) ) );
18104 unop( Iop_ReinterpF32asI32
,
18105 unop( Iop_TruncF64asF32
,
18106 triop( Iop_DivF64r32
,
18109 resp
? mkexpr( b1
) : mkexpr( sqrt1
) ) ) ) );
18111 unop( Iop_ReinterpF32asI32
,
18112 unop( Iop_TruncF64asF32
,
18113 triop( Iop_DivF64r32
,
18116 resp
? mkexpr( b2
) : mkexpr( sqrt2
) ) ) ) );
18118 unop( Iop_ReinterpF32asI32
,
18119 unop( Iop_TruncF64asF32
,
18120 triop( Iop_DivF64r32
,
18123 resp
? mkexpr( b3
) : mkexpr( sqrt3
) ) ) ) );
18125 binop( Iop_64HLtoV128
,
18126 binop( Iop_32HLto64
, mkexpr( res3
), mkexpr( res2
) ),
18127 binop( Iop_32HLto64
, mkexpr( res1
), mkexpr( res0
) ) ) );
18130 case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
18131 case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
18133 UChar XA
= ifieldRegXA( theInstr
);
18134 IRTemp a3
, a2
, a1
, a0
;
18135 IRTemp b3
, b2
, b1
, b0
;
18136 IRTemp res0
= newTemp( Ity_I32
);
18137 IRTemp res1
= newTemp( Ity_I32
);
18138 IRTemp res2
= newTemp( Ity_I32
);
18139 IRTemp res3
= newTemp( Ity_I32
);
18140 IRTemp a0_I64
= newTemp( Ity_I64
);
18141 IRTemp a1_I64
= newTemp( Ity_I64
);
18142 IRTemp a2_I64
= newTemp( Ity_I64
);
18143 IRTemp a3_I64
= newTemp( Ity_I64
);
18144 IRTemp b0_I64
= newTemp( Ity_I64
);
18145 IRTemp b1_I64
= newTemp( Ity_I64
);
18146 IRTemp b2_I64
= newTemp( Ity_I64
);
18147 IRTemp b3_I64
= newTemp( Ity_I64
);
18149 Bool isMin
= opc2
== 0x320 ? True
: False
;
18151 a3
= a2
= a1
= a0
= IRTemp_INVALID
;
18152 b3
= b2
= b1
= b0
= IRTemp_INVALID
;
18153 DIP("%s v%d,v%d v%d\n", isMin
? "xvminsp" : "xvmaxsp", XT
, XA
, XB
);
18154 breakV128to4xF64( getVSReg( XA
), &a3
, &a2
, &a1
, &a0
);
18155 breakV128to4xF64( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
18156 assign( a0_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( a0
) ) );
18157 assign( b0_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( b0
) ) );
18158 assign( a1_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( a1
) ) );
18159 assign( b1_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( b1
) ) );
18160 assign( a2_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( a2
) ) );
18161 assign( b2_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( b2
) ) );
18162 assign( a3_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( a3
) ) );
18163 assign( b3_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( b3
) ) );
18165 unop( Iop_ReinterpF32asI32
,
18166 unop( Iop_TruncF64asF32
,
18167 unop( Iop_ReinterpI64asF64
,
18168 get_max_min_fp( a0_I64
, b0_I64
, isMin
) ) ) ) );
18170 unop( Iop_ReinterpF32asI32
,
18171 unop( Iop_TruncF64asF32
,
18172 unop( Iop_ReinterpI64asF64
,
18173 get_max_min_fp( a1_I64
, b1_I64
, isMin
) ) ) ) );
18175 unop( Iop_ReinterpF32asI32
,
18176 unop( Iop_TruncF64asF32
,
18177 unop( Iop_ReinterpI64asF64
,
18178 get_max_min_fp( a2_I64
, b2_I64
, isMin
) ) ) ) );
18180 unop( Iop_ReinterpF32asI32
,
18181 unop( Iop_TruncF64asF32
,
18182 unop( Iop_ReinterpI64asF64
,
18183 get_max_min_fp( a3_I64
, b3_I64
, isMin
) ) ) ) );
18185 binop( Iop_64HLtoV128
,
18186 binop( Iop_32HLto64
, mkexpr( res3
), mkexpr( res2
) ),
18187 binop( Iop_32HLto64
, mkexpr( res1
), mkexpr( res0
) ) ) );
18190 case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
18191 case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
18193 UChar XA
= ifieldRegXA( theInstr
);
18194 IRTemp frA
= newTemp(Ity_I64
);
18195 IRTemp frB
= newTemp(Ity_I64
);
18196 IRTemp frA2
= newTemp(Ity_I64
);
18197 IRTemp frB2
= newTemp(Ity_I64
);
18198 Bool isMin
= opc2
== 0x3A0 ? True
: False
;
18200 assign(frA
, unop(Iop_V128HIto64
, getVSReg( XA
)));
18201 assign(frB
, unop(Iop_V128HIto64
, getVSReg( XB
)));
18202 assign(frA2
, unop(Iop_V128to64
, getVSReg( XA
)));
18203 assign(frB2
, unop(Iop_V128to64
, getVSReg( XB
)));
18204 DIP("%s v%d,v%d v%d\n", isMin
? "xvmindp" : "xvmaxdp", XT
, XA
, XB
);
18205 putVSReg( XT
, binop( Iop_64HLtoV128
, get_max_min_fp(frA
, frB
, isMin
), get_max_min_fp(frA2
, frB2
, isMin
) ) );
18209 case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
18211 UChar XA
= ifieldRegXA( theInstr
);
18212 IRTemp frA
= newTemp(Ity_I64
);
18213 IRTemp frB
= newTemp(Ity_I64
);
18214 IRTemp frA2
= newTemp(Ity_I64
);
18215 IRTemp frB2
= newTemp(Ity_I64
);
18216 assign(frA
, unop(Iop_V128HIto64
, getVSReg( XA
)));
18217 assign(frB
, unop(Iop_V128HIto64
, getVSReg( XB
)));
18218 assign(frA2
, unop(Iop_V128to64
, getVSReg( XA
)));
18219 assign(frB2
, unop(Iop_V128to64
, getVSReg( XB
)));
18221 DIP("xvcpsgndp v%d,v%d,v%d\n", XT
, XA
, XB
);
18223 binop( Iop_64HLtoV128
,
18227 mkU64( SIGN_BIT
) ),
18230 mkU64( SIGN_MASK
) ) ),
18234 mkU64( SIGN_BIT
) ),
18237 mkU64( SIGN_MASK
) ) ) ) );
18240 case 0x340: // xvcpsgnsp
18242 UChar XA
= ifieldRegXA( theInstr
);
18243 IRTemp a3_I64
, a2_I64
, a1_I64
, a0_I64
;
18244 IRTemp b3_I64
, b2_I64
, b1_I64
, b0_I64
;
18245 IRTemp resHi
= newTemp(Ity_I64
);
18246 IRTemp resLo
= newTemp(Ity_I64
);
18248 a3_I64
= a2_I64
= a1_I64
= a0_I64
= IRTemp_INVALID
;
18249 b3_I64
= b2_I64
= b1_I64
= b0_I64
= IRTemp_INVALID
;
18250 DIP("xvcpsgnsp v%d,v%d v%d\n",XT
, XA
, XB
);
18251 breakV128to4x64U( getVSReg( XA
), &a3_I64
, &a2_I64
, &a1_I64
, &a0_I64
);
18252 breakV128to4x64U( getVSReg( XB
), &b3_I64
, &b2_I64
, &b1_I64
, &b0_I64
);
18255 binop( Iop_32HLto64
,
18258 unop(Iop_64to32
, mkexpr( a3_I64
) ),
18259 mkU32( SIGN_BIT32
) ),
18261 unop(Iop_64to32
, mkexpr( b3_I64
) ),
18262 mkU32( SIGN_MASK32
) ) ),
18266 unop(Iop_64to32
, mkexpr( a2_I64
) ),
18267 mkU32( SIGN_BIT32
) ),
18269 unop(Iop_64to32
, mkexpr( b2_I64
) ),
18270 mkU32( SIGN_MASK32
) ) ) ) );
18272 binop( Iop_32HLto64
,
18275 unop(Iop_64to32
, mkexpr( a1_I64
) ),
18276 mkU32( SIGN_BIT32
) ),
18278 unop(Iop_64to32
, mkexpr( b1_I64
) ),
18279 mkU32( SIGN_MASK32
) ) ),
18283 unop(Iop_64to32
, mkexpr( a0_I64
) ),
18284 mkU32( SIGN_BIT32
) ),
18286 unop(Iop_64to32
, mkexpr( b0_I64
) ),
18287 mkU32( SIGN_MASK32
) ) ) ) );
18288 putVSReg( XT
, binop( Iop_64HLtoV128
, mkexpr( resHi
), mkexpr( resLo
) ) );
18291 case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
18292 case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
18294 IRTemp frB
= newTemp(Ity_F64
);
18295 IRTemp frB2
= newTemp(Ity_F64
);
18296 IRTemp abs_resultHi
= newTemp(Ity_F64
);
18297 IRTemp abs_resultLo
= newTemp(Ity_F64
);
18298 Bool make_negative
= (opc2
== 0x3D2) ? True
: False
;
18299 assign(frB
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XB
))));
18300 assign(frB2
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, getVSReg(XB
))));
18302 DIP("xv%sabsdp v%d,v%d\n", make_negative
? "n" : "", XT
, XB
);
18303 if (make_negative
) {
18304 assign(abs_resultHi
, unop( Iop_NegF64
, unop( Iop_AbsF64
, mkexpr( frB
) ) ) );
18305 assign(abs_resultLo
, unop( Iop_NegF64
, unop( Iop_AbsF64
, mkexpr( frB2
) ) ) );
18308 assign(abs_resultHi
, unop( Iop_AbsF64
, mkexpr( frB
) ) );
18309 assign(abs_resultLo
, unop( Iop_AbsF64
, mkexpr( frB2
) ) );
18311 putVSReg( XT
, binop( Iop_64HLtoV128
,
18312 unop( Iop_ReinterpF64asI64
, mkexpr( abs_resultHi
) ),
18313 unop( Iop_ReinterpF64asI64
, mkexpr( abs_resultLo
) ) ) );
18316 case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
18317 case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
18320 * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
18321 * of xvabssp, there has not been an abs(sp) type of instruction. But since emulation
18322 * of this function is so easy using shifts, I choose to emulate this instruction that
18323 * way versus a native instruction method of implementation.
18325 Bool make_negative
= (opc2
== 0x352) ? True
: False
;
18326 IRTemp shiftVector
= newTemp(Ity_V128
);
18327 IRTemp absVal_vector
= newTemp(Ity_V128
);
18328 assign( shiftVector
,
18329 binop( Iop_64HLtoV128
,
18330 binop( Iop_32HLto64
, mkU32( 1 ), mkU32( 1 ) ),
18331 binop( Iop_32HLto64
, mkU32( 1 ), mkU32( 1 ) ) ) );
18332 assign( absVal_vector
,
18333 binop( Iop_Shr32x4
,
18334 binop( Iop_Shl32x4
,
18336 mkexpr( shiftVector
) ),
18337 mkexpr( shiftVector
) ) );
18338 if (make_negative
) {
18339 IRTemp signBit_vector
= newTemp(Ity_V128
);
18340 assign( signBit_vector
,
18341 binop( Iop_64HLtoV128
,
18342 binop( Iop_32HLto64
,
18343 mkU32( 0x80000000 ),
18344 mkU32( 0x80000000 ) ),
18345 binop( Iop_32HLto64
,
18346 mkU32( 0x80000000 ),
18347 mkU32( 0x80000000 ) ) ) );
18350 mkexpr( absVal_vector
),
18351 mkexpr( signBit_vector
) ) );
18353 putVSReg( XT
, mkexpr( absVal_vector
) );
18357 case 0x372: // xvnegsp (VSX Vector Negate Single-Precision)
18359 IRTemp B0
= newTemp(Ity_I32
);
18360 IRTemp B1
= newTemp(Ity_I32
);
18361 IRTemp B2
= newTemp(Ity_I32
);
18362 IRTemp B3
= newTemp(Ity_I32
);
18364 DIP("xvnegsp v%d,v%d\n", XT
, XB
);
18366 /* Don't support NegF32, so just XOR the sign bit in the int value */
18367 assign(B0
, unop( Iop_64HIto32
,
18368 unop( Iop_V128HIto64
, getVSReg( XB
) ) ) );
18369 assign(B1
, unop( Iop_64to32
,
18370 unop( Iop_V128HIto64
, getVSReg( XB
) ) ) );
18371 assign(B2
, unop( Iop_64HIto32
,
18372 unop( Iop_V128to64
, getVSReg( XB
) ) ) );
18373 assign(B3
, unop( Iop_64to32
,
18374 unop( Iop_V128to64
, getVSReg( XB
) ) ) );
18377 binop( Iop_64HLtoV128
,
18378 binop( Iop_32HLto64
,
18379 binop( Iop_Xor32
, mkexpr( B0
), mkU32( 0x80000000 ) ),
18380 binop( Iop_Xor32
, mkexpr( B1
), mkU32( 0x80000000 ) ) ),
18381 binop( Iop_32HLto64
,
18382 binop( Iop_Xor32
, mkexpr( B2
), mkU32( 0x80000000 ) ),
18383 binop( Iop_Xor32
, mkexpr( B3
), mkU32( 0x80000000 ) ) ) ) );
18386 case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
18388 IRTemp frB
= newTemp(Ity_F64
);
18389 IRTemp frB2
= newTemp(Ity_F64
);
18390 assign(frB
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XB
))));
18391 assign(frB2
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, getVSReg(XB
))));
18392 DIP("xvnegdp v%d,v%d\n", XT
, XB
);
18394 binop( Iop_64HLtoV128
,
18395 unop( Iop_ReinterpF64asI64
,
18396 unop( Iop_NegF64
, mkexpr( frB
) ) ),
18397 unop( Iop_ReinterpF64asI64
,
18398 unop( Iop_NegF64
, mkexpr( frB2
) ) ) ) );
18401 case 0x192: // xvrdpi (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
18402 case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
18403 case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
18404 case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
18405 case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
18407 IRTemp frBHi_I64
= newTemp(Ity_I64
);
18408 IRTemp frBLo_I64
= newTemp(Ity_I64
);
18409 IRExpr
* frD_fp_roundHi
= NULL
;
18410 IRExpr
* frD_fp_roundLo
= NULL
;
18412 assign( frBHi_I64
, unop( Iop_V128HIto64
, getVSReg( XB
) ) );
18413 frD_fp_roundHi
= _do_vsx_fp_roundToInt(frBHi_I64
, opc2
);
18414 assign( frBLo_I64
, unop( Iop_V128to64
, getVSReg( XB
) ) );
18415 frD_fp_roundLo
= _do_vsx_fp_roundToInt(frBLo_I64
, opc2
);
18417 DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2
), XT
, XB
);
18419 binop( Iop_64HLtoV128
,
18420 unop( Iop_ReinterpF64asI64
, frD_fp_roundHi
),
18421 unop( Iop_ReinterpF64asI64
, frD_fp_roundLo
) ) );
18424 case 0x112: // xvrspi (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
18425 case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
18426 case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
18427 case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
18428 case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
18430 const HChar
* insn_suffix
= NULL
;
18432 if (opc2
!= 0x156) {
18433 // Use pre-defined IRop's for vrfi{m|n|p|z}
18437 op
= Iop_RoundF32x4_RN
;
18441 op
= Iop_RoundF32x4_RM
;
18445 op
= Iop_RoundF32x4_RP
;
18449 op
= Iop_RoundF32x4_RZ
;
18453 vex_printf("Unrecognized opcode %x\n", opc2
);
18454 vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
18456 DIP("xvrspi%s v%d,v%d\n", insn_suffix
, XT
, XB
);
18457 putVSReg( XT
, unop( op
, getVSReg(XB
) ) );
18459 // Handle xvrspic. Unfortunately there is no corresponding "vfric" instruction.
18460 IRExpr
* frD_fp_roundb3
, * frD_fp_roundb2
, * frD_fp_roundb1
, * frD_fp_roundb0
;
18461 IRTemp b3_F64
, b2_F64
, b1_F64
, b0_F64
;
18462 IRTemp b3_I64
= newTemp(Ity_I64
);
18463 IRTemp b2_I64
= newTemp(Ity_I64
);
18464 IRTemp b1_I64
= newTemp(Ity_I64
);
18465 IRTemp b0_I64
= newTemp(Ity_I64
);
18467 b3_F64
= b2_F64
= b1_F64
= b0_F64
= IRTemp_INVALID
;
18468 frD_fp_roundb3
= frD_fp_roundb2
= frD_fp_roundb1
= frD_fp_roundb0
= NULL
;
18469 breakV128to4xF64( getVSReg(XB
), &b3_F64
, &b2_F64
, &b1_F64
, &b0_F64
);
18470 assign(b3_I64
, unop(Iop_ReinterpF64asI64
, mkexpr(b3_F64
)));
18471 assign(b2_I64
, unop(Iop_ReinterpF64asI64
, mkexpr(b2_F64
)));
18472 assign(b1_I64
, unop(Iop_ReinterpF64asI64
, mkexpr(b1_F64
)));
18473 assign(b0_I64
, unop(Iop_ReinterpF64asI64
, mkexpr(b0_F64
)));
18474 frD_fp_roundb3
= unop(Iop_TruncF64asF32
,
18475 _do_vsx_fp_roundToInt(b3_I64
, opc2
));
18476 frD_fp_roundb2
= unop(Iop_TruncF64asF32
,
18477 _do_vsx_fp_roundToInt(b2_I64
, opc2
));
18478 frD_fp_roundb1
= unop(Iop_TruncF64asF32
,
18479 _do_vsx_fp_roundToInt(b1_I64
, opc2
));
18480 frD_fp_roundb0
= unop(Iop_TruncF64asF32
,
18481 _do_vsx_fp_roundToInt(b0_I64
, opc2
));
18482 DIP("xvrspic v%d,v%d\n", XT
, XB
);
18484 binop( Iop_64HLtoV128
,
18485 binop( Iop_32HLto64
,
18486 unop( Iop_ReinterpF32asI32
, frD_fp_roundb3
),
18487 unop( Iop_ReinterpF32asI32
, frD_fp_roundb2
) ),
18488 binop( Iop_32HLto64
,
18489 unop( Iop_ReinterpF32asI32
, frD_fp_roundb1
),
18490 unop( Iop_ReinterpF32asI32
, frD_fp_roundb0
) ) ) );
18496 vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
18504 * VSX Scalar Floating Point Arithmetic Instructions
18507 dis_vxs_arith ( UInt theInstr
, UInt opc2
)
18510 UChar opc1
= ifieldOPC( theInstr
);
18511 UChar XT
= ifieldRegXT( theInstr
);
18512 UChar XA
= ifieldRegXA( theInstr
);
18513 UChar XB
= ifieldRegXB( theInstr
);
18514 IRExpr
* rm
= get_IR_roundingmode();
18515 IRTemp frA
= newTemp(Ity_F64
);
18516 IRTemp frB
= newTemp(Ity_F64
);
18518 if (opc1
!= 0x3C) {
18519 vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
18523 assign(frA
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XA
))));
18524 assign(frB
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XB
))));
18526 /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
18527 * of VSX[XT] are undefined after the operation; therefore, we can simply set
18528 * element to zero where it makes sense to do so.
18531 case 0x000: // xsaddsp (VSX Scalar Add Single-Precision)
18532 DIP("xsaddsp v%d,v%d,v%d\n", XT
, XA
, XB
);
18533 putVSReg( XT
, binop( Iop_64HLtoV128
,
18534 unop( Iop_ReinterpF64asI64
,
18535 binop( Iop_RoundF64toF32
, rm
,
18536 triop( Iop_AddF64
, rm
,
18538 mkexpr( frB
) ) ) ),
18541 case 0x020: // xssubsp (VSX Scalar Subtract Single-Precision)
18542 DIP("xssubsp v%d,v%d,v%d\n", XT
, XA
, XB
);
18543 putVSReg( XT
, binop( Iop_64HLtoV128
,
18544 unop( Iop_ReinterpF64asI64
,
18545 binop( Iop_RoundF64toF32
, rm
,
18546 triop( Iop_SubF64
, rm
,
18548 mkexpr( frB
) ) ) ),
18551 case 0x080: // xsadddp (VSX scalar add double-precision)
18552 DIP("xsadddp v%d,v%d,v%d\n", XT
, XA
, XB
);
18553 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
18554 triop( Iop_AddF64
, rm
,
18559 case 0x060: // xsdivsp (VSX scalar divide single-precision)
18560 DIP("xsdivsp v%d,v%d,v%d\n", XT
, XA
, XB
);
18561 putVSReg( XT
, binop( Iop_64HLtoV128
,
18562 unop( Iop_ReinterpF64asI64
,
18563 binop( Iop_RoundF64toF32
, rm
,
18564 triop( Iop_DivF64
, rm
,
18566 mkexpr( frB
) ) ) ),
18569 case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
18570 DIP("xsdivdp v%d,v%d,v%d\n", XT
, XA
, XB
);
18571 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
18572 triop( Iop_DivF64
, rm
,
18577 case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
18578 * single-precision)
18581 IRTemp frT
= newTemp(Ity_F64
);
18582 Bool mdp
= opc2
== 0x024;
18583 DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
18584 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
18585 getVSReg( XT
) ) ) );
18587 binop( Iop_64HLtoV128
,
18588 unop( Iop_ReinterpF64asI64
,
18589 binop( Iop_RoundF64toF32
, rm
,
18590 qop( Iop_MAddF64
, rm
,
18592 mkexpr( mdp
? frT
: frB
),
18593 mkexpr( mdp
? frB
: frT
) ) ) ),
18597 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
18599 IRTemp frT
= newTemp(Ity_F64
);
18600 Bool mdp
= opc2
== 0x0A4;
18601 DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
18602 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
18603 getVSReg( XT
) ) ) );
18604 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
18605 qop( Iop_MAddF64
, rm
,
18607 mkexpr( mdp
? frT
: frB
),
18608 mkexpr( mdp
? frB
: frT
) ) ),
18612 case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
18613 * multiply-subtract single-precision)
18616 IRTemp frT
= newTemp(Ity_F64
);
18617 Bool mdp
= opc2
== 0x064;
18618 DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
18619 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
18620 getVSReg( XT
) ) ) );
18622 binop( Iop_64HLtoV128
,
18623 unop( Iop_ReinterpF64asI64
,
18624 binop( Iop_RoundF64toF32
, rm
,
18625 qop( Iop_MSubF64
, rm
,
18627 mkexpr( mdp
? frT
: frB
),
18628 mkexpr( mdp
? frB
: frT
) ) ) ),
18632 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
18634 IRTemp frT
= newTemp(Ity_F64
);
18635 Bool mdp
= opc2
== 0x0E4;
18636 DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
18637 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
18638 getVSReg( XT
) ) ) );
18639 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
18640 qop( Iop_MSubF64
, rm
,
18642 mkexpr( mdp
? frT
: frB
),
18643 mkexpr( mdp
? frB
: frT
) ) ),
18647 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
18649 /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
18650 * of fnmadd and use pretty much the same code. However, that code has a bug in the
18651 * way it blindly negates the signbit, even if the floating point result is a NaN.
18652 * So, the TODO is to fix fnmadd (which I'll do in a different patch).
18653 * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
18654 * bit for NaN result.
18656 Bool mdp
= opc2
== 0x2A4;
18657 IRTemp frT
= newTemp(Ity_F64
);
18658 IRTemp maddResult
= newTemp(Ity_I64
);
18660 DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
18661 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
18662 getVSReg( XT
) ) ) );
18663 assign( maddResult
, unop( Iop_ReinterpF64asI64
, qop( Iop_MAddF64
, rm
,
18665 mkexpr( mdp
? frT
: frB
),
18666 mkexpr( mdp
? frB
: frT
) ) ) );
18668 putVSReg( XT
, binop( Iop_64HLtoV128
, mkexpr( getNegatedResult(maddResult
) ),
18672 case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
18673 * multiply-add single-precision)
18676 Bool mdp
= opc2
== 0x224;
18677 IRTemp frT
= newTemp(Ity_F64
);
18678 IRTemp maddResult
= newTemp(Ity_I64
);
18680 DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
18681 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
18682 getVSReg( XT
) ) ) );
18683 assign( maddResult
,
18684 unop( Iop_ReinterpF64asI64
,
18685 binop( Iop_RoundF64toF32
, rm
,
18686 qop( Iop_MAddF64
, rm
,
18688 mkexpr( mdp
? frT
: frB
),
18689 mkexpr( mdp
? frB
: frT
) ) ) ) );
18691 putVSReg( XT
, binop( Iop_64HLtoV128
,
18692 mkexpr( getNegatedResult(maddResult
) ),
18696 case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
18697 * Multiply-Subtract Single-Precision)
18700 IRTemp frT
= newTemp(Ity_F64
);
18701 Bool mdp
= opc2
== 0x264;
18702 IRTemp msubResult
= newTemp(Ity_I64
);
18704 DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
18705 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
18706 getVSReg( XT
) ) ) );
18707 assign( msubResult
,
18708 unop( Iop_ReinterpF64asI64
,
18709 binop( Iop_RoundF64toF32
, rm
,
18710 qop( Iop_MSubF64
, rm
,
18712 mkexpr( mdp
? frT
: frB
),
18713 mkexpr( mdp
? frB
: frT
) ) ) ) );
18715 putVSReg( XT
, binop( Iop_64HLtoV128
,
18716 mkexpr( getNegatedResult(msubResult
) ),
18722 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
18724 IRTemp frT
= newTemp(Ity_F64
);
18725 Bool mdp
= opc2
== 0x2E4;
18726 IRTemp msubResult
= newTemp(Ity_I64
);
18728 DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
18729 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
18730 getVSReg( XT
) ) ) );
18731 assign(msubResult
, unop( Iop_ReinterpF64asI64
,
18735 mkexpr( mdp
? frT
: frB
),
18736 mkexpr( mdp
? frB
: frT
) ) ));
18738 putVSReg( XT
, binop( Iop_64HLtoV128
, mkexpr( getNegatedResult(msubResult
) ), mkU64( 0 ) ) );
18743 case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
18744 DIP("xsmulsp v%d,v%d,v%d\n", XT
, XA
, XB
);
18745 putVSReg( XT
, binop( Iop_64HLtoV128
,
18746 unop( Iop_ReinterpF64asI64
,
18747 binop( Iop_RoundF64toF32
, rm
,
18748 triop( Iop_MulF64
, rm
,
18750 mkexpr( frB
) ) ) ),
18754 case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
18755 DIP("xsmuldp v%d,v%d,v%d\n", XT
, XA
, XB
);
18756 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
18757 triop( Iop_MulF64
, rm
,
18762 case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
18763 DIP("xssubdp v%d,v%d,v%d\n", XT
, XA
, XB
);
18764 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
18765 triop( Iop_SubF64
, rm
,
18771 case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
18772 DIP("xssqrtsp v%d,v%d\n", XT
, XB
);
18774 binop( Iop_64HLtoV128
,
18775 unop( Iop_ReinterpF64asI64
,
18776 binop( Iop_RoundF64toF32
, rm
,
18777 binop( Iop_SqrtF64
, rm
,
18778 mkexpr( frB
) ) ) ),
18782 case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
18783 DIP("xssqrtdp v%d,v%d\n", XT
, XB
);
18784 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
18785 binop( Iop_SqrtF64
, rm
,
18790 case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
18792 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
18793 IRTemp frA_I64
= newTemp(Ity_I64
);
18794 IRTemp frB_I64
= newTemp(Ity_I64
);
18795 DIP("xstdivdp crf%d,v%d,v%d\n", crfD
, XA
, XB
);
18796 assign( frA_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( frA
) ) );
18797 assign( frB_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( frB
) ) );
18798 putGST_field( PPC_GST_CR
, do_fp_tdiv(frA_I64
, frB_I64
), crfD
);
18801 case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
18803 IRTemp frB_I64
= newTemp(Ity_I64
);
18804 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
18805 IRTemp flags
= newTemp(Ity_I32
);
18806 IRTemp fe_flag
, fg_flag
;
18807 fe_flag
= fg_flag
= IRTemp_INVALID
;
18808 DIP("xstsqrtdp v%d,v%d\n", XT
, XB
);
18809 assign( frB_I64
, unop(Iop_V128HIto64
, getVSReg( XB
)) );
18810 do_fp_tsqrt(frB_I64
, False
/*not single precision*/, &fe_flag
, &fg_flag
);
18811 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
18812 * where fl_flag == 1 on ppc64.
18816 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
18817 binop( Iop_Shl32
, mkexpr(fg_flag
), mkU8( 2 ) ) ),
18818 binop( Iop_Shl32
, mkexpr(fe_flag
), mkU8( 1 ) ) ) );
18819 putGST_field( PPC_GST_CR
, mkexpr(flags
), crfD
);
18824 vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
18833 * VSX Floating Point Compare Instructions
18836 dis_vx_cmp( UInt theInstr
, UInt opc2
)
18838 /* XX3-Form and XX2-Form */
18839 UChar opc1
= ifieldOPC( theInstr
);
18840 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
18842 UChar XA
= ifieldRegXA ( theInstr
);
18843 UChar XB
= ifieldRegXB ( theInstr
);
18844 IRTemp frA
= newTemp(Ity_F64
);
18845 IRTemp frB
= newTemp(Ity_F64
);
18847 if (opc1
!= 0x3C) {
18848 vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
18852 assign(frA
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XA
))));
18853 assign(frB
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XB
))));
18855 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
18856 /* Note: Differences between xscmpudp and xscmpodp are only in
18857 * exception flag settings, which aren't supported anyway. */
18858 DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2
== 0x08c ? "u" : "o",
18860 ccPPC32
= get_fp_cmp_CR_val( binop(Iop_CmpF64
, mkexpr(frA
), mkexpr(frB
)));
18861 putGST_field( PPC_GST_CR
, mkexpr(ccPPC32
), crfD
);
18862 putFPCC( mkexpr( ccPPC32
) );
18866 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
18873 do_vvec_fp_cmp ( IRTemp vA
, IRTemp vB
, UChar XT
, UChar flag_rC
,
18874 ppc_cmp_t cmp_type
)
18876 IRTemp frA_hi
= newTemp(Ity_F64
);
18877 IRTemp frB_hi
= newTemp(Ity_F64
);
18878 IRTemp frA_lo
= newTemp(Ity_F64
);
18879 IRTemp frB_lo
= newTemp(Ity_F64
);
18880 IRTemp ccPPC32
= newTemp(Ity_I32
);
18884 IRTemp hiResult
= newTemp(Ity_I64
);
18885 IRTemp loResult
= newTemp(Ity_I64
);
18886 IRTemp hiEQlo
= newTemp(Ity_I1
);
18887 IRTemp all_elem_true
= newTemp(Ity_I32
);
18888 IRTemp all_elem_false
= newTemp(Ity_I32
);
18890 assign(frA_hi
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, mkexpr( vA
))));
18891 assign(frB_hi
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, mkexpr( vB
))));
18892 assign(frA_lo
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, mkexpr( vA
))));
18893 assign(frB_lo
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, mkexpr( vB
))));
18895 ccIR_hi
= get_fp_cmp_CR_val( binop( Iop_CmpF64
,
18897 mkexpr( frB_hi
) ) );
18898 ccIR_lo
= get_fp_cmp_CR_val( binop( Iop_CmpF64
,
18900 mkexpr( frB_lo
) ) );
18902 if (cmp_type
!= PPC_CMP_GE
) {
18905 binop( Iop_CmpEQ32
, mkexpr( ccIR_hi
), mkU32( cmp_type
) ) ) );
18908 binop( Iop_CmpEQ32
, mkexpr( ccIR_lo
), mkU32( cmp_type
) ) ) );
18910 // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
18911 // the other element compare may return "2" (for "equal to").
18912 IRTemp lo_GE
= newTemp(Ity_I1
);
18913 IRTemp hi_GE
= newTemp(Ity_I1
);
18915 assign(hi_GE
, mkOR1( binop( Iop_CmpEQ32
, mkexpr( ccIR_hi
), mkU32( 2 ) ),
18916 binop( Iop_CmpEQ32
, mkexpr( ccIR_hi
), mkU32( 4 ) ) ) );
18917 assign( hiResult
,unop( Iop_1Sto64
, mkexpr( hi_GE
) ) );
18919 assign(lo_GE
, mkOR1( binop( Iop_CmpEQ32
, mkexpr( ccIR_lo
), mkU32( 2 ) ),
18920 binop( Iop_CmpEQ32
, mkexpr( ccIR_lo
), mkU32( 4 ) ) ) );
18921 assign( loResult
, unop( Iop_1Sto64
, mkexpr( lo_GE
) ) );
18924 // The [hi/lo]Result will be all 1's or all 0's. We just look at the lower word.
18926 binop( Iop_CmpEQ32
,
18927 unop( Iop_64to32
, mkexpr( hiResult
) ),
18928 unop( Iop_64to32
, mkexpr( loResult
) ) ) );
18930 binop( Iop_64HLtoV128
, mkexpr( hiResult
), mkexpr( loResult
) ) );
18932 assign( all_elem_true
,
18934 mkAND1( mkexpr( hiEQlo
),
18935 binop( Iop_CmpEQ32
,
18936 mkU32( 0xffffffff ),
18938 mkexpr( hiResult
) ) ) ) ) );
18940 assign( all_elem_false
,
18942 mkAND1( mkexpr( hiEQlo
),
18943 binop( Iop_CmpEQ32
,
18946 mkexpr( hiResult
) ) ) ) ) );
18949 binop( Iop_Shl32
, mkexpr( all_elem_false
), mkU8( 1 ) ),
18950 binop( Iop_Shl32
, mkexpr( all_elem_true
), mkU8( 3 ) ) ) );
18953 putGST_field( PPC_GST_CR
, mkexpr(ccPPC32
), 6 );
18958 * VSX Vector Compare Instructions
18961 dis_vvec_cmp( UInt theInstr
, UInt opc2
)
18964 UChar opc1
= ifieldOPC( theInstr
);
18965 UChar XT
= ifieldRegXT ( theInstr
);
18966 UChar XA
= ifieldRegXA ( theInstr
);
18967 UChar XB
= ifieldRegXB ( theInstr
);
18968 UChar flag_rC
= ifieldBIT10(theInstr
);
18969 IRTemp vA
= newTemp( Ity_V128
);
18970 IRTemp vB
= newTemp( Ity_V128
);
18972 if (opc1
!= 0x3C) {
18973 vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
18977 assign( vA
, getVSReg( XA
) );
18978 assign( vB
, getVSReg( XB
) );
18981 case 0x18C: // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
18983 DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
18985 do_vvec_fp_cmp(vA
, vB
, XT
, flag_rC
, PPC_CMP_EQ
);
18989 case 0x1CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
18991 DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
18993 do_vvec_fp_cmp(vA
, vB
, XT
, flag_rC
, PPC_CMP_GE
);
18997 case 0x1AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
18999 DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
19001 do_vvec_fp_cmp(vA
, vB
, XT
, flag_rC
, PPC_CMP_GT
);
19005 case 0x10C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
19007 IRTemp vD
= newTemp(Ity_V128
);
19009 DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
19011 assign( vD
, binop(Iop_CmpEQ32Fx4
, mkexpr(vA
), mkexpr(vB
)) );
19012 putVSReg( XT
, mkexpr(vD
) );
19014 set_AV_CR6( mkexpr(vD
), True
);
19019 case 0x14C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
19021 IRTemp vD
= newTemp(Ity_V128
);
19023 DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
19025 assign( vD
, binop(Iop_CmpGE32Fx4
, mkexpr(vA
), mkexpr(vB
)) );
19026 putVSReg( XT
, mkexpr(vD
) );
19028 set_AV_CR6( mkexpr(vD
), True
);
19033 case 0x12C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
19035 IRTemp vD
= newTemp(Ity_V128
);
19037 DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
19039 assign( vD
, binop(Iop_CmpGT32Fx4
, mkexpr(vA
), mkexpr(vB
)) );
19040 putVSReg( XT
, mkexpr(vD
) );
19042 set_AV_CR6( mkexpr(vD
), True
);
19048 vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
19054 * Miscellaneous VSX Scalar Instructions
19057 dis_vxs_misc( UInt theInstr
, const VexAbiInfo
* vbi
, UInt opc2
,
19058 int allow_isa_3_0
)
19060 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
19061 /* XX3-Form and XX2-Form */
19062 UChar opc1
= ifieldOPC( theInstr
);
19063 UChar XT
= ifieldRegXT ( theInstr
);
19064 UChar XA
= ifieldRegXA ( theInstr
);
19065 UChar XB
= ifieldRegXB ( theInstr
);
19066 IRTemp vA
= newTemp( Ity_V128
);
19067 IRTemp vB
= newTemp( Ity_V128
);
19069 if (opc1
!= 0x3C) {
19070 vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
19074 assign( vA
, getVSReg( XA
) );
19075 assign( vB
, getVSReg( XB
) );
19077 /* For all the VSX move instructions, the contents of doubleword element 1
19078 * of VSX[XT] are undefined after the operation; therefore, we can simply
19079 * move the entire array element where it makes sense to do so.
19081 if (( opc2
== 0x168 ) && ( IFIELD( theInstr
, 19, 2 ) == 0 ) )
19083 /* Special case of XX1-Form with immediate value
19084 * xxspltib (VSX Vector Splat Immediate Byte)
19086 UInt uim
= IFIELD( theInstr
, 11, 8 );
19087 UInt word_value
= ( uim
<< 24 ) | ( uim
<< 16 ) | ( uim
<< 8 ) | uim
;
19089 DIP("xxspltib v%u,%u\n", (UInt
)XT
, uim
);
19090 putVSReg(XT
, binop( Iop_64HLtoV128
,
19091 binop( Iop_32HLto64
,
19092 mkU32( word_value
),
19093 mkU32( word_value
) ),
19094 binop( Iop_32HLto64
,
19095 mkU32( word_value
),
19096 mkU32( word_value
) ) ) );
19101 case 0x0ec: // xscmpexpdp (VSX Scalar Compare Exponents Double-Precision)
19103 /* Compare 64-bit data, 128-bit layout:
19104 src1[0:63] is double word, src1[64:127] is unused
19105 src2[0:63] is double word, src2[64:127] is unused
19107 IRExpr
*bit4
, *bit5
, *bit6
, *bit7
;
19108 UInt BF
= IFIELD( theInstr
, 23, 3 );
19109 IRTemp eq_lt_gt
= newTemp( Ity_I32
);
19110 IRTemp CC
= newTemp( Ity_I32
);
19111 IRTemp vA_hi
= newTemp( Ity_I64
);
19112 IRTemp vB_hi
= newTemp( Ity_I64
);
19113 IRExpr
*mask
= mkU64( 0x7FF0000000000000 );
19115 DIP("xscmpexpdp %u,v%u,v%u\n", BF
, XA
, XB
);
19117 assign( vA_hi
, unop( Iop_V128HIto64
, mkexpr( vA
) ) );
19118 assign( vB_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
19120 /* A exp < B exp */
19121 bit4
= binop( Iop_CmpLT64U
,
19128 /* A exp > B exp */
19129 bit5
= binop( Iop_CmpLT64U
,
19137 bit6
= binop( Iop_CmpEQ64
,
19145 /* exp A or exp B is NaN */
19146 bit7
= mkOR1( is_NaN( Ity_I64
, vA_hi
),
19147 is_NaN( Ity_I64
, vB_hi
) );
19149 assign( eq_lt_gt
, binop( Iop_Or32
,
19151 unop( Iop_1Uto32
, bit4
),
19155 unop( Iop_1Uto32
, bit5
),
19158 unop( Iop_1Uto32
, bit6
),
19160 assign(CC
, binop( Iop_Or32
,
19162 mkexpr( eq_lt_gt
) ,
19163 unop( Iop_Not32
, unop( Iop_1Sto32
, bit7
) ) ),
19164 unop( Iop_1Uto32
, bit7
) ) );
19166 putGST_field( PPC_GST_CR
, mkexpr( CC
), BF
);
19167 putFPCC( mkexpr( CC
) );
19172 case 0x14A: // xxextractuw (VSX Vector Extract Unsigned Word)
19174 UInt uim
= IFIELD( theInstr
, 16, 4 );
19176 DIP("xxextractuw v%u,v%u,%u\n", (UInt
)XT
, (UInt
)XB
, uim
);
19179 binop( Iop_ShlV128
,
19180 binop( Iop_AndV128
,
19181 binop( Iop_ShrV128
,
19183 mkU8( ( 12 - uim
) * 8 ) ),
19184 binop(Iop_64HLtoV128
,
19186 mkU64( 0xFFFFFFFF ) ) ),
19187 mkU8( ( 32*2 ) ) ) );
19190 case 0x16A: // xxinsertw (VSX Vector insert Word)
19192 UInt uim
= IFIELD( theInstr
, 16, 4 );
19193 IRTemp vT
= newTemp( Ity_V128
);
19194 IRTemp tmp
= newTemp( Ity_V128
);
19196 DIP("xxinsertw v%u,v%u,%u\n", (UInt
)XT
, (UInt
)XB
, uim
);
19198 assign( vT
, getVSReg( XT
) );
19199 assign( tmp
, binop( Iop_AndV128
,
19202 binop( Iop_ShlV128
,
19203 binop( Iop_64HLtoV128
,
19205 mkU64( 0xFFFFFFFF) ),
19206 mkU8( ( 12 - uim
) * 8 ) ) ) ) );
19210 binop( Iop_ShlV128
,
19211 binop( Iop_AndV128
,
19212 binop( Iop_ShrV128
,
19215 binop( Iop_64HLtoV128
,
19217 mkU64( 0xFFFFFFFF ) ) ),
19218 mkU8( ( 12 - uim
) * 8 ) ),
19223 case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
19225 /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
19226 IRTemp absVal
= newTemp(Ity_V128
);
19227 if (host_endness
== VexEndnessLE
) {
19228 IRTemp hi64
= newTemp(Ity_I64
);
19229 IRTemp lo64
= newTemp(Ity_I64
);
19230 assign( hi64
, unop( Iop_V128HIto64
, mkexpr(vB
) ) );
19231 assign( lo64
, unop( Iop_V128to64
, mkexpr(vB
) ) );
19232 assign( absVal
, binop( Iop_64HLtoV128
,
19233 binop( Iop_And64
, mkexpr(hi64
),
19234 mkU64(VG_PPC_SIGN_MASK
) ),
19237 assign(absVal
, binop(Iop_ShrV128
,
19238 binop(Iop_ShlV128
, mkexpr(vB
),
19239 mkU8(1)), mkU8(1)));
19241 DIP("xsabsdp v%u,v%u\n", XT
, XB
);
19242 putVSReg(XT
, mkexpr(absVal
));
19246 case 0x2b6: // xsxexpdp (VSX Scalar Extract Exponent Double-Precision)
19247 // xsxsigdp (VSX Scalar Extract Significand Doulbe-Precision)
19248 // xsvhpdp (VSX Scalar Convert Half-Precision format
19249 // to Double-Precision format)
19250 // xscvdphp (VSX Scalar round & convert Double-precision
19251 // format to Half-precision format)
19253 IRTemp rT
= newTemp( Ity_I64
);
19254 UInt inst_select
= IFIELD( theInstr
, 16, 5);
19256 if (inst_select
== 0) {
19257 DIP("xsxexpd %u,v%u\n", (UInt
)XT
, (UInt
)XB
);
19259 assign( rT
, binop( Iop_Shr64
,
19261 unop( Iop_V128HIto64
, mkexpr( vB
) ),
19262 mkU64( 0x7FF0000000000000 ) ),
19264 } else if (inst_select
== 1) {
19266 IRTemp tmp
= newTemp(Ity_I64
);
19268 DIP("xsxsigdp v%u,v%u\n", (UInt
)XT
, (UInt
)XB
);
19270 assign( tmp
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
19272 /* Value is normal if it isn't infinite, zero or denormalized */
19273 normal
= mkNOT1( mkOR1(
19274 mkOR1( is_NaN( Ity_I64
, tmp
),
19275 is_Inf( Ity_I64
, tmp
) ),
19276 mkOR1( is_Zero( Ity_I64
, tmp
),
19277 is_Denorm( Ity_I64
, tmp
) ) ) );
19279 assign( rT
, binop( Iop_Or64
,
19282 mkU64( 0xFFFFFFFFFFFFF ) ),
19284 unop( Iop_1Uto64
, normal
),
19286 putIReg( XT
, mkexpr( rT
) );
19288 } else if (inst_select
== 16) {
19289 IRTemp result
= newTemp( Ity_V128
);
19290 IRTemp value
= newTemp( Ity_I64
);
19291 /* Note: PPC only coverts the 16-bit value in the upper 64-bits
19292 * of the source V128 to a 64-bit value stored in the upper
19293 * 64-bits of the V128 result. The contents of the lower 64-bits
19297 DIP("xscvhpdp v%u, v%u\n", (UInt
)XT
, (UInt
)XB
);
19298 assign( result
, unop( Iop_F16toF64x2
, mkexpr( vB
) ) );
19300 putVSReg( XT
, mkexpr( result
) );
19302 assign( value
, unop( Iop_V128HIto64
, mkexpr( result
) ) );
19303 generate_store_FPRF( Ity_I64
, value
, vbi
);
19306 } else if (inst_select
== 17) { // xscvdphp
19307 IRTemp value
= newTemp( Ity_I32
);
19308 IRTemp result
= newTemp( Ity_V128
);
19309 /* Note: PPC only coverts the 64-bit value in the upper 64-bits of
19310 * the V128 and stores the 16-bit result in the upper word of the
19311 * V128 result. The contents of the lower 64-bits is undefined.
19313 DIP("xscvdphp v%u, v%u\n", (UInt
)XT
, (UInt
)XB
);
19314 assign( result
, unop( Iop_F64toF16x2_DEP
, mkexpr( vB
) ) );
19315 assign( value
, unop( Iop_64to32
, unop( Iop_V128HIto64
,
19316 mkexpr( result
) ) ) );
19317 putVSReg( XT
, mkexpr( result
) );
19318 generate_store_FPRF( Ity_I16
, value
, vbi
);
19322 vex_printf( "dis_vxv_scalar_extract_exp_sig invalid inst_select (ppc)(opc2)\n" );
19323 vex_printf("inst_select = %u\n", inst_select
);
19329 case 0x254: // xststdcsp (VSX Scalar Test Data Class Single-Precision)
19330 case 0x2D4: // xststdcdp (VSX Scalar Test Data Class Double-Precision)
19332 /* These instructions only differ in that the single precision
19333 instruction, xststdcsp, has the additional constraint on the
19334 denormal test that the exponent be greater then zero and
19335 less then 0x381. */
19336 IRTemp vB_hi
= newTemp( Ity_I64
);
19337 UInt BF
= IFIELD( theInstr
, 23, 3 );
19338 UInt DCMX_mask
= IFIELD( theInstr
, 16, 7 );
19339 IRTemp NaN
= newTemp( Ity_I64
);
19340 IRTemp inf
= newTemp( Ity_I64
);
19341 IRTemp zero
= newTemp( Ity_I64
);
19342 IRTemp dnorm
= newTemp( Ity_I64
);
19343 IRTemp pos
= newTemp( Ity_I64
);
19344 IRTemp not_sp
= newTemp( Ity_I64
);
19345 IRTemp DCM
= newTemp( Ity_I64
);
19346 IRTemp CC
= newTemp( Ity_I64
);
19347 IRTemp exponent
= newTemp( Ity_I64
);
19348 IRTemp tmp
= newTemp( Ity_I64
);
19350 assign( vB_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
19352 assign( pos
, unop( Iop_1Uto64
,
19353 binop( Iop_CmpEQ64
,
19359 assign( NaN
, unop( Iop_1Uto64
, is_NaN( Ity_I64
, vB_hi
) ) );
19360 assign( inf
, unop( Iop_1Uto64
, is_Inf( Ity_I64
, vB_hi
) ) );
19361 assign( zero
, unop( Iop_1Uto64
, is_Zero( Ity_I64
, vB_hi
) ) );
19363 if (opc2
== 0x254) {
19364 DIP("xststdcsp %u,v%u,%u\n", BF
, (UInt
)XB
, DCMX_mask
);
19366 /* The least significant bit of the CC is set to 1 if the double
19367 precision value is not representable as a single precision
19368 value. The spec says the bit is set if:
19369 src != convert_SPtoDP(convert_DPtoSP(src))
19372 unop( Iop_ReinterpF64asI64
,
19373 unop( Iop_F32toF64
,
19374 unop( Iop_TruncF64asF32
,
19375 unop( Iop_ReinterpI64asF64
,
19376 mkexpr( vB_hi
) ) ) ) ) );
19377 assign( not_sp
, unop( Iop_1Uto64
,
19378 mkNOT1( binop( Iop_CmpEQ64
,
19380 mkexpr( tmp
) ) ) ) );
19385 mkU64( 0x7ff0000000000000 ) ),
19387 assign( dnorm
, unop( Iop_1Uto64
,
19388 mkOR1( is_Denorm( Ity_I64
, vB_hi
),
19389 mkAND1( binop( Iop_CmpLT64U
,
19390 mkexpr( exponent
),
19392 binop( Iop_CmpNE64
,
19393 mkexpr( exponent
),
19394 mkU64( 0x0 ) ) ) ) ) );
19397 DIP("xststdcdp %u,v%u,%u\n", BF
, (UInt
)XB
, DCMX_mask
);
19398 assign( not_sp
, mkU64( 0 ) );
19399 assign( dnorm
, unop( Iop_1Uto64
, is_Denorm( Ity_I64
, vB_hi
) ) );
19402 assign( DCM
, create_DCM( Ity_I64
, NaN
, inf
, zero
, dnorm
, pos
) );
19405 binop( Iop_And64
, /* vB sign bit */
19413 binop( Iop_CmpNE64
,
19416 mkU64( DCMX_mask
) ),
19419 mkexpr( not_sp
) ) ) );
19420 putGST_field( PPC_GST_CR
, unop( Iop_64to32
, mkexpr( CC
) ), BF
);
19421 putFPCC( unop( Iop_64to32
, mkexpr( CC
) ) );
19425 case 0x2C0: // xscpsgndp
19427 /* Scalar copy sign double-precision */
19428 IRTemp vecA_signed
= newTemp(Ity_I64
);
19429 IRTemp vecB_unsigned
= newTemp(Ity_I64
);
19430 IRTemp vec_result
= newTemp(Ity_V128
);
19431 DIP("xscpsgndp v%d,v%d v%d\n", XT
, XA
, XB
);
19432 assign( vecA_signed
, binop( Iop_And64
,
19433 unop( Iop_V128HIto64
,
19435 mkU64(~VG_PPC_SIGN_MASK
) ) );
19436 assign( vecB_unsigned
, binop( Iop_And64
,
19437 unop( Iop_V128HIto64
,
19439 mkU64(VG_PPC_SIGN_MASK
) ) );
19440 assign( vec_result
, binop( Iop_64HLtoV128
,
19442 mkexpr(vecA_signed
),
19443 mkexpr(vecB_unsigned
) ),
19445 putVSReg(XT
, mkexpr(vec_result
));
19448 case 0x2D2: // xsnabsdp
19450 /* Scalar negative absolute value double-precision */
19451 IRTemp BHi_signed
= newTemp(Ity_I64
);
19452 DIP("xsnabsdp v%d,v%d\n", XT
, XB
);
19453 assign( BHi_signed
, binop( Iop_Or64
,
19454 unop( Iop_V128HIto64
,
19456 mkU64(~VG_PPC_SIGN_MASK
) ) );
19457 putVSReg(XT
, binop( Iop_64HLtoV128
,
19458 mkexpr(BHi_signed
), mkU64(0x0ULL
) ) );
19461 case 0x2F2: // xsnegdp
19463 /* Scalar negate double-precision */
19464 IRTemp BHi_signed
= newTemp(Ity_I64
);
19465 IRTemp BHi_unsigned
= newTemp(Ity_I64
);
19466 IRTemp BHi_negated
= newTemp(Ity_I64
);
19467 IRTemp BHi_negated_signbit
= newTemp(Ity_I1
);
19468 IRTemp vec_result
= newTemp(Ity_V128
);
19469 DIP("xsnabsdp v%d,v%d\n", XT
, XB
);
19470 assign( BHi_signed
, unop( Iop_V128HIto64
, mkexpr(vB
) ) );
19471 assign( BHi_unsigned
, binop( Iop_And64
, mkexpr(BHi_signed
),
19472 mkU64(VG_PPC_SIGN_MASK
) ) );
19473 assign( BHi_negated_signbit
,
19477 unop( Iop_64HIto32
,
19479 mkexpr(BHi_signed
),
19480 mkU64(~VG_PPC_SIGN_MASK
) )
19483 assign( BHi_negated
,
19485 binop( Iop_32HLto64
,
19488 mkexpr(BHi_negated_signbit
) ),
19491 mkexpr(BHi_unsigned
) ) );
19492 assign( vec_result
, binop( Iop_64HLtoV128
, mkexpr(BHi_negated
),
19494 putVSReg( XT
, mkexpr(vec_result
));
19497 case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
19498 case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
19500 IRTemp frA
= newTemp(Ity_I64
);
19501 IRTemp frB
= newTemp(Ity_I64
);
19502 Bool isMin
= opc2
== 0x2A0 ? True
: False
;
19503 DIP("%s v%d,v%d v%d\n", isMin
? "xsmaxdp" : "xsmindp", XT
, XA
, XB
);
19505 assign(frA
, unop(Iop_V128HIto64
, mkexpr( vA
)));
19506 assign(frB
, unop(Iop_V128HIto64
, mkexpr( vB
)));
19507 putVSReg( XT
, binop( Iop_64HLtoV128
, get_max_min_fp(frA
, frB
, isMin
), mkU64( 0 ) ) );
19511 case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
19512 case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
19513 case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
19514 case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
19515 case 0x092: // xsrdpi (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
19517 IRTemp frB_I64
= newTemp(Ity_I64
);
19518 IRExpr
* frD_fp_round
= NULL
;
19520 assign(frB_I64
, unop(Iop_V128HIto64
, mkexpr( vB
)));
19521 frD_fp_round
= _do_vsx_fp_roundToInt(frB_I64
, opc2
);
19523 DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2
), XT
, XB
);
19525 binop( Iop_64HLtoV128
,
19526 unop( Iop_ReinterpF64asI64
, frD_fp_round
),
19530 case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
19531 case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
19532 * single-Precision)
19535 IRTemp frB
= newTemp(Ity_F64
);
19536 IRTemp sqrt
= newTemp(Ity_F64
);
19537 IRExpr
* ieee_one
= IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
19538 IRExpr
* rm
= get_IR_roundingmode();
19539 Bool redp
= opc2
== 0x034;
19540 DIP("%s v%d,v%d\n", redp
? "xsresp" : "xsrsqrtesp", XT
,
19544 unop( Iop_ReinterpI64asF64
,
19545 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
19549 binop( Iop_SqrtF64
,
19553 binop( Iop_64HLtoV128
,
19554 unop( Iop_ReinterpF64asI64
,
19555 binop( Iop_RoundF64toF32
, rm
,
19559 redp
? mkexpr( frB
) :
19560 mkexpr( sqrt
) ) ) ),
19565 case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
19566 case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
19569 IRTemp frB
= newTemp(Ity_F64
);
19570 IRTemp sqrt
= newTemp(Ity_F64
);
19571 IRExpr
* ieee_one
= IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
19572 IRExpr
* rm
= get_IR_roundingmode();
19573 Bool redp
= opc2
== 0x0B4;
19574 DIP("%s v%d,v%d\n", redp
? "xsredp" : "xsrsqrtedp", XT
, XB
);
19576 unop( Iop_ReinterpI64asF64
,
19577 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
19581 binop( Iop_SqrtF64
,
19585 binop( Iop_64HLtoV128
,
19586 unop( Iop_ReinterpF64asI64
,
19590 redp
? mkexpr( frB
) : mkexpr( sqrt
) ) ),
19595 case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
19597 IRTemp frB
= newTemp(Ity_F64
);
19598 IRExpr
* rm
= get_IR_roundingmode();
19599 DIP("xsrsp v%d, v%d\n", XT
, XB
);
19601 unop( Iop_ReinterpI64asF64
,
19602 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
19604 putVSReg( XT
, binop( Iop_64HLtoV128
,
19605 unop( Iop_ReinterpF64asI64
,
19606 binop( Iop_RoundF64toF32
,
19613 case 0x354: // xvtstdcsp (VSX Test Data Class Single-Precision)
19615 UInt DX_mask
= IFIELD( theInstr
, 16, 5 );
19616 UInt DC_mask
= IFIELD( theInstr
, 6, 1 );
19617 UInt DM_mask
= IFIELD( theInstr
, 2, 1 );
19618 UInt DCMX_mask
= (DC_mask
<< 6) | (DM_mask
<< 5) | DX_mask
;
19620 IRTemp match_value
[4];
19630 DIP("xvtstdcsp v%u,v%u,%u\n", (UInt
)XT
, (UInt
)XB
, DCMX_mask
);
19632 for (i
= 0; i
< 4; i
++) {
19633 NaN
[i
] = newTemp(Ity_I32
);
19634 inf
[i
] = newTemp(Ity_I32
);
19635 pos
[i
] = newTemp(Ity_I32
);
19636 DCM
[i
] = newTemp(Ity_I32
);
19637 zero
[i
] = newTemp(Ity_I32
);
19638 dnorm
[i
] = newTemp(Ity_I32
);
19640 value
[i
] = newTemp(Ity_I32
);
19641 match_value
[i
] = newTemp(Ity_I32
);
19645 unop( Iop_V128to64
,
19646 binop( Iop_AndV128
,
19647 binop( Iop_ShrV128
,
19649 mkU8( (3-i
)*32 ) ),
19650 binop( Iop_64HLtoV128
,
19652 mkU64( 0xFFFFFFFF ) ) ) ) ) );
19654 assign( pos
[i
], unop( Iop_1Uto32
,
19655 binop( Iop_CmpEQ32
,
19657 mkexpr( value
[i
] ),
19661 assign( NaN
[i
], unop( Iop_1Uto32
, is_NaN( Ity_I32
, value
[i
] ) ));
19662 assign( inf
[i
], unop( Iop_1Uto32
, is_Inf( Ity_I32
, value
[i
] ) ) );
19663 assign( zero
[i
], unop( Iop_1Uto32
, is_Zero( Ity_I32
, value
[i
] ) ) );
19665 assign( dnorm
[i
], unop( Iop_1Uto32
, is_Denorm( Ity_I32
,
19667 assign( DCM
[i
], create_DCM( Ity_I32
, NaN
[i
], inf
[i
], zero
[i
],
19668 dnorm
[i
], pos
[i
] ) );
19670 assign( match_value
[i
],
19672 binop( Iop_CmpNE32
,
19674 mkU32( DCMX_mask
),
19675 mkexpr( DCM
[i
] ) ),
19679 putVSReg( XT
, binop( Iop_64HLtoV128
,
19680 binop( Iop_32HLto64
,
19681 mkexpr( match_value
[0] ),
19682 mkexpr( match_value
[1] ) ),
19683 binop( Iop_32HLto64
,
19684 mkexpr( match_value
[2] ),
19685 mkexpr( match_value
[3] ) ) ) );
19689 case 0x360: // xviexpsp (VSX Vector Insert Exponent Single-Precision)
19695 IRExpr
*sign
[4], *expr
[4], *fract
[4];
19697 DIP("xviexpsp v%d,v%d\n", XT
, XB
);
19698 new_XT
[0] = newTemp(Ity_V128
);
19699 assign( new_XT
[0], binop( Iop_64HLtoV128
,
19703 for (i
= 0; i
< 4; i
++) {
19704 A_value
[i
] = newTemp(Ity_I32
);
19705 B_value
[i
] = newTemp(Ity_I32
);
19707 assign( A_value
[i
],
19709 unop( Iop_V128to64
,
19710 binop( Iop_AndV128
,
19711 binop( Iop_ShrV128
,
19713 mkU8( (3-i
)*32 ) ),
19714 binop( Iop_64HLtoV128
,
19716 mkU64( 0xFFFFFFFF ) ) ) ) ) );
19717 assign( B_value
[i
],
19719 unop( Iop_V128to64
,
19720 binop( Iop_AndV128
,
19721 binop( Iop_ShrV128
,
19723 mkU8( (3-i
)*32 ) ),
19724 binop( Iop_64HLtoV128
,
19726 mkU64( 0xFFFFFFFF ) ) ) ) ) );
19728 sign
[i
] = binop( Iop_And32
, mkexpr( A_value
[i
] ),
19729 mkU32( 0x80000000 ) );
19730 expr
[i
] = binop( Iop_Shl32
,
19731 binop( Iop_And32
, mkexpr( B_value
[i
] ),
19734 fract
[i
] = binop( Iop_And32
, mkexpr( A_value
[i
] ),
19735 mkU32( 0x007FFFFF ) );
19737 new_XT
[i
+1] = newTemp(Ity_V128
);
19738 assign( new_XT
[i
+1],
19740 binop( Iop_ShlV128
,
19741 binop( Iop_64HLtoV128
,
19743 binop( Iop_32HLto64
,
19750 mkU8( (3-i
)*32 ) ),
19751 mkexpr( new_XT
[i
] ) ) );
19753 putVSReg( XT
, mkexpr( new_XT
[4] ) );
19757 case 0x396: // xsiexpdp (VSX Scalar Insert Exponent Double-Precision)
19759 IRExpr
*sign
, *expr
, *fract
;
19760 UChar rA_addr
= ifieldRegA(theInstr
);
19761 UChar rB_addr
= ifieldRegB(theInstr
);
19762 IRTemp rA
= newTemp( Ity_I64
);
19763 IRTemp rB
= newTemp( Ity_I64
);
19765 DIP("xsiexpdp v%u,%u,%u\n", (UInt
)XT
, (UInt
)rA_addr
, (UInt
)rB_addr
);
19766 assign( rA
, getIReg(rA_addr
));
19767 assign( rB
, getIReg(rB_addr
));
19769 sign
= binop( Iop_And64
, mkexpr( rA
), mkU64( 0x8000000000000000 ) );
19770 expr
= binop( Iop_Shl64
,
19771 binop( Iop_And64
, mkexpr( rB
), mkU64( 0x7FF ) ),
19773 fract
= binop( Iop_And64
, mkexpr( rA
), mkU64( 0x000FFFFFFFFFFFFF ) );
19775 putVSReg( XT
, binop( Iop_64HLtoV128
,
19777 binop( Iop_Or64
, sign
, expr
),
19783 case 0x3B6: // xvxexpdp (VSX Vector Extract Exponent Double-Precision)
19784 // xvxsigdp (VSX Vector Extract Significand Double-Precision)
19786 // xvxexpsp (VSX Vector Extract Exponent Single-Precision)
19787 // xvxsigsp (VSX Vector Extract Significand Single-Precision)
19791 // xvcvhpsp (VSX Vector Convert Half-Precision format to Single-Precision format)
19792 // xvcvsphp (VSX Vector round and convert Single-Precision format to Half-Precision format)
19794 UInt inst_select
= IFIELD( theInstr
, 16, 5);
19796 if (inst_select
== 0) {
19797 DIP("xvxexpdp v%d,v%d\n", XT
, XB
);
19799 putVSReg( XT
, binop( Iop_ShrV128
,
19800 binop( Iop_AndV128
,
19802 binop( Iop_64HLtoV128
,
19803 mkU64( 0x7FF0000000000000 ),
19804 mkU64( 0x7FF0000000000000 ) ) ),
19807 } else if (inst_select
== 1) {
19813 DIP("xvxsigdp v%d,v%d\n", XT
, XB
);
19814 new_XT
[0] = newTemp(Ity_V128
);
19815 assign( new_XT
[0], binop( Iop_64HLtoV128
,
19819 for (i
= 0; i
< 2; i
++) {
19820 value
[i
] = newTemp(Ity_I64
);
19822 unop( Iop_V128to64
,
19823 binop( Iop_AndV128
,
19824 binop( Iop_ShrV128
,
19826 mkU8( (1-i
)*64 ) ),
19827 binop( Iop_64HLtoV128
,
19829 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
19831 /* Value is normal if it isn't infinite, zero or denormalized */
19832 normal
[i
] = mkNOT1( mkOR1(
19833 mkOR1( is_NaN( Ity_I64
, value
[i
] ),
19834 is_Inf( Ity_I64
, value
[i
] ) ),
19835 mkOR1( is_Zero( Ity_I64
, value
[i
] ),
19836 is_Denorm( Ity_I64
,
19838 new_XT
[i
+1] = newTemp(Ity_V128
);
19840 assign( new_XT
[i
+1],
19842 binop( Iop_ShlV128
,
19843 binop( Iop_64HLtoV128
,
19847 mkexpr( value
[i
] ),
19848 mkU64( 0xFFFFFFFFFFFFF ) ),
19853 mkU8( (1-i
)*64 ) ),
19854 mkexpr( new_XT
[i
] ) ) );
19856 putVSReg( XT
, mkexpr( new_XT
[2] ) );
19858 } else if (inst_select
== 7) {
19859 IRTemp sub_element0
= newTemp( Ity_V128
);
19860 IRTemp sub_element1
= newTemp( Ity_V128
);
19862 DIP("xxbrh v%u, v%u\n", (UInt
)XT
, (UInt
)XB
);
19864 assign( sub_element0
,
19865 binop( Iop_ShrV128
,
19866 binop( Iop_AndV128
,
19867 binop(Iop_64HLtoV128
,
19868 mkU64( 0xFF00FF00FF00FF00 ),
19869 mkU64( 0xFF00FF00FF00FF00 ) ),
19872 assign( sub_element1
,
19873 binop( Iop_ShlV128
,
19874 binop( Iop_AndV128
,
19875 binop(Iop_64HLtoV128
,
19876 mkU64( 0x00FF00FF00FF00FF ),
19877 mkU64( 0x00FF00FF00FF00FF ) ),
19881 putVSReg(XT
, binop( Iop_OrV128
,
19882 mkexpr( sub_element1
),
19883 mkexpr( sub_element0
) ) );
19885 } else if (inst_select
== 8) {
19886 DIP("xvxexpsp v%d,v%d\n", XT
, XB
);
19888 putVSReg( XT
, binop( Iop_ShrV128
,
19889 binop( Iop_AndV128
,
19891 binop( Iop_64HLtoV128
,
19892 mkU64( 0x7F8000007F800000 ),
19893 mkU64( 0x7F8000007F800000 ) ) ),
19895 } else if (inst_select
== 9) {
19899 IRTemp new_value
[4];
19902 DIP("xvxsigsp v%d,v%d\n", XT
, XB
);
19903 new_XT
[0] = newTemp(Ity_V128
);
19904 assign( new_XT
[0], binop( Iop_64HLtoV128
,
19908 for (i
= 0; i
< 4; i
++) {
19909 value
[i
] = newTemp(Ity_I32
);
19912 unop( Iop_V128to64
,
19913 binop( Iop_AndV128
,
19914 binop( Iop_ShrV128
,
19916 mkU8( (3-i
)*32 ) ),
19917 binop( Iop_64HLtoV128
,
19919 mkU64( 0xFFFFFFFF ) ) ) ) ) );
19921 new_XT
[i
+1] = newTemp(Ity_V128
);
19923 /* Value is normal if it isn't infinite, zero or denormalized */
19924 normal
[i
] = mkNOT1( mkOR1(
19925 mkOR1( is_NaN( Ity_I32
, value
[i
] ),
19926 is_Inf( Ity_I32
, value
[i
] ) ),
19927 mkOR1( is_Zero( Ity_I32
, value
[i
] ),
19928 is_Denorm( Ity_I32
,
19930 new_value
[i
] = newTemp(Ity_I32
);
19931 assign( new_value
[i
],
19934 mkexpr( value
[i
] ),
19935 mkU32( 0x7FFFFF ) ),
19941 assign( new_XT
[i
+1],
19943 binop( Iop_ShlV128
,
19944 binop( Iop_64HLtoV128
,
19946 binop( Iop_32HLto64
,
19948 mkexpr( new_value
[i
] ) ) ),
19949 mkU8( (3-i
)*32 ) ),
19950 mkexpr( new_XT
[i
] ) ) );
19952 putVSReg( XT
, mkexpr( new_XT
[4] ) );
19954 } else if (inst_select
== 15) {
19955 IRTemp sub_element0
= newTemp( Ity_V128
);
19956 IRTemp sub_element1
= newTemp( Ity_V128
);
19957 IRTemp sub_element2
= newTemp( Ity_V128
);
19958 IRTemp sub_element3
= newTemp( Ity_V128
);
19960 DIP("xxbrw v%u, v%u\n", (UInt
)XT
, (UInt
)XB
);
19962 assign( sub_element0
,
19963 binop( Iop_ShrV128
,
19964 binop( Iop_AndV128
,
19965 binop(Iop_64HLtoV128
,
19966 mkU64( 0xFF000000FF000000 ),
19967 mkU64( 0xFF000000FF000000 ) ),
19970 assign( sub_element1
,
19971 binop( Iop_ShrV128
,
19972 binop( Iop_AndV128
,
19973 binop(Iop_64HLtoV128
,
19974 mkU64( 0x00FF000000FF0000 ),
19975 mkU64( 0x00FF000000FF0000 ) ),
19978 assign( sub_element2
,
19979 binop( Iop_ShlV128
,
19980 binop( Iop_AndV128
,
19981 binop(Iop_64HLtoV128
,
19982 mkU64( 0x0000FF000000FF00 ),
19983 mkU64( 0x0000FF000000FF00 ) ),
19986 assign( sub_element3
,
19987 binop( Iop_ShlV128
,
19988 binop( Iop_AndV128
,
19989 binop(Iop_64HLtoV128
,
19990 mkU64( 0x00000000FF000000FF ),
19991 mkU64( 0x00000000FF000000FF ) ),
19998 mkexpr( sub_element3
),
19999 mkexpr( sub_element2
) ),
20001 mkexpr( sub_element1
),
20002 mkexpr( sub_element0
) ) ) );
20004 } else if (inst_select
== 23) {
20005 DIP("xxbrd v%u, v%u\n", (UInt
)XT
, (UInt
)XB
);
20009 IRTemp sub_element
[16];
20012 new_xT
[0] = newTemp( Ity_V128
);
20013 assign( new_xT
[0], binop( Iop_64HLtoV128
,
20017 for ( i
= 0; i
< 4; i
++ ) {
20018 new_xT
[i
+1] = newTemp( Ity_V128
);
20019 sub_element
[i
] = newTemp( Ity_V128
);
20020 sub_element
[i
+4] = newTemp( Ity_V128
);
20022 assign( sub_element
[i
],
20023 binop( Iop_ShrV128
,
20024 binop( Iop_AndV128
,
20025 binop( Iop_64HLtoV128
,
20026 mkU64( (0xFFULL
<< (7 - i
) * 8) ),
20027 mkU64( (0xFFULL
<< (7 - i
) * 8) ) ),
20031 assign( sub_element
[i
+4],
20032 binop( Iop_ShlV128
,
20033 binop( Iop_AndV128
,
20034 binop( Iop_64HLtoV128
,
20035 mkU64( (0xFFULL
<< i
*8) ),
20036 mkU64( (0xFFULL
<< i
*8) ) ),
20039 shift
= shift
- 16;
20041 assign( new_xT
[i
+1],
20043 mkexpr( new_xT
[i
] ),
20045 mkexpr ( sub_element
[i
] ),
20046 mkexpr ( sub_element
[i
+4] ) ) ) );
20049 putVSReg( XT
, mkexpr( new_xT
[4] ) );
20051 } else if (inst_select
== 24) {
20052 // xvcvhpsp, (VSX Vector Convert half-precision format to
20053 // Single-precision format)
20054 /* only supported on ISA 3.0 and newer */
20055 IRTemp result
= newTemp( Ity_V128
);
20056 IRTemp src
= newTemp( Ity_I64
);
20058 if (!allow_isa_3_0
) return False
;
20060 DIP("xvcvhpsp v%d,v%d\n", XT
,XB
);
20061 /* The instruction does not set the C or FPCC fields. The
20062 * instruction takes four 16-bit values stored in a 128-bit value
20063 * as follows: x V | x V | x V | x V where V is a 16-bit
20064 * value and x is an unused 16-bit value. To use Iop_F16toF32x4
20065 * the four 16-bit values will be gathered into a single 64 bit
20066 * value. The backend will scatter the four 16-bit values back
20067 * into a 128-bit operand before issuing the instruction.
20069 /* Gather 16-bit float values from V128 source into new 64-bit
20070 * source value for the Iop.
20073 unop( Iop_V128to64
,
20074 binop( Iop_Perm8x16
,
20076 binop ( Iop_64HLtoV128
,
20078 mkU64( 0x020306070A0B0E0F) ) ) ) );
20080 assign( result
, unop( Iop_F16toF32x4
, mkexpr( src
) ) );
20082 putVSReg( XT
, mkexpr( result
) );
20084 } else if (inst_select
== 25) {
20085 // xvcvsphp, (VSX Vector round and Convert single-precision
20086 // format to half-precision format)
20087 /* only supported on ISA 3.0 and newer */
20088 IRTemp result
= newTemp( Ity_V128
);
20089 IRTemp tmp64
= newTemp( Ity_I64
);
20091 if (!allow_isa_3_0
) return False
;
20092 DIP("xvcvsphp v%d,v%d\n", XT
,XB
);
20094 /* Iop_F32toF16x4 is V128 -> I64, scatter the 16-bit floats in the
20095 * I64 result to the V128 register to store.
20097 assign( tmp64
, unop( Iop_F32toF16x4_DEP
, mkexpr( vB
) ) );
20099 /* Scatter 16-bit float values from returned 64-bit value
20102 if (host_endness
== VexEndnessLE
)
20103 /* Note location 0 may have a valid number in it. Location
20104 * 15 should always be zero. Use 0xF to put zeros in the
20108 binop( Iop_Perm8x16
,
20109 binop( Iop_64HLtoV128
,
20112 binop ( Iop_64HLtoV128
,
20113 mkU64( 0x0F0F00010F0F0203 ),
20114 mkU64( 0x0F0F04050F0F0607 ) ) ) );
20117 binop( Iop_Perm8x16
,
20118 binop( Iop_64HLtoV128
,
20121 binop ( Iop_64HLtoV128
,
20122 mkU64( 0x0F0F06070F0F0405 ),
20123 mkU64( 0x0F0F02030F0F0001 ) ) ) );
20124 putVSReg( XT
, mkexpr( result
) );
20126 } else if ( inst_select
== 31 ) {
20128 int shift_left
= 8;
20129 int shift_right
= 120;
20130 IRTemp sub_element
[16];
20133 DIP("xxbrq v%u, v%u\n", (UInt
) XT
, (UInt
) XB
);
20135 new_xT
[0] = newTemp( Ity_V128
);
20136 assign( new_xT
[0], binop( Iop_64HLtoV128
,
20140 for ( i
= 0; i
< 8; i
++ ) {
20141 new_xT
[i
+1] = newTemp( Ity_V128
);
20142 sub_element
[i
] = newTemp( Ity_V128
);
20143 sub_element
[i
+8] = newTemp( Ity_V128
);
20145 assign( sub_element
[i
],
20146 binop( Iop_ShrV128
,
20147 binop( Iop_AndV128
,
20148 binop( Iop_64HLtoV128
,
20149 mkU64( ( 0xFFULL
<< (7 - i
) * 8 ) ),
20152 mkU8( shift_right
) ) );
20153 shift_right
= shift_right
- 16;
20155 assign( sub_element
[i
+8],
20156 binop( Iop_ShlV128
,
20157 binop( Iop_AndV128
,
20158 binop( Iop_64HLtoV128
,
20160 mkU64( ( 0xFFULL
<< (7 - i
) * 8 ) ) ),
20162 mkU8( shift_left
) ) );
20163 shift_left
= shift_left
+ 16;
20165 assign( new_xT
[i
+1],
20167 mkexpr( new_xT
[i
] ),
20169 mkexpr ( sub_element
[i
] ),
20170 mkexpr ( sub_element
[i
+8] ) ) ) );
20173 putVSReg( XT
, mkexpr( new_xT
[8] ) );
20176 vex_printf("dis_vxs_misc(ppc) Invalid instruction selection\n");
20182 case 0x3D4: // xvtstdcdp (VSX Test Data Class Double-Precision)
20184 UInt DX_mask
= IFIELD( theInstr
, 16, 5 );
20185 UInt DC_mask
= IFIELD( theInstr
, 6, 1 );
20186 UInt DM_mask
= IFIELD( theInstr
, 2, 1 );
20187 UInt DCMX_mask
= (DC_mask
<< 6) | (DM_mask
<< 5) | DX_mask
;
20189 IRTemp NaN
[2], inf
[2], zero
[2], dnorm
[2], pos
[2], DCM
[2];
20190 IRTemp match_value
[2];
20194 DIP("xvtstdcdp v%u,v%u,%u\n", (UInt
)XT
, (UInt
)XB
, DCMX_mask
);
20196 for (i
= 0; i
< 2; i
++) {
20197 NaN
[i
] = newTemp(Ity_I64
);
20198 inf
[i
] = newTemp(Ity_I64
);
20199 pos
[i
] = newTemp(Ity_I64
);
20200 DCM
[i
] = newTemp(Ity_I64
);
20201 zero
[i
] = newTemp(Ity_I64
);
20202 dnorm
[i
] = newTemp(Ity_I64
);
20204 value
[i
] = newTemp(Ity_I64
);
20205 match_value
[i
] = newTemp(Ity_I64
);
20208 unop( Iop_V128to64
,
20209 binop( Iop_AndV128
,
20210 binop( Iop_ShrV128
,
20212 mkU8( (1-i
)*64 ) ),
20213 binop( Iop_64HLtoV128
,
20215 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
20217 assign( pos
[i
], unop( Iop_1Uto64
,
20218 binop( Iop_CmpEQ64
,
20220 mkexpr( value
[i
] ),
20224 assign( NaN
[i
], unop( Iop_1Uto64
, is_NaN( Ity_I64
, value
[i
] ) ) );
20225 assign( inf
[i
], unop( Iop_1Uto64
, is_Inf( Ity_I64
, value
[i
] ) ) );
20226 assign( zero
[i
], unop( Iop_1Uto64
, is_Zero( Ity_I64
, value
[i
] ) ) );
20227 assign( dnorm
[i
], unop( Iop_1Uto64
, is_Denorm( Ity_I64
,
20230 assign( DCM
[i
], create_DCM( Ity_I64
, NaN
[i
], inf
[i
], zero
[i
],
20231 dnorm
[i
], pos
[i
] ) );
20233 assign( match_value
[i
],
20235 binop( Iop_CmpNE64
,
20237 mkU64( DCMX_mask
),
20238 mkexpr( DCM
[i
] ) ),
20241 putVSReg( XT
, binop( Iop_64HLtoV128
,
20242 mkexpr( match_value
[0] ),
20243 mkexpr( match_value
[1] ) ) );
20247 case 0x3E0: // xviexpdp (VSX Vector Insert Exponent Double-Precision)
20253 IRExpr
*sign
[2], *expr
[2], *fract
[2];
20255 DIP("xviexpdp v%d,v%d\n", XT
, XB
);
20256 new_XT
[0] = newTemp(Ity_V128
);
20257 assign( new_XT
[0], binop( Iop_64HLtoV128
,
20261 for (i
= 0; i
< 2; i
++) {
20262 A_value
[i
] = newTemp(Ity_I64
);
20263 B_value
[i
] = newTemp(Ity_I64
);
20265 assign( A_value
[i
],
20266 unop( Iop_V128to64
,
20267 binop( Iop_AndV128
,
20268 binop( Iop_ShrV128
,
20270 mkU8( (1-i
)*64 ) ),
20271 binop( Iop_64HLtoV128
,
20273 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
20274 assign( B_value
[i
],
20275 unop( Iop_V128to64
,
20276 binop( Iop_AndV128
,
20277 binop( Iop_ShrV128
,
20279 mkU8( (1-i
)*64 ) ),
20280 binop( Iop_64HLtoV128
,
20282 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
20284 sign
[i
] = binop( Iop_And64
, mkexpr( A_value
[i
] ),
20285 mkU64( 0x8000000000000000 ) );
20286 expr
[i
] = binop( Iop_Shl64
,
20287 binop( Iop_And64
, mkexpr( B_value
[i
] ),
20290 fract
[i
] = binop( Iop_And64
, mkexpr( A_value
[i
] ),
20291 mkU64( 0x000FFFFFFFFFFFFF ) );
20293 new_XT
[i
+1] = newTemp(Ity_V128
);
20294 assign( new_XT
[i
+1],
20296 binop( Iop_ShlV128
,
20297 binop( Iop_64HLtoV128
,
20304 mkU8( (1-i
)*64 ) ),
20305 mkexpr( new_XT
[i
] ) ) );
20307 putVSReg( XT
, mkexpr( new_XT
[2] ) );
20312 vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
20319 * VSX vector miscellaneous instructions
20323 dis_vx_misc ( UInt theInstr
, UInt opc2
)
20326 UChar XT
= ifieldRegXT ( theInstr
);
20327 UChar XA
= ifieldRegXA ( theInstr
);
20328 UChar XB
= ifieldRegXB ( theInstr
);
20329 IRTemp vA
= newTemp( Ity_V128
);
20330 IRTemp vB
= newTemp( Ity_V128
);
20331 IRTemp src1
= newTemp(Ity_I64
);
20332 IRTemp src2
= newTemp(Ity_I64
);
20333 IRTemp result_mask
= newTemp(Ity_I64
);
20334 IRTemp cmp_mask
= newTemp(Ity_I64
);
20335 IRTemp nan_mask
= newTemp(Ity_I64
);
20336 IRTemp snan_mask
= newTemp(Ity_I64
);
20337 IRTemp word_result
= newTemp(Ity_I64
);
20338 IRTemp check_result
= newTemp(Ity_I64
);
20339 IRTemp xT
= newTemp( Ity_V128
);
20340 IRTemp nan_cmp_value
= newTemp(Ity_I64
);
20341 UInt trap_enabled
= 0; /* 0 - trap enabled is False */
20343 assign( vA
, getVSReg( XA
) );
20344 assign( vB
, getVSReg( XB
) );
20345 assign( xT
, getVSReg( XT
) );
20347 assign(src1
, unop( Iop_V128HIto64
, mkexpr( vA
) ) );
20348 assign(src2
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
20352 unop( Iop_1Sto64
, is_NaN( Ity_I64
, src1
) ),
20353 unop( Iop_1Sto64
, is_NaN( Ity_I64
, src2
) ) ) );
20355 if ( trap_enabled
== 0 )
20356 /* Traps on invalid operation are assumed not enabled, assign
20357 result of comparison to xT.
20359 assign( snan_mask
, mkU64( 0 ) );
20364 unop( Iop_1Sto64
, is_sNaN( Ity_I64
, src1
) ),
20365 unop( Iop_1Sto64
, is_sNaN( Ity_I64
, src2
) ) ) );
20367 assign (result_mask
, binop( Iop_Or64
,
20368 mkexpr( snan_mask
),
20369 mkexpr( nan_mask
) ) );
20372 case 0xC: //xscmpeqdp
20374 DIP("xscmpeqdp v%d,v%d,v%d\n", XT
, XA
, XB
);
20375 /* extract double-precision floating point source values from
20378 /* result of Iop_CmpF64 is 0x40 if operands are equal,
20379 mask is all 1's if equal. */
20386 unop( Iop_ReinterpI64asF64
,
20388 unop( Iop_ReinterpI64asF64
,
20389 mkexpr( src2
) ) ),
20392 assign( word_result
,
20394 binop( Iop_And64
, mkexpr( cmp_mask
),
20395 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
20397 unop( Iop_Not64
, mkexpr( cmp_mask
) ),
20398 mkU64( 0x0 ) ) ) );
20399 assign( nan_cmp_value
, mkU64( 0 ) );
20403 case 0x2C: //xscmpgtdp
20405 DIP("xscmpgtdp v%d,v%d,v%d\n", XT
, XA
, XB
);
20406 /* Test for src1 > src2 */
20408 /* Result of Iop_CmpF64 is 0x1 if op1 < op2, set mask to all 1's. */
20413 unop( Iop_ReinterpI64asF64
,
20415 unop( Iop_ReinterpI64asF64
,
20416 mkexpr( src1
) ) ) ) ) );
20417 assign( word_result
,
20419 binop( Iop_And64
, mkexpr( cmp_mask
),
20420 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
20422 unop( Iop_Not64
, mkexpr( cmp_mask
) ),
20423 mkU64( 0x0 ) ) ) );
20424 assign( nan_cmp_value
, mkU64( 0 ) );
20428 case 0x4C: //xscmpgedp
20430 DIP("xscmpeqdp v%d,v%d,v%d\n", XT
, XA
, XB
);
20431 /* compare src 1 >= src 2 */
20432 /* result of Iop_CmpF64 is 0x40 if operands are equal,
20433 mask is all 1's if equal. */
20439 binop(Iop_CmpF64
, /* EQ test */
20440 unop( Iop_ReinterpI64asF64
,
20442 unop( Iop_ReinterpI64asF64
,
20443 mkexpr( src2
) ) ),
20445 binop(Iop_CmpF64
, /* src2 < src 1 test */
20446 unop( Iop_ReinterpI64asF64
,
20448 unop( Iop_ReinterpI64asF64
,
20449 mkexpr( src1
) ) ) ) ) ) );
20450 assign( word_result
,
20452 binop( Iop_And64
, mkexpr( cmp_mask
),
20453 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
20455 unop( Iop_Not64
, mkexpr( cmp_mask
) ),
20456 mkU64( 0x0 ) ) ) );
20457 assign( nan_cmp_value
, mkU64( 0 ) );
20461 case 0x200: //xsmaxcdp
20463 DIP("xsmaxcdp v%d,v%d,v%d\n", XT
, XA
, XB
);
20464 /* extract double-precision floating point source values from
20467 /* result of Iop_CmpF64 is 0x1 if arg1 LT then arg2, */
20472 unop( Iop_ReinterpI64asF64
,
20474 unop( Iop_ReinterpI64asF64
,
20475 mkexpr( src1
) ) ) ) ) );
20476 assign( word_result
,
20478 binop( Iop_And64
, mkexpr( cmp_mask
), mkexpr( src1
) ),
20480 unop( Iop_Not64
, mkexpr( cmp_mask
) ),
20481 mkexpr( src2
) ) ) );
20482 assign( nan_cmp_value
, mkexpr( src2
) );
20486 case 0x220: //xsmincdp
20488 DIP("xsmincdp v%d,v%d,v%d\n", XT
, XA
, XB
);
20489 /* extract double-precision floating point source values from
20492 /* result of Iop_CmpF64 is 0x1 if arg1 less then arg2, */
20497 unop( Iop_ReinterpI64asF64
,
20499 unop( Iop_ReinterpI64asF64
,
20500 mkexpr( src2
) ) ) ) ) );
20501 assign( word_result
,
20503 binop( Iop_And64
, mkexpr( cmp_mask
), mkexpr( src1
) ),
20505 unop( Iop_Not64
, mkexpr( cmp_mask
) ),
20506 mkexpr( src2
) ) ) );
20507 assign( nan_cmp_value
, mkexpr( src2
) );
20512 vex_printf( "dis_vx_misc(ppc)(opc2)\n" );
20516 /* If either argument is NaN, result is src2. If either argument is
20517 SNaN, we are supposed to generate invalid operation exception.
20518 Currently don't support generating exceptions. In case of an
20519 trap enabled invalid operation (SNaN) XT is not changed. The
20520 snan_mask is setup appropriately for trap enabled or not.
20522 assign( check_result
,
20524 binop( Iop_And64
, mkexpr( snan_mask
),
20525 unop( Iop_V128HIto64
, mkexpr( xT
) ) ),
20526 binop( Iop_And64
, unop( Iop_Not64
,
20527 mkexpr( snan_mask
) ),
20529 binop( Iop_And64
, mkexpr( nan_mask
),
20530 mkexpr( nan_cmp_value
) ),
20533 mkexpr( nan_mask
) ),
20534 mkU64( 0 ) ) ) ) ) );
20536 /* If SNaN is true, then the result is unchanged if a trap-enabled
20537 Invalid Operation occurs. Result mask already setup for trap-enabled
20541 binop( Iop_64HLtoV128
,
20544 unop( Iop_Not64
, mkexpr( result_mask
) ),
20545 mkexpr( word_result
) ),
20547 mkexpr( result_mask
),
20548 mkexpr( check_result
) ) ),
20554 * VSX Logical Instructions
20557 dis_vx_logic ( UInt theInstr
, UInt opc2
)
20560 UChar opc1
= ifieldOPC( theInstr
);
20561 UChar XT
= ifieldRegXT ( theInstr
);
20562 UChar XA
= ifieldRegXA ( theInstr
);
20563 UChar XB
= ifieldRegXB ( theInstr
);
20564 IRTemp vA
= newTemp( Ity_V128
);
20565 IRTemp vB
= newTemp( Ity_V128
);
20567 if (opc1
!= 0x3C) {
20568 vex_printf( "dis_vx_logic(ppc)(instr)\n" );
20572 assign( vA
, getVSReg( XA
) );
20573 assign( vB
, getVSReg( XB
) );
20576 case 0x268: // xxlxor
20577 DIP("xxlxor v%d,v%d,v%d\n", XT
, XA
, XB
);
20578 putVSReg( XT
, binop( Iop_XorV128
, mkexpr( vA
), mkexpr( vB
) ) );
20580 case 0x248: // xxlor
20581 DIP("xxlor v%d,v%d,v%d\n", XT
, XA
, XB
);
20582 putVSReg( XT
, binop( Iop_OrV128
, mkexpr( vA
), mkexpr( vB
) ) );
20584 case 0x288: // xxlnor
20585 DIP("xxlnor v%d,v%d,v%d\n", XT
, XA
, XB
);
20586 putVSReg( XT
, unop( Iop_NotV128
, binop( Iop_OrV128
, mkexpr( vA
),
20587 mkexpr( vB
) ) ) );
20589 case 0x208: // xxland
20590 DIP("xxland v%d,v%d,v%d\n", XT
, XA
, XB
);
20591 putVSReg( XT
, binop( Iop_AndV128
, mkexpr( vA
), mkexpr( vB
) ) );
20593 case 0x228: //xxlandc
20594 DIP("xxlandc v%d,v%d,v%d\n", XT
, XA
, XB
);
20595 putVSReg( XT
, binop( Iop_AndV128
, mkexpr( vA
), unop( Iop_NotV128
,
20596 mkexpr( vB
) ) ) );
20598 case 0x2A8: // xxlorc (VSX Logical OR with complement)
20599 DIP("xxlorc v%d,v%d,v%d\n", XT
, XA
, XB
);
20600 putVSReg( XT
, binop( Iop_OrV128
,
20602 unop( Iop_NotV128
, mkexpr( vB
) ) ) );
20604 case 0x2C8: // xxlnand (VSX Logical NAND)
20605 DIP("xxlnand v%d,v%d,v%d\n", XT
, XA
, XB
);
20606 putVSReg( XT
, unop( Iop_NotV128
,
20607 binop( Iop_AndV128
, mkexpr( vA
),
20608 mkexpr( vB
) ) ) );
20610 case 0x2E8: // xxleqv (VSX Logical Equivalence)
20611 DIP("xxleqv v%d,v%d,v%d\n", XT
, XA
, XB
);
20612 putVSReg( XT
, unop( Iop_NotV128
,
20613 binop( Iop_XorV128
,
20614 mkexpr( vA
), mkexpr( vB
) ) ) );
20617 vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
20624 * VSX Load Instructions
20625 * NOTE: VSX supports word-aligned storage access.
20628 dis_vx_load ( UInt theInstr
)
20631 UChar opc1
= ifieldOPC( theInstr
);
20632 UChar XT
= ifieldRegXT ( theInstr
);
20633 UChar rA_addr
= ifieldRegA( theInstr
);
20634 UChar rB_addr
= ifieldRegB( theInstr
);
20635 UInt opc2
= ifieldOPClo10( theInstr
);
20637 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
20638 IRTemp EA
= newTemp( ty
);
20640 if (opc1
!= 0x1F) {
20641 vex_printf( "dis_vx_load(ppc)(instr)\n" );
20645 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
20648 case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
20651 DIP("lxsiwzx %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
20653 if (host_endness
== VexEndnessLE
)
20654 exp
= unop( Iop_64to32
, load( Ity_I64
, mkexpr( EA
) ) );
20656 exp
= unop( Iop_64HIto32
, load( Ity_I64
, mkexpr( EA
) ) );
20658 putVSReg( XT
, binop( Iop_64HLtoV128
,
20659 unop( Iop_32Uto64
, exp
),
20663 case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
20666 DIP("lxsiwax %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
20668 if (host_endness
== VexEndnessLE
)
20669 exp
= unop( Iop_64to32
, load( Ity_I64
, mkexpr( EA
) ) );
20671 exp
= unop( Iop_64HIto32
, load( Ity_I64
, mkexpr( EA
) ) );
20673 putVSReg( XT
, binop( Iop_64HLtoV128
,
20674 unop( Iop_32Sto64
, exp
),
20678 case 0x10C: // lxvx
20685 DIP("lxvx %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
20687 if ( host_endness
== VexEndnessBE
) {
20688 for ( i
= 3; i
>= 0; i
-- ) {
20689 word
[i
] = newTemp( Ity_I64
);
20692 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
20693 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
20695 assign( word
[i
], unop( Iop_32Uto64
,
20696 load( Ity_I32
, irx_addr
) ) );
20700 putVSReg( XT
, binop( Iop_64HLtoV128
,
20710 mkU8( 32 ) ) ) ) );
20712 for ( i
= 0; i
< 4; i
++ ) {
20713 word
[i
] = newTemp( Ity_I64
);
20716 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
20717 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
20719 assign( word
[i
], unop( Iop_32Uto64
,
20720 load( Ity_I32
, irx_addr
) ) );
20724 putVSReg( XT
, binop( Iop_64HLtoV128
,
20734 mkU8( 32 ) ) ) ) );
20739 case 0x10D: // lxvl
20741 DIP("lxvl %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
20749 IRTemp shift
= newTemp( Ity_I8
);
20750 IRTemp nb_gt16
= newTemp( Ity_I8
);
20751 IRTemp ld_result
= newTemp( Ity_V128
);
20752 IRTemp nb_not_zero
= newTemp( Ity_I64
);
20754 IRTemp base_addr
= newTemp( ty
);
20756 tmp_low
[0] = newTemp( Ity_I64
);
20757 tmp_hi
[0] = newTemp( Ity_I64
);
20759 assign( base_addr
, ea_rAor0( rA_addr
) );
20760 assign( tmp_low
[0], mkU64( 0 ) );
20761 assign( tmp_hi
[0], mkU64( 0 ) );
20763 /* shift is 15 - nb, where nb = rB[0:7], used to zero out upper bytes */
20764 assign( nb_not_zero
, unop( Iop_1Sto64
,
20765 binop( Iop_CmpNE64
,
20768 getIReg( rB_addr
),
20769 mkU8( 56 ) ) ) ) );
20771 assign( nb_gt16
, unop( Iop_1Sto8
,
20772 binop( Iop_CmpLT64U
,
20774 getIReg( rB_addr
),
20778 /* Set the shift to 0, by ANDing with nb_gt16. nb_gt16 will be all
20779 * zeros if nb > 16. This will result in quad word load being stored.
20788 getIReg( rB_addr
),
20791 mkexpr( nb_gt16
) ) );
20793 /* fetch all 16 bytes, we will remove what we don't want later */
20794 if ( host_endness
== VexEndnessBE
) {
20795 for ( i
= 0; i
< 8; i
++ ) {
20796 byte
[i
] = newTemp( Ity_I64
);
20797 tmp_hi
[i
+1] = newTemp( Ity_I64
);
20800 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
20801 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
20804 assign( byte
[i
], binop( Iop_Shl64
,
20806 load( Ity_I8
, irx_addr
) ),
20807 mkU8( 8 * ( 7 - i
) ) ) );
20809 assign( tmp_hi
[i
+1], binop( Iop_Or64
,
20811 mkexpr( tmp_hi
[i
] ) ) );
20814 for ( i
= 0; i
< 8; i
++ ) {
20815 byte
[i
+8] = newTemp( Ity_I64
);
20816 tmp_low
[i
+1] = newTemp( Ity_I64
);
20819 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
20820 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
20823 assign( byte
[i
+8], binop( Iop_Shl64
,
20825 load( Ity_I8
, irx_addr
) ),
20826 mkU8( 8 * ( 7 - i
) ) ) );
20828 assign( tmp_low
[i
+1], binop( Iop_Or64
,
20829 mkexpr( byte
[i
+8] ),
20830 mkexpr( tmp_low
[i
] ) ) );
20832 assign( ld_result
, binop( Iop_ShlV128
,
20833 binop( Iop_ShrV128
,
20834 binop( Iop_64HLtoV128
,
20835 mkexpr( tmp_hi
[8] ),
20836 mkexpr( tmp_low
[8] ) ),
20838 mkexpr( shift
) ) );
20840 for ( i
= 0; i
< 8; i
++ ) {
20841 byte
[i
] = newTemp( Ity_I64
);
20842 tmp_low
[i
+1] = newTemp( Ity_I64
);
20845 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
20846 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
20849 assign( byte
[i
], binop( Iop_Shl64
,
20851 load( Ity_I8
, irx_addr
) ),
20854 assign( tmp_low
[i
+1],
20856 mkexpr( byte
[i
] ), mkexpr( tmp_low
[i
] ) ) );
20859 for ( i
= 0; i
< 8; i
++ ) {
20860 byte
[i
+ 8] = newTemp( Ity_I64
);
20861 tmp_hi
[i
+1] = newTemp( Ity_I64
);
20864 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
20865 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
20868 assign( byte
[i
+8], binop( Iop_Shl64
,
20870 load( Ity_I8
, irx_addr
) ),
20873 assign( tmp_hi
[i
+1], binop( Iop_Or64
,
20874 mkexpr( byte
[i
+8] ),
20875 mkexpr( tmp_hi
[i
] ) ) );
20877 assign( ld_result
, binop( Iop_ShrV128
,
20878 binop( Iop_ShlV128
,
20879 binop( Iop_64HLtoV128
,
20880 mkexpr( tmp_hi
[8] ),
20881 mkexpr( tmp_low
[8] ) ),
20883 mkexpr( shift
) ) );
20887 /* If nb = 0, mask out the calculated load result so the stored
20891 putVSReg( XT
, binop( Iop_AndV128
,
20892 mkexpr( ld_result
),
20893 binop( Iop_64HLtoV128
,
20894 mkexpr( nb_not_zero
),
20895 mkexpr( nb_not_zero
) ) ) );
20899 case 0x12D: // lxvll (Load VSX Vector Left-Justified with Length XX1 form)
20904 IRTemp mask
= newTemp(Ity_V128
);
20905 IRTemp rB
= newTemp( Ity_I64
);
20906 IRTemp nb
= newTemp( Ity_I64
);
20907 IRTemp nb_zero
= newTemp(Ity_V128
);
20908 IRTemp mask_shift
= newTemp(Ity_I64
);
20912 IRTemp base_addr
= newTemp( ty
);
20913 IRTemp nb_compare_zero
= newTemp( Ity_I64
);
20915 DIP("lxvll %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
20917 tmp_low
[0] = newTemp(Ity_I64
);
20918 tmp_hi
[0] = newTemp(Ity_I64
);
20920 assign( rB
, getIReg(rB_addr
));
20921 assign( base_addr
, ea_rAor0( rA_addr
) );
20922 assign( tmp_low
[0], mkU64( 0 ) );
20923 assign( tmp_hi
[0], mkU64( 0 ) );
20925 /* mask_shift is number of 16 bytes minus (nb times 8-bits per byte) */
20926 assign( nb
, binop( Iop_Shr64
, mkexpr( rB
), mkU8( 56 ) ) );
20928 assign( nb_compare_zero
, unop( Iop_1Sto64
,
20929 binop( Iop_CmpEQ64
,
20933 /* nb_zero is 0xFF..FF if the nb_field = 0 */
20934 assign( nb_zero
, binop( Iop_64HLtoV128
,
20935 mkexpr( nb_compare_zero
),
20936 mkexpr( nb_compare_zero
) ) );
20938 assign( mask_shift
, binop( Iop_Sub64
,
20944 /* fetch all 16 bytes, we will remove what we don't want later */
20945 for (i
= 0; i
< 8; i
++) {
20946 byte
[i
] = newTemp(Ity_I64
);
20947 tmp_hi
[i
+1] = newTemp(Ity_I64
);
20949 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
20950 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
20953 /* Instruction always loads in Big Endian format */
20954 assign( byte
[i
], binop( Iop_Shl64
,
20956 load( Ity_I8
, irx_addr
) ),
20957 mkU8( 8 * (7 - i
) ) ) );
20958 assign( tmp_hi
[i
+1],
20960 mkexpr( byte
[i
] ), mkexpr( tmp_hi
[i
] ) ) );
20963 for (i
= 0; i
< 8; i
++) {
20964 byte
[i
+ 8] = newTemp(Ity_I64
);
20965 tmp_low
[i
+1] = newTemp(Ity_I64
);
20967 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
20968 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
20971 /* Instruction always loads in Big Endian format */
20972 assign( byte
[i
+8], binop( Iop_Shl64
,
20974 load( Ity_I8
, irx_addr
) ),
20975 mkU8( 8 * (7 - i
) ) ) );
20976 assign( tmp_low
[i
+1], binop( Iop_Or64
,
20977 mkexpr( byte
[i
+8] ),
20978 mkexpr( tmp_low
[i
] ) ) );
20981 /* Create mask to clear the right most 16 - nb bytes, set to zero
20984 assign( mask
, binop( Iop_AndV128
,
20985 binop( Iop_ShlV128
,
20986 binop( Iop_ShrV128
,
20988 unop( Iop_64to8
, mkexpr( mask_shift
) ) ),
20989 unop( Iop_64to8
, mkexpr( mask_shift
) ) ),
20990 unop( Iop_NotV128
, mkexpr( nb_zero
) ) ) );
20992 putVSReg( XT
, binop( Iop_AndV128
,
20994 binop( Iop_64HLtoV128
,
20995 mkexpr( tmp_hi
[8] ),
20996 mkexpr( tmp_low
[8] ) ) ) );
21000 case 0x16C: // lxvwsx
21002 IRTemp data
= newTemp( Ity_I64
);
21004 DIP("lxvwsx %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
21006 /* The load is a 64-bit fetch that is Endian aware, just want
21007 * the lower 32 bits. */
21008 if ( host_endness
== VexEndnessBE
) {
21013 binop( mkSzOp( ty
, Iop_Sub8
), mkexpr( EA
),
21014 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21016 assign( data
, binop( Iop_And64
,
21017 load( Ity_I64
, irx_addr
),
21018 mkU64( 0xFFFFFFFF ) ) );
21021 assign( data
, binop( Iop_And64
,
21022 load( Ity_I64
, mkexpr( EA
) ),
21023 mkU64( 0xFFFFFFFF ) ) );
21026 /* Take lower 32-bits and spat across the four word positions */
21028 binop( Iop_64HLtoV128
,
21038 mkU8( 32 ) ) ) ) );
21042 case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
21045 DIP("lxsspx %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
21046 /* Take 32-bit floating point value in the upper half of the fetched
21047 * 64-bit value, convert to 64-bit floating point value and load into
21048 * top word of V128.
21050 exp
= unop( Iop_ReinterpF64asI64
,
21051 unop( Iop_F32toF64
,
21052 unop( Iop_ReinterpI32asF32
,
21053 load( Ity_I32
, mkexpr( EA
) ) ) ) );
21055 putVSReg( XT
, binop( Iop_64HLtoV128
, exp
, mkU64( 0 ) ) );
21058 case 0x24C: // lxsdx
21061 DIP("lxsdx %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
21062 exp
= load( Ity_I64
, mkexpr( EA
) );
21063 // We need to pass an expression of type Ity_V128 with putVSReg, but the load
21064 // we just performed is only a DW. But since the contents of VSR[XT] element 1
21065 // are undefined after this operation, we can just do a splat op.
21066 putVSReg( XT
, binop( Iop_64HLtoV128
, exp
, exp
) );
21070 case 0x30D: // lxsibzx
21075 DIP("lxsibzx %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
21077 if ( host_endness
== VexEndnessBE
)
21078 irx_addr
= binop( Iop_Sub64
, mkexpr( EA
), mkU64( 7 ) );
21081 irx_addr
= mkexpr( EA
);
21083 byte
= load( Ity_I64
, irx_addr
);
21084 putVSReg( XT
, binop( Iop_64HLtoV128
,
21092 case 0x32D: // lxsihzx
21097 DIP("lxsihzx %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
21099 if ( host_endness
== VexEndnessBE
)
21100 irx_addr
= binop( Iop_Sub64
, mkexpr( EA
), mkU64( 6 ) );
21103 irx_addr
= mkexpr( EA
);
21105 byte
= load( Ity_I64
, irx_addr
);
21106 putVSReg( XT
, binop( Iop_64HLtoV128
,
21113 case 0x34C: // lxvd2x
21116 DIP("lxvd2x %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
21117 t128
= load( Ity_V128
, mkexpr( EA
) );
21119 /* The data in the vec register should be in big endian order.
21120 So if we just did a little endian load then swap around the
21121 high and low double words. */
21122 if (host_endness
== VexEndnessLE
) {
21123 IRTemp high
= newTemp(Ity_I64
);
21124 IRTemp low
= newTemp(Ity_I64
);
21125 assign( high
, unop(Iop_V128HIto64
, t128
) );
21126 assign( low
, unop(Iop_V128to64
, t128
) );
21127 t128
= binop( Iop_64HLtoV128
, mkexpr (low
), mkexpr (high
) );
21130 putVSReg( XT
, t128
);
21133 case 0x14C: // lxvdsx
21135 IRTemp data
= newTemp(Ity_I64
);
21136 DIP("lxvdsx %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
21137 assign( data
, load( Ity_I64
, mkexpr( EA
) ) );
21138 putVSReg( XT
, binop( Iop_64HLtoV128
, mkexpr( data
), mkexpr( data
) ) );
21145 DIP("lxvw4x %u,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
21147 /* The load will result in the data being in BE order. */
21148 if (host_endness
== VexEndnessLE
) {
21150 IRTemp perm_LE
= newTemp(Ity_V128
);
21152 t0_BE
= load( Ity_V128
, mkexpr( EA
) );
21154 /* Permute the data to LE format */
21155 assign( perm_LE
, binop( Iop_64HLtoV128
, mkU64(0x0c0d0e0f08090a0bULL
),
21156 mkU64(0x0405060700010203ULL
)));
21158 t0
= binop( Iop_Perm8x16
, t0_BE
, mkexpr(perm_LE
) );
21160 t0
= load( Ity_V128
, mkexpr( EA
) );
21163 putVSReg( XT
, t0
);
21167 case 0x32C: // lxvh8x
21169 DIP("lxvh8x %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
21178 tmp_low
[0] = newTemp( Ity_I64
);
21179 tmp_hi
[0] = newTemp( Ity_I64
);
21180 assign( tmp_low
[0], mkU64( 0 ) );
21181 assign( tmp_hi
[0], mkU64( 0 ) );
21183 for ( i
= 0; i
< 4; i
++ ) {
21184 h_word
[i
] = newTemp(Ity_I64
);
21185 tmp_low
[i
+1] = newTemp(Ity_I64
);
21187 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21188 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21191 assign( h_word
[i
], binop( Iop_Shl64
,
21193 load( Ity_I16
, irx_addr
) ),
21194 mkU8( 16 * ( 3 - i
) ) ) );
21196 assign( tmp_low
[i
+1],
21198 mkexpr( h_word
[i
] ), mkexpr( tmp_low
[i
] ) ) );
21201 for ( i
= 0; i
< 4; i
++ ) {
21202 h_word
[i
+4] = newTemp( Ity_I64
);
21203 tmp_hi
[i
+1] = newTemp( Ity_I64
);
21205 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21206 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21209 assign( h_word
[i
+4], binop( Iop_Shl64
,
21211 load( Ity_I16
, irx_addr
) ),
21212 mkU8( 16 * ( 3 - i
) ) ) );
21214 assign( tmp_hi
[i
+1], binop( Iop_Or64
,
21215 mkexpr( h_word
[i
+4] ),
21216 mkexpr( tmp_hi
[i
] ) ) );
21218 putVSReg( XT
, binop( Iop_64HLtoV128
,
21219 mkexpr( tmp_low
[4] ), mkexpr( tmp_hi
[4] ) ) );
21223 case 0x36C: // lxvb16x
21225 DIP("lxvb16x %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
21227 /* The result of lxvb16x should be the same on big and little
21228 endian systems. We do a host load, then reverse the bytes in
21229 the double words. If the host load was little endian we swap
21230 them around again. */
21232 IRTemp high
= newTemp(Ity_I64
);
21233 IRTemp high_rev
= newTemp(Ity_I64
);
21234 IRTemp low
= newTemp(Ity_I64
);
21235 IRTemp low_rev
= newTemp(Ity_I64
);
21237 IRExpr
*t128
= load( Ity_V128
, mkexpr( EA
) );
21239 assign( high
, unop(Iop_V128HIto64
, t128
) );
21240 assign( high_rev
, unop(Iop_Reverse8sIn64_x1
, mkexpr(high
)) );
21241 assign( low
, unop(Iop_V128to64
, t128
) );
21242 assign( low_rev
, unop(Iop_Reverse8sIn64_x1
, mkexpr(low
)) );
21244 if (host_endness
== VexEndnessLE
)
21245 t128
= binop( Iop_64HLtoV128
, mkexpr (low_rev
), mkexpr (high_rev
) );
21247 t128
= binop( Iop_64HLtoV128
, mkexpr (high_rev
), mkexpr (low_rev
) );
21249 putVSReg( XT
, t128
);
21254 vex_printf( "dis_vx_load(ppc)(opc2)\n" );
21261 * VSX Move Instructions
21264 dis_vx_move ( UInt theInstr
)
21267 UChar opc1
= ifieldOPC( theInstr
);
21268 UChar XS
= ifieldRegXS( theInstr
);
21269 UChar rA_addr
= ifieldRegA( theInstr
);
21270 UChar rB_addr
= ifieldRegB( theInstr
);
21271 IRTemp vS
= newTemp( Ity_V128
);
21272 UInt opc2
= ifieldOPClo10( theInstr
);
21273 IRType ty
= Ity_I64
;
21275 if ( opc1
!= 0x1F ) {
21276 vex_printf( "dis_vx_move(ppc)(instr)\n" );
21281 case 0x133: // mfvsrld RA,XS Move From VSR Lower Doubleword
21282 DIP("mfvsrld %u,r%u\n", (UInt
)XS
, rA_addr
);
21284 assign( vS
, getVSReg( XS
) );
21285 putIReg( rA_addr
, unop(Iop_V128to64
, mkexpr( vS
) ) );
21289 case 0x193: // mfvsrdd XT,RA,RB Move to VSR Double Doubleword
21291 IRTemp tmp
= newTemp( Ity_I32
);
21293 DIP("mfvsrdd %u,r%u\n", (UInt
)XS
, rA_addr
);
21295 assign( tmp
, unop( Iop_64to32
, getIReg(rA_addr
) ) );
21296 assign( vS
, binop( Iop_64HLtoV128
,
21297 binop( Iop_32HLto64
,
21300 binop( Iop_32HLto64
,
21302 mkexpr( tmp
) ) ) );
21303 putVSReg( XS
, mkexpr( vS
) );
21307 case 0x1B3: // mtvsrws XT,RA Move to VSR word & Splat
21309 IRTemp rA
= newTemp( ty
);
21310 IRTemp rB
= newTemp( ty
);
21312 DIP("mfvsrws %u,r%u\n", (UInt
)XS
, rA_addr
);
21314 if ( rA_addr
== 0 )
21315 assign( rA
, mkU64 ( 0 ) );
21317 assign( rA
, getIReg(rA_addr
) );
21319 assign( rB
, getIReg(rB_addr
) );
21320 assign( vS
, binop( Iop_64HLtoV128
, mkexpr( rA
), mkexpr( rB
) ) );
21321 putVSReg( XS
, mkexpr( vS
) );
21326 vex_printf( "dis_vx_move(ppc)(opc2)\n" );
21333 * VSX Store Instructions
21334 * NOTE: VSX supports word-aligned storage access.
21337 dis_vx_store ( UInt theInstr
)
21340 UChar opc1
= ifieldOPC( theInstr
);
21341 UChar XS
= ifieldRegXS( theInstr
);
21342 UChar rA_addr
= ifieldRegA( theInstr
);
21343 UChar rB_addr
= ifieldRegB( theInstr
);
21344 IRTemp vS
= newTemp( Ity_V128
);
21345 UInt opc2
= ifieldOPClo10( theInstr
);
21347 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
21348 IRTemp EA
= newTemp( ty
);
21350 if (opc1
!= 0x1F) {
21351 vex_printf( "dis_vx_store(ppc)(instr)\n" );
21355 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
21356 assign( vS
, getVSReg( XS
) );
21361 /* Need the next to the most significant 32-bit word from
21362 * the 128-bit vector.
21364 IRExpr
* high64
, * low32
;
21365 DIP("stxsiwx %d,r%u,r%u\n", XS
, rA_addr
, rB_addr
);
21366 high64
= unop( Iop_V128HIto64
, mkexpr( vS
) );
21367 low32
= unop( Iop_64to32
, high64
);
21368 store( mkexpr( EA
), low32
);
21372 case 0x18C: // stxvx Store VSX Vector Indexed
21376 IRTemp word0
= newTemp( Ity_I64
);
21377 IRTemp word1
= newTemp( Ity_I64
);
21378 IRTemp word2
= newTemp( Ity_I64
);
21379 IRTemp word3
= newTemp( Ity_I64
);
21380 DIP("stxvx %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
21382 assign( word0
, binop( Iop_Shr64
,
21383 unop( Iop_V128HIto64
, mkexpr( vS
) ),
21386 assign( word1
, binop( Iop_And64
,
21387 unop( Iop_V128HIto64
, mkexpr( vS
) ),
21388 mkU64( 0xFFFFFFFF ) ) );
21390 assign( word2
, binop( Iop_Shr64
,
21391 unop( Iop_V128to64
, mkexpr( vS
) ),
21394 assign( word3
, binop( Iop_And64
,
21395 unop( Iop_V128to64
, mkexpr( vS
) ),
21396 mkU64( 0xFFFFFFFF ) ) );
21398 if (host_endness
== VexEndnessBE
) {
21399 store( mkexpr( EA
), unop( Iop_64to32
, mkexpr( word0
) ) );
21402 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21403 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21405 store( irx_addr
, unop( Iop_64to32
, mkexpr( word1
) ) );
21408 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21409 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21411 store( irx_addr
, unop( Iop_64to32
, mkexpr( word2
) ) );
21413 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21414 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21416 store( irx_addr
, unop( Iop_64to32
, mkexpr( word3
) ) );
21418 store( mkexpr( EA
), unop( Iop_64to32
, mkexpr( word3
) ) );
21421 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21422 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21424 store( irx_addr
, unop( Iop_64to32
, mkexpr( word2
) ) );
21427 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21428 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21430 store( irx_addr
, unop( Iop_64to32
, mkexpr( word1
) ) );
21432 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21433 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21435 store( irx_addr
, unop( Iop_64to32
, mkexpr( word0
) ) );
21440 case 0x18D: // stxvl Store VSX Vector Indexed
21444 IRTemp word0
= newTemp( Ity_I64
);
21445 IRTemp word1
= newTemp( Ity_I64
);
21446 IRTemp word2
= newTemp( Ity_I64
);
21447 IRTemp word3
= newTemp( Ity_I64
);
21448 IRTemp shift
= newTemp( Ity_I8
);
21449 IRTemp nb_gt16
= newTemp( Ity_I8
);
21450 IRTemp nb_zero
= newTemp( Ity_V128
);
21451 IRTemp nb
= newTemp( Ity_I8
);
21452 IRTemp nb_field
= newTemp( Ity_I64
);
21453 IRTemp n_bytes
= newTemp( Ity_I8
);
21454 IRTemp base_addr
= newTemp( ty
);
21455 IRTemp current_mem
= newTemp( Ity_V128
);
21456 IRTemp store_val
= newTemp( Ity_V128
);
21457 IRTemp nb_mask
= newTemp( Ity_V128
);
21459 DIP("stxvl %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
21461 assign( nb_field
, binop( Iop_Shr64
,
21465 assign( nb
, unop( Iop_64to8
, mkexpr( nb_field
) ) );
21467 /* nb_gt16 will be all zeros if nb > 16 */
21468 assign( nb_gt16
, unop( Iop_1Sto8
,
21469 binop( Iop_CmpLT64U
,
21471 mkexpr( nb_field
),
21475 /* nb_zero is 0xFF..FF if the nb_field = 0 */
21476 assign( nb_zero
, binop( Iop_64HLtoV128
,
21478 binop( Iop_CmpEQ64
,
21479 mkexpr( nb_field
),
21482 binop( Iop_CmpEQ64
,
21483 mkexpr( nb_field
),
21484 mkU64( 0 ) ) ) ) );
21486 /* set n_bytes to 0 if nb >= 16. Otherwise, set to nb. */
21487 assign( n_bytes
, binop( Iop_And8
, mkexpr( nb
), mkexpr( nb_gt16
) ) );
21488 assign( shift
, unop( Iop_64to8
,
21493 mkexpr( n_bytes
) ) ),
21496 /* We only have a 32-bit store function. So, need to fetch the
21497 * contents of memory merge with the store value and do two
21498 * 32-byte stores so we preserve the contents of memory not
21501 assign( base_addr
, ea_rAor0( rA_addr
) );
21503 assign( current_mem
,
21504 binop( Iop_64HLtoV128
,
21506 binop( mkSzOp( ty
, Iop_Add8
),
21507 mkexpr( base_addr
),
21508 ty
== Ity_I64
? mkU64( 8 ) : mkU32( 8 )
21510 load( Ity_I64
, mkexpr( base_addr
) ) ) );
21512 /* Set the nb_mask to all zeros if nb = 0 so the current contents
21513 * of memory get written back without modifications.
21515 * The store_val is a combination of the current memory value
21516 * and the bytes you want to store. The nb_mask selects the
21517 * bytes you want stored from Vs.
21521 binop( Iop_AndV128
,
21524 binop( Iop_AndV128
,
21525 binop( Iop_ShrV128
,
21528 unop( Iop_NotV128
, mkexpr( nb_zero
) ) ) ) );
21532 binop( Iop_AndV128
,
21534 mkexpr( nb_mask
) ),
21535 binop( Iop_AndV128
,
21536 unop( Iop_NotV128
, mkexpr( nb_mask
) ),
21537 mkexpr( current_mem
) ) ) );
21539 /* Store the value in 32-byte chunks */
21540 assign( word0
, binop( Iop_Shr64
,
21541 unop( Iop_V128HIto64
, mkexpr( store_val
) ),
21544 assign( word1
, binop( Iop_And64
,
21545 unop( Iop_V128HIto64
, mkexpr( store_val
) ),
21546 mkU64( 0xFFFFFFFF ) ) );
21548 assign( word2
, binop( Iop_Shr64
,
21549 unop( Iop_V128to64
, mkexpr( store_val
) ),
21552 assign( word3
, binop( Iop_And64
,
21553 unop( Iop_V128to64
, mkexpr( store_val
) ),
21554 mkU64( 0xFFFFFFFF ) ) );
21557 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21558 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21560 store( irx_addr
, unop( Iop_64to32
, mkexpr( word3
) ) );
21563 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21564 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21566 store( irx_addr
, unop( Iop_64to32
, mkexpr( word2
) ) );
21569 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21570 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21572 store( irx_addr
, unop( Iop_64to32
, mkexpr( word1
) ) );
21575 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21576 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21578 store( irx_addr
, unop( Iop_64to32
, mkexpr( word0
) ) );
21582 case 0x1AD: // stxvll (Store VSX Vector Left-justified with length XX1-form)
21590 IRTemp shift
= newTemp(Ity_I8
);
21591 IRTemp nb_gt16
= newTemp(Ity_I8
);
21592 IRTemp nb_zero
= newTemp(Ity_V128
);
21593 IRTemp nb
= newTemp(Ity_I8
);
21594 IRTemp nb_field
= newTemp(Ity_I64
);
21595 IRTemp n_bytes
= newTemp(Ity_I8
);
21596 IRTemp base_addr
= newTemp( ty
);
21597 IRTemp current_mem
= newTemp(Ity_V128
);
21598 IRTemp store_val
= newTemp(Ity_V128
);
21599 IRTemp nb_mask
= newTemp(Ity_V128
);
21600 IRTemp mask
= newTemp( Ity_I64
);
21604 IRTemp nb_field_compare_zero
= newTemp( Ity_I64
);
21607 DIP("stxvll %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
21609 assign( nb_field
, binop( Iop_Shr64
,
21612 assign( nb
, unop( Iop_64to8
, mkexpr( nb_field
) ) );
21613 assign( mask
, mkU64( 0xFFFFFFFFFFFFFFFFULL
) );
21615 /* nb_gt16 will be all zeros if nb > 16 */
21616 assign( nb_gt16
, unop( Iop_1Sto8
,
21617 binop( Iop_CmpLT64U
,
21619 mkexpr( nb_field
),
21623 assign( nb_field_compare_zero
, unop( Iop_1Sto64
,
21624 binop( Iop_CmpEQ64
,
21625 mkexpr( nb_field
),
21628 /* nb_zero is 0xFF..FF if the nb_field = 0 */
21629 assign( nb_zero
, binop( Iop_64HLtoV128
,
21630 mkexpr( nb_field_compare_zero
),
21631 mkexpr( nb_field_compare_zero
) ) );
21634 /* set n_bytes to 0 if nb >= 16. Otherwise, set to nb. */
21635 assign( n_bytes
, binop( Iop_And8
, mkexpr( nb
), mkexpr( nb_gt16
) ) );
21641 unop( Iop_8Uto64
, mkexpr( n_bytes
) )),
21644 /* We only have a 32-bit store function. So, need to fetch the
21645 * contents of memory merge with the store value and do two
21646 * 32-byte stores so we preserve the contents of memory not
21649 assign( base_addr
, ea_rAor0( rA_addr
) );
21650 /* fetch all 16 bytes and store in Big Endian format */
21651 word0
[0] = newTemp(Ity_I64
);
21652 assign( word0
[0], mkU64( 0 ) );
21654 word1
[0] = newTemp(Ity_I64
);
21655 assign( word1
[0], mkU64( 0 ) );
21657 word2
[0] = newTemp(Ity_I64
);
21658 assign( word2
[0], mkU64( 0 ) );
21660 word3
[0] = newTemp(Ity_I64
);
21661 assign( word3
[0], mkU64( 0 ) );
21663 for (i
= 0; i
< 4; i
++) {
21664 word0
[i
+1] = newTemp(Ity_I64
);
21666 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21667 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21670 /* Instruction always loads in Big Endian format */
21671 assign( word0
[i
+1],
21678 mkexpr( word0
[i
] ) ) );
21681 for (i
= 0; i
< 4; i
++) {
21682 word1
[i
+1] = newTemp(Ity_I64
);
21684 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21685 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21688 /* Instruction always loads in Big Endian format */
21689 assign( word1
[i
+1],
21696 mkexpr( word1
[i
] ) ) );
21698 for (i
= 0; i
< 4; i
++) {
21699 word2
[i
+1] = newTemp(Ity_I64
);
21701 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21702 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21705 /* Instruction always loads in Big Endian format */
21706 assign( word2
[i
+1],
21713 mkexpr( word2
[i
] ) ) );
21715 for (i
= 0; i
< 4; i
++) {
21716 word3
[i
+1] = newTemp(Ity_I64
);
21718 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21719 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21722 /* Instruction always loads in Big Endian format */
21723 assign( word3
[i
+1],
21730 mkexpr( word3
[i
] ) ) );
21734 assign( current_mem
,
21735 binop( Iop_64HLtoV128
,
21738 mkexpr( word0
[4] ),
21740 mkexpr( word1
[4] ) ),
21743 mkexpr( word2
[4] ),
21745 mkexpr( word3
[4] ) ) ) );
21747 /* Set the nb_mask to all zeros if nb = 0 so the current contents
21748 * of memory get written back without modifications.
21750 * The store_val is a combination of the current memory value
21751 * and the bytes you want to store. The nb_mask selects the
21752 * bytes you want stored from Vs.
21754 /* The instruction always uses Big Endian order */
21757 binop( Iop_AndV128
,
21758 binop( Iop_ShlV128
,
21759 binop( Iop_ShrV128
,
21760 binop( Iop_64HLtoV128
,
21765 unop( Iop_NotV128
, mkexpr( nb_zero
) ) ),
21766 binop( Iop_AndV128
,
21768 binop( Iop_64HLtoV128
,
21770 mkU64( 0x0 ) ) ) ) );
21774 binop( Iop_AndV128
,
21776 mkexpr( nb_mask
) ),
21777 binop( Iop_AndV128
,
21778 unop( Iop_NotV128
, mkexpr( nb_mask
) ),
21779 mkexpr( current_mem
) ) ) );
21781 /* store the merged value in Big Endian format */
21782 tmp_low
[0] = newTemp(Ity_I64
);
21783 tmp_hi
[0] = newTemp(Ity_I64
);
21784 assign( tmp_low
[0], mkU64( 0 ) );
21785 assign( tmp_hi
[0], mkU64( 0 ) );
21787 for (i
= 0; i
< 8; i
++) {
21788 byte
[i
] = newTemp(Ity_I64
);
21789 byte
[i
+8] = newTemp(Ity_I64
);
21790 tmp_low
[i
+1] = newTemp(Ity_I64
);
21791 tmp_hi
[i
+1] = newTemp(Ity_I64
);
21793 assign( byte
[i
], binop( Iop_And64
,
21795 unop( Iop_V128HIto64
,
21796 mkexpr( store_val
) ),
21799 assign( byte
[i
+8], binop( Iop_And64
,
21801 unop( Iop_V128to64
,
21802 mkexpr( store_val
) ),
21806 assign( tmp_low
[i
+1],
21808 mkexpr( tmp_low
[i
] ),
21809 binop( Iop_Shl64
, mkexpr( byte
[i
] ), mkU8( i
*8 ) ) ) );
21810 assign( tmp_hi
[i
+1],
21812 mkexpr( tmp_hi
[i
] ),
21813 binop( Iop_Shl64
, mkexpr( byte
[i
+8] ),
21817 /* Store the value in 32-byte chunks */
21819 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21820 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21822 store( irx_addr
, unop( Iop_64to32
, mkexpr( tmp_low
[8] ) ) );
21825 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21826 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21828 store( irx_addr
, unop( Iop_64HIto32
, mkexpr( tmp_low
[8] ) ) );
21831 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21832 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21834 store( irx_addr
, unop( Iop_64to32
, mkexpr( tmp_hi
[8] ) ) );
21837 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
21838 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21840 store( irx_addr
, unop( Iop_64HIto32
, mkexpr( tmp_hi
[8] ) ) );
21847 IRTemp high64
= newTemp(Ity_F64
);
21848 IRTemp val32
= newTemp(Ity_I32
);
21849 DIP("stxsspx %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
21850 assign(high64
, unop( Iop_ReinterpI64asF64
,
21851 unop( Iop_V128HIto64
, mkexpr( vS
) ) ) );
21852 assign(val32
, unop( Iop_ReinterpF32asI32
,
21853 unop( Iop_TruncF64asF32
,
21854 mkexpr(high64
) ) ) );
21855 store( mkexpr( EA
), mkexpr( val32
) );
21861 DIP("stxsdx %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
21862 high64
= unop( Iop_V128HIto64
, mkexpr( vS
) );
21863 store( mkexpr( EA
), high64
);
21867 case 0x38D: // stxsibx
21869 IRExpr
*stored_word
;
21870 IRTemp byte_to_store
= newTemp( Ity_I64
);
21872 DIP("stxsibx %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
21874 /* Can't store just a byte, need to fetch the word at EA merge data
21877 stored_word
= load( Ity_I64
, mkexpr( EA
) );
21878 assign( byte_to_store
, binop( Iop_And64
,
21879 unop( Iop_V128HIto64
,
21883 store( mkexpr( EA
), binop( Iop_Or64
,
21886 mkU64( 0xFFFFFFFFFFFFFF00 ) ),
21887 mkexpr( byte_to_store
) ) );
21891 case 0x3AD: // stxsihx
21893 IRExpr
*stored_word
;
21894 IRTemp byte_to_store
= newTemp( Ity_I64
);
21896 DIP("stxsihx %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
21898 /* Can't store just a halfword, need to fetch the word at EA merge data
21901 stored_word
= load( Ity_I64
, mkexpr( EA
) );
21902 assign( byte_to_store
, binop( Iop_And64
,
21903 unop( Iop_V128HIto64
,
21905 mkU64( 0xFFFF ) ) );
21907 store( mkexpr( EA
), binop( Iop_Or64
,
21910 mkU64( 0xFFFFFFFFFFFF0000 ) ),
21911 mkexpr( byte_to_store
) ) );
21917 IRExpr
* high64
, *low64
;
21918 DIP("stxvd2x %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
21919 high64
= unop( Iop_V128HIto64
, mkexpr( vS
) );
21920 low64
= unop( Iop_V128to64
, mkexpr( vS
) );
21921 store( mkexpr( EA
), high64
);
21922 store( binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21923 ty
== Ity_I64
? mkU64( 8 ) : mkU32( 8 ) ), low64
);
21930 IRTemp hi64
= newTemp( Ity_I64
);
21931 IRTemp lo64
= newTemp( Ity_I64
);
21933 DIP("stxvw4x %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
21935 // This instruction supports word-aligned stores, so EA may not be
21936 // quad-word aligned. Therefore, do 4 individual word-size stores.
21937 assign( hi64
, unop( Iop_V128HIto64
, mkexpr( vS
) ) );
21938 assign( lo64
, unop( Iop_V128to64
, mkexpr( vS
) ) );
21939 store( mkexpr( EA
), unop( Iop_64HIto32
, mkexpr( hi64
) ) );
21941 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21942 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21943 store( irx_addr
, unop( Iop_64to32
, mkexpr( hi64
) ) );
21945 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21946 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21947 store( irx_addr
, unop( Iop_64HIto32
, mkexpr( lo64
) ) );
21949 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
21950 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
21951 store( irx_addr
, unop( Iop_64to32
, mkexpr( lo64
) ) );
21955 case 0x3AC: // stxvh8x Store VSX Vector Halfword*8 Indexed
21959 IRTemp half_word0
= newTemp( Ity_I64
);
21960 IRTemp half_word1
= newTemp( Ity_I64
);
21961 IRTemp half_word2
= newTemp( Ity_I64
);
21962 IRTemp half_word3
= newTemp( Ity_I64
);
21963 IRTemp half_word4
= newTemp( Ity_I64
);
21964 IRTemp half_word5
= newTemp( Ity_I64
);
21965 IRTemp half_word6
= newTemp( Ity_I64
);
21966 IRTemp half_word7
= newTemp( Ity_I64
);
21968 DIP("stxvb8x %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
21970 assign( half_word0
, binop( Iop_Shr64
,
21971 unop( Iop_V128HIto64
, mkexpr( vS
) ),
21974 assign( half_word1
, binop( Iop_And64
,
21976 unop( Iop_V128HIto64
, mkexpr( vS
) ),
21978 mkU64( 0xFFFF ) ) );
21980 assign( half_word2
, binop( Iop_And64
,
21982 unop( Iop_V128HIto64
, mkexpr( vS
) ),
21984 mkU64( 0xFFFF ) ) );
21986 assign( half_word3
, binop( Iop_And64
,
21987 unop( Iop_V128HIto64
, mkexpr( vS
) ),
21988 mkU64( 0xFFFF ) ) );
21990 assign( half_word4
, binop( Iop_Shr64
,
21991 unop( Iop_V128to64
, mkexpr( vS
) ),
21994 assign( half_word5
, binop( Iop_And64
,
21996 unop( Iop_V128to64
, mkexpr( vS
) ),
21998 mkU64( 0xFFFF ) ) );
22000 assign( half_word6
, binop( Iop_And64
,
22002 unop( Iop_V128to64
, mkexpr( vS
) ),
22004 mkU64( 0xFFFF ) ) );
22006 assign( half_word7
, binop( Iop_And64
,
22007 unop( Iop_V128to64
, mkexpr( vS
) ),
22008 mkU64( 0xFFFF ) ) );
22010 /* Do the 32-bit stores. The store() does an Endian aware store. */
22011 if ( host_endness
== VexEndnessBE
) {
22012 store( mkexpr( EA
), unop( Iop_64to32
,
22014 mkexpr( half_word1
),
22016 mkexpr( half_word0
),
22017 mkU8( 16 ) ) ) ) );
22020 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
22021 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
22024 store( irx_addr
, unop( Iop_64to32
,
22026 mkexpr( half_word3
),
22028 mkexpr( half_word2
),
22029 mkU8( 16 ) ) ) ) );
22032 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
22033 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
22035 store( irx_addr
, unop( Iop_64to32
,
22037 mkexpr( half_word5
),
22039 mkexpr( half_word4
),
22040 mkU8( 16 ) ) ) ) );
22042 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
22043 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
22045 store( irx_addr
, unop( Iop_64to32
,
22047 mkexpr( half_word7
),
22049 mkexpr( half_word6
),
22050 mkU8( 16 ) ) ) ) );
22053 store( mkexpr( EA
), unop( Iop_64to32
,
22055 mkexpr( half_word0
),
22057 mkexpr( half_word1
),
22058 mkU8( 16 ) ) ) ) );
22061 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
22062 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
22064 store( irx_addr
, unop( Iop_64to32
,
22066 mkexpr( half_word2
),
22068 mkexpr( half_word3
),
22069 mkU8( 16 ) ) ) ) );
22071 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
22072 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
22074 store( irx_addr
, unop( Iop_64to32
,
22076 mkexpr( half_word4
),
22078 mkexpr( half_word5
),
22079 mkU8( 16 ) ) ) ) );
22081 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
22082 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
22084 store( irx_addr
, unop( Iop_64to32
,
22086 mkexpr( half_word6
),
22088 mkexpr( half_word7
),
22089 mkU8( 16 ) ) ) ) );
22094 case 0x3EC: // stxvb16x Store VSX Vector Byte*16 Indexed
22101 DIP("stxvb16x %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
22103 for ( i
= 0; i
< 8; i
++ ) {
22104 byte
[i
] = newTemp( Ity_I64
);
22105 byte
[i
+8] = newTemp( Ity_I64
);
22107 assign( byte
[i
], binop( Iop_And64
,
22109 unop( Iop_V128HIto64
, mkexpr( vS
) ),
22110 mkU8( 56 - i
*8 ) ),
22113 assign( byte
[i
+8], binop( Iop_And64
,
22115 unop( Iop_V128to64
, mkexpr( vS
) ),
22120 if ( host_endness
== VexEndnessBE
) {
22121 for ( i
= 0; i
< 16; i
= i
+ 4) {
22123 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
22124 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
22130 mkexpr( byte
[i
+3] ),
22132 mkexpr( byte
[i
+2] ),
22136 mkexpr( byte
[i
+1] ),
22140 mkU8( 24 ) ) ) ) ) );
22145 for ( i
= 0; i
< 16; i
= i
+ 4) {
22147 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
22148 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
22156 mkexpr( byte
[i
+1] ),
22160 mkexpr( byte
[i
+2] ),
22163 mkexpr( byte
[i
+3] ),
22164 mkU8( 24 ) ) ) ) ) );
22173 vex_printf( "dis_vx_store(ppc)(opc2)\n" );
22180 dis_vx_Scalar_Round_to_quad_integer( UInt theInstr
, const VexAbiInfo
* vbi
)
22182 /* The ISA 3.0 instructions supported in this function require
22183 * the underlying hardware platform that supports the ISA3.0
22187 UChar opc1
= ifieldOPC( theInstr
);
22188 UInt opc2
= IFIELD( theInstr
, 1, 8 );
22189 UChar vT_addr
= ifieldRegDS( theInstr
);
22190 UChar vB_addr
= ifieldRegB( theInstr
);
22191 IRTemp vB
= newTemp( Ity_F128
);
22192 IRTemp vT
= newTemp( Ity_F128
);
22193 UChar EX
= IFIELD( theInstr
, 0, 1 );
22195 assign( vB
, getF128Reg( vB_addr
) );
22196 if (opc1
!= 0x3F) {
22197 vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(instr)\n" );
22201 case 0x005: // VSX Scalar Round to Quad-Precision Integer [with Inexact]
22203 UChar R
= IFIELD( theInstr
, 16, 1 );
22204 UChar RMC
= IFIELD( theInstr
, 9, 2 );
22206 /* Store the rm specification bits. Will extract them later when
22207 * the isntruction is issued.
22209 IRExpr
* rm
= mkU32( R
<< 3 | RMC
<< 1 | EX
);
22211 if ( EX
== 0 ) { // xsrqpi
22212 DIP("xsrqpi %d,v%d,v%d,%d\n", R
, vT_addr
, vB_addr
, RMC
);
22213 assign( vT
, binop( Iop_F128toI128S
, rm
, mkexpr( vB
) ) );
22215 } else { // xsrqpix
22216 DIP("xsrqpix %d,v%d,v%d,%d\n", R
, vT_addr
, vB_addr
, RMC
);
22217 assign( vT
, binop( Iop_F128toI128S
, rm
, mkexpr( vB
) ) );
22219 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22222 case 0x025: // xsrqpxp VSX Scalar Round Quad-Precision to
22223 // Double-Extended Precision
22225 UChar R
= IFIELD( theInstr
, 16, 1 );
22226 UChar RMC
= IFIELD( theInstr
, 9, 2 );
22228 /* Store the rm specification bits. Will extract them later when
22229 * the isntruction is issued.
22231 IRExpr
* rm
= mkU32( R
<< 3 | RMC
<< 1 );
22233 DIP("xsrqpxp %d,v%d,v%d,%d\n", R
, vT_addr
, vB_addr
, RMC
);
22234 assign( vT
, binop( Iop_RndF128
, rm
, mkexpr( vB
) ) );
22235 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22239 vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(opc2)\n" );
22241 } /* switch opc2 */
22242 putF128Reg( vT_addr
, mkexpr( vT
) );
22247 dis_vx_Floating_Point_Arithmetic_quad_precision( UInt theInstr
,
22248 const VexAbiInfo
* vbi
)
22250 /* The ISA 3.0 instructions supported in this function require
22251 * the underlying hardware platform that supports the ISA 3.0
22255 UChar opc1
= ifieldOPC( theInstr
);
22256 UInt opc2
= ifieldOPClo10( theInstr
);
22257 UChar vT_addr
= ifieldRegDS( theInstr
);
22258 UChar vA_addr
= ifieldRegA( theInstr
);
22259 UChar vB_addr
= ifieldRegB( theInstr
);
22260 IRTemp vA
= newTemp( Ity_F128
);
22261 IRTemp vB
= newTemp( Ity_F128
);
22262 IRTemp vT
= newTemp( Ity_F128
);
22263 IRExpr
* rm
= get_IR_roundingmode();
22264 UChar R0
= IFIELD( theInstr
, 0, 1 );
22266 assign( vB
, getF128Reg( vB_addr
) );
22268 if ( opc1
!= 0x3F ) {
22269 vex_printf( "Erorr, dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(instr)\n" );
22273 case 0x004: // xsaddqp (VSX Scalar Add Quad-Precision[using round to Odd])
22275 assign( vA
, getF128Reg( vA_addr
) );
22278 /* rounding mode specified by RN. Issue inst with R0 = 0 */
22279 DIP("xsaddqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22280 assign( vT
, triop( Iop_AddF128
, rm
, mkexpr( vA
), mkexpr( vB
) ) );
22283 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
22284 DIP("xsaddqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22285 assign( vT
, triop( Iop_AddF128
, set_round_to_Oddmode(),
22286 mkexpr( vA
), mkexpr( vB
) ) );
22288 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22291 case 0x024: // xsmulqp (VSX Scalar Multiply Quad-Precision[using round to Odd])
22293 assign( vA
, getF128Reg( vA_addr
) );
22296 /* rounding mode specified by RN. Issue inst with R0 = 0 */
22297 DIP("xsmulqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22298 assign( vT
, triop( Iop_MulF128
, rm
, mkexpr( vA
), mkexpr( vB
) ) );
22301 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
22302 DIP("xsmulqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22303 assign( vT
, triop( Iop_MulF128
, set_round_to_Oddmode(), mkexpr( vA
),
22306 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22309 case 0x184: // xsmaddqp (VSX Scalar Multiply add Quad-Precision[using round to Odd])
22311 /* instruction computes (vA * vB) + vC */
22312 IRTemp vC
= newTemp( Ity_F128
);
22314 assign( vA
, getF128Reg( vA_addr
) );
22315 assign( vC
, getF128Reg( vT_addr
) );
22318 /* rounding mode specified by RN. Issue inst with R0 = 0 */
22319 DIP("xsmaddqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22321 qop( Iop_MAddF128
, rm
, mkexpr( vA
),
22322 mkexpr( vC
), mkexpr( vB
) ) );
22325 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
22326 DIP("xsmaddqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22328 qop( Iop_MAddF128
, set_round_to_Oddmode(), mkexpr( vA
),
22329 mkexpr( vC
), mkexpr( vB
) ) );
22331 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22334 case 0x1A4: // xsmsubqp (VSX Scalar Multiply Subtract Quad-Precision[using round to Odd])
22336 IRTemp vC
= newTemp( Ity_F128
);
22338 assign( vA
, getF128Reg( vA_addr
) );
22339 assign( vC
, getF128Reg( vT_addr
) );
22342 /* rounding mode specified by RN. Issue inst with R0 = 0 */
22343 DIP("xsmsubqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22345 qop( Iop_MSubF128
, rm
, mkexpr( vA
),
22346 mkexpr( vC
), mkexpr( vB
) ) );
22349 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
22350 DIP("xsmsubqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22352 qop( Iop_MSubF128
, set_round_to_Oddmode(),
22353 mkexpr( vA
), mkexpr( vC
), mkexpr( vB
) ) );
22355 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22358 case 0x1C4: // xsnmaddqp (VSX Scalar Negative Multiply Add Quad-Precision[using round to Odd])
22360 IRTemp vC
= newTemp( Ity_F128
);
22362 assign( vA
, getF128Reg( vA_addr
) );
22363 assign( vC
, getF128Reg( vT_addr
) );
22366 /* rounding mode specified by RN. Issue inst with R0 = 0 */
22367 DIP("xsnmaddqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22369 qop( Iop_NegMAddF128
, rm
, mkexpr( vA
),
22370 mkexpr( vC
), mkexpr( vB
) ) );
22373 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
22374 DIP("xsnmaddqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22376 qop( Iop_NegMAddF128
, set_round_to_Oddmode(),
22377 mkexpr( vA
), mkexpr( vC
), mkexpr( vB
) ) );
22379 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22382 case 0x1E4: // xsmsubqp (VSX Scalar Negatve Multiply Subtract Quad-Precision[using round to Odd])
22384 IRTemp vC
= newTemp( Ity_F128
);
22386 assign( vA
, getF128Reg( vA_addr
) );
22387 assign( vC
, getF128Reg( vT_addr
) );
22390 /* rounding mode specified by RN. Issue inst with R0 = 0 */
22391 DIP("xsnmsubqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22393 qop( Iop_NegMSubF128
, rm
, mkexpr( vA
),
22394 mkexpr( vC
), mkexpr( vB
) ) );
22397 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
22398 DIP("xsnmsubqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22400 qop( Iop_NegMSubF128
, set_round_to_Oddmode(),
22401 mkexpr( vA
), mkexpr( vC
), mkexpr( vB
) ) );
22403 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22406 case 0x204: // xssubqp (VSX Scalar Subtract Quad-Precision[using round to Odd])
22408 assign( vA
, getF128Reg( vA_addr
) );
22410 /* use rounding mode specified by RN. Issue inst with R0 = 0 */
22411 DIP("xssubqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22412 assign( vT
, triop( Iop_SubF128
, rm
, mkexpr( vA
), mkexpr( vB
) ) );
22415 /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */
22416 DIP("xssubqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22417 assign( vT
, triop( Iop_SubF128
, set_round_to_Oddmode(), mkexpr( vA
),
22420 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22423 case 0x224: // xsdivqp (VSX Scalar Divide Quad-Precision[using round to Odd])
22425 assign( vA
, getF128Reg( vA_addr
) );
22427 /* use rounding mode specified by RN. Issue inst with R0 = 0 */
22428 DIP("xsdivqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22429 assign( vT
, triop( Iop_DivF128
, rm
, mkexpr( vA
), mkexpr( vB
) ) );
22432 /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */
22433 DIP("xsdivqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22434 assign( vT
, triop( Iop_DivF128
, set_round_to_Oddmode(), mkexpr( vA
),
22437 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22440 case 0x324: // xssqrtqp (VSX Scalar Square root Quad-Precision[using round to Odd])
22442 UInt inst_select
= IFIELD( theInstr
, 16, 5 );
22444 switch (inst_select
) {
22447 if ( R0
== 0 ) { // xssqrtqp
22448 /* rounding mode specified by RN. Issue inst with R0 = 0 */
22449 DIP("xssqrtqp v%d,v%d\n", vT_addr
, vB_addr
);
22450 assign( vT
, binop( Iop_SqrtF128
, rm
, mkexpr( vB
) ) );
22452 } else { // xssqrtqpo
22453 /* rounding mode is Round to odd. Issue inst with R0 = 1 */
22454 DIP("xssqrtqpo v%d,v%d\n", vT_addr
, vB_addr
);
22455 assign( vT
, binop( Iop_SqrtF128
, set_round_to_Oddmode(),
22458 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22460 } /* end case 27 */
22462 vex_printf("dis_vx_Floating_Point_Arithmetic_quad_precision(0x324 unknown inst_select)\n");
22464 } /* end switch inst_select */
22466 } /* end case 0x324 */
22470 UInt inst_select
= IFIELD( theInstr
, 16, 5);
22472 switch (inst_select
) {
22473 case 1: // xscvqpuwz VSX Scalar Truncate & Convert Quad-Precision
22474 // format to Unsigned Word format
22476 DIP("xscvqpuwz v%d,v%d\n", vT_addr
, vB_addr
);
22477 assign( vT
, unop( Iop_TruncF128toI32U
, mkexpr( vB
) ) );
22480 case 2: // xscvudqp VSX Scalar Convert from Unsigned Doubleword
22481 // format to Quad-Precision format
22483 IRTemp tmp
= newTemp( Ity_I64
);
22485 DIP("xscvudqp v%d,v%d\n", vT_addr
, vB_addr
);
22486 assign( tmp
, unop( Iop_ReinterpF64asI64
,
22487 unop( Iop_F128HItoF64
, mkexpr( vB
) ) ) );
22488 assign( vT
, unop( Iop_I64UtoF128
, mkexpr( tmp
) ) );
22489 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22492 case 9: // xsvqpswz VSX Scalar Truncate & Convert Quad-Precision
22493 // format to Signed Word format
22495 DIP("xscvqpswz v%d,v%d\n", vT_addr
, vB_addr
);
22496 assign( vT
, unop( Iop_TruncF128toI32S
, mkexpr( vB
) ) );
22499 case 10: // xscvsdqp VSX Scalar from Signed Doubleword format
22500 // Quad-Precision format
22502 IRTemp tmp
= newTemp( Ity_I64
);
22504 DIP("xscvsdqp v%d,v%d\n", vT_addr
, vB_addr
);
22506 assign( tmp
, unop( Iop_ReinterpF64asI64
,
22507 unop( Iop_F128HItoF64
, mkexpr( vB
) ) ) );
22508 assign( vT
, unop( Iop_I64StoF128
, mkexpr( tmp
) ) );
22509 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22512 case 17: // xsvqpudz VSX Scalar Truncate & Convert Quad-Precision
22513 // format to Unigned Doubleword format
22515 DIP("xscvqpudz v%d,v%d\n", vT_addr
, vB_addr
);
22516 assign( vT
, unop( Iop_TruncF128toI64U
, mkexpr( vB
) ) );
22519 case 20: // xscvqpdp Scalar round & Conver Quad-Precision
22520 // format to Double-Precision format [using round to Odd]
22522 IRTemp ftmp
= newTemp( Ity_F64
);
22523 IRTemp tmp
= newTemp( Ity_I64
);
22525 /* This instruction takes a 128-bit floating point value and
22526 * converts it to a 64-bit floating point value. The 64-bit
22527 * result is stored in the upper 64-bit of the 128-bit result
22528 * register. The lower 64-bit are undefined.
22530 if (R0
== 0) { // xscvqpdp
22531 /* rounding mode specified by RN. Issue inst with R0 = 0 */
22532 DIP("xscvqpdp v%d,v%d\n", vT_addr
, vB_addr
);
22534 assign( ftmp
, binop( Iop_F128toF64
, rm
, mkexpr( vB
) ) );
22536 } else { // xscvqpdpo
22537 /* rounding mode is Round to odd. Issue inst with R0 = 1 */
22538 DIP("xscvqpdpo v%d,v%d\n", vT_addr
, vB_addr
);
22540 binop( Iop_F128toF64
,
22541 set_round_to_Oddmode(), mkexpr( vB
) ) );
22544 /* store 64-bit float in upper 64-bits of 128-bit register,
22545 * lower 64-bits are zero.
22547 if (host_endness
== VexEndnessLE
)
22549 binop( Iop_F64HLtoF128
,
22551 unop( Iop_ReinterpI64asF64
, mkU64( 0 ) ) ) );
22554 binop( Iop_F64HLtoF128
,
22555 unop( Iop_ReinterpI64asF64
, mkU64( 0 ) ),
22556 mkexpr( ftmp
) ) );
22558 assign( tmp
, unop( Iop_ReinterpF64asI64
,
22559 unop( Iop_F128HItoF64
, mkexpr( vT
) ) ) );
22561 generate_store_FPRF( Ity_I64
, tmp
, vbi
);
22564 case 22: // xscvdpqp VSX Scalar Convert from Double-Precision
22565 // format to Quad-Precision format
22567 DIP("xscvdpqp v%d,v%d\n", vT_addr
, vB_addr
);
22568 /* The 64-bit value is in the upper 64 bit of the src */
22569 assign( vT
, unop( Iop_F64toF128
,
22570 unop( Iop_F128HItoF64
, mkexpr( vB
) ) ) );
22572 generate_store_FPRF( Ity_F128
, vT
, vbi
);
22575 case 25: // xsvqpsdz VSX Scalar Truncate & Convert Quad-Precision
22576 // format to Signed Doubleword format
22578 DIP("xscvqpsdz v%d,v%d\n", vT_addr
, vB_addr
);
22579 assign( vT
, unop( Iop_TruncF128toI64S
, mkexpr( vB
) ) );
22583 vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision invalid inst_select (ppc)(opc2)\n" );
22585 } /* switch inst_select */
22586 } /* end case 0x344 */
22588 default: /* switch opc2 */
22589 vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(opc2)\n" );
22592 putF128Reg( vT_addr
, mkexpr( vT
) );
22597 /* VSX Scalar Quad-Precision instructions */
22599 dis_vx_scalar_quad_precision ( UInt theInstr
)
22601 /* This function emulates the 128-bit floating point instructions
22602 * using existing 128-bit vector instructions (Iops). The 128-bit
22603 * floating point instructions use the same 128-bit vector register
22607 UChar opc1
= ifieldOPC( theInstr
);
22608 UInt opc2
= ifieldOPClo10( theInstr
);
22609 UChar vT_addr
= ifieldRegDS( theInstr
) + 32;
22610 UChar vA_addr
= ifieldRegA( theInstr
) + 32;
22611 UChar vB_addr
= ifieldRegB( theInstr
) + 32;
22612 IRTemp vA
= newTemp( Ity_V128
);
22613 IRTemp vB
= newTemp( Ity_V128
);
22614 IRTemp vT
= newTemp( Ity_V128
);
22616 assign( vB
, getVSReg( vB_addr
) );
22618 if (opc1
!= 0x3F) {
22619 vex_printf( "dis_vx_scalar_quad_precision(ppc)(instr)\n" );
22625 case 0x064: // xscpsgnqp (VSX Scalar Copy Sign Quad-Precision)
22627 IRTemp sign_vA
= newTemp( Ity_I64
);
22628 IRTemp vB_hi
= newTemp( Ity_I64
);
22630 DIP("xscpsgnqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22632 assign( vA
, getVSReg(vA_addr
) );
22634 assign( sign_vA
, binop( Iop_And64
,
22635 unop( Iop_V128HIto64
,
22637 mkU64( 0x8000000000000000ULL
) ) );
22638 assign( vB_hi
, binop( Iop_Or64
,
22640 unop( Iop_V128HIto64
,
22642 mkU64( 0x7FFFFFFFFFFFFFFFULL
) ),
22643 mkexpr( sign_vA
) ) );
22644 assign( vT
, binop( Iop_64HLtoV128
,
22646 unop( Iop_V128to64
, mkexpr( vB
) ) ) );
22650 case 0x084: // xscmpoqp (VSX Scalar Compare Ordered Quad-Precision)
22651 case 0x284: // xscmpuqp (VSX Scalar Compare Unrdered Quad-Precision)
22653 /* Note, only differece between xscmoqp and xscmpuqp is the
22654 exception flag settings which are not supported anyway. */
22655 IRExpr
*bit4
, *bit5
, *bit6
, *bit7
;
22656 IRExpr
*bit_zero
, *bit_inf
, *same_sign
;
22657 UInt BF
= IFIELD( theInstr
, 23, 3 );
22658 IRTemp eq_lt_gt
= newTemp( Ity_I32
);
22659 IRTemp CC
= newTemp( Ity_I32
);
22661 if (opc2
== 0x084) {
22662 DIP("xscmpoqp %u,v%d,v%u\n", BF
, vA_addr
, vB_addr
);
22664 DIP("xscmpuqp %u,v%d,v%u\n", BF
, vA_addr
, vB_addr
);
22667 assign( vA
, getVSReg(vA_addr
));
22669 /* A and B have the same sign */
22670 same_sign
= binop( Iop_CmpEQ64
,
22672 unop( Iop_V128HIto64
,
22676 unop( Iop_V128HIto64
,
22681 bit4
= Quad_precision_gt( vB
, vA
);
22684 bit5
= Quad_precision_gt( vA
, vB
);
22687 bit6
= mkAND1( binop( Iop_CmpEQ64
,
22688 unop( Iop_V128HIto64
,
22690 unop( Iop_V128HIto64
,
22692 binop( Iop_CmpEQ64
,
22693 unop( Iop_V128to64
,
22695 unop( Iop_V128to64
,
22696 mkexpr( vB
) ) ) );
22698 /* test both zero don't care about sign */
22699 bit_zero
= mkAND1( is_Zero( Ity_V128
, vA
), is_Zero( Ity_V128
, vB
) );
22701 /* test both for infinity, don't care about sign */
22703 mkAND1( is_Inf( Ity_V128
, vA
), is_Inf( Ity_V128
, vB
) ),
22704 binop( Iop_CmpEQ64
,
22706 unop( Iop_V128to64
,
22708 mkU64( 0x80000000) ),
22710 unop( Iop_V128to64
,
22712 mkU64( 0x80000000) ) ) );
22714 /* exp A or exp B is NaN */
22715 bit7
= mkOR1( is_NaN( Ity_V128
, vA
),
22716 is_NaN( Ity_V128
, vB
) );
22722 unop( Iop_1Uto32
, bit4
),
22725 unop( Iop_1Uto32
, bit5
),
22729 unop( Iop_1Uto32
, bit6
),
22738 mkAND1( bit_inf
, same_sign
) ),
22739 mkU8( 1 ) ) ) ) ) );
22741 assign(CC
, binop( Iop_Or32
,
22744 unop( Iop_1Sto32
, bit7
) ),
22745 mkexpr( eq_lt_gt
) ),
22746 unop( Iop_1Uto32
, bit7
) ) );
22748 /* put result of the comparison into CC and FPCC */
22749 putGST_field( PPC_GST_CR
, mkexpr( CC
), BF
);
22750 putFPCC( mkexpr( CC
) );
22755 case 0xA4: // xscmpexpqp (VSX Scalar Compare Exponents Double-Precision)
22757 IRExpr
*bit4
, *bit5
, *bit6
, *bit7
;
22758 UInt BF
= IFIELD( theInstr
, 23, 3 );
22760 IRTemp eq_lt_gt
= newTemp( Ity_I32
);
22761 IRTemp CC
= newTemp( Ity_I32
);
22763 DIP("xscmpexpqp %u,v%d,v%u\n", BF
, vA_addr
, vB_addr
);
22765 assign( vA
, getVSReg(vA_addr
));
22767 /* A exp < B exp */
22768 bit4
= binop( Iop_CmpLT64U
,
22770 unop( Iop_V128HIto64
,
22772 mkU64( 0x7FFF000000000000 ) ),
22774 unop( Iop_V128HIto64
,
22776 mkU64( 0x7FFF000000000000 ) ) );
22778 bit5
= binop( Iop_CmpLT64U
,
22780 unop( Iop_V128HIto64
,
22782 mkU64( 0x7FFF000000000000 ) ),
22784 unop( Iop_V128HIto64
,
22786 mkU64( 0x7FFF000000000000 ) ) );
22788 bit6
= binop( Iop_CmpEQ64
,
22790 unop( Iop_V128HIto64
,
22792 mkU64( 0x7FFF000000000000 ) ),
22794 unop( Iop_V128HIto64
,
22796 mkU64( 0x7FFF000000000000 ) ) );
22798 /* exp A or exp B is NaN */
22799 bit7
= mkOR1( is_NaN( Ity_V128
, vA
),
22800 is_NaN( Ity_V128
, vB
) );
22802 /* NaN over rules the other comparisons */
22803 assign( eq_lt_gt
, binop( Iop_Or32
,
22805 unop( Iop_1Uto32
, bit4
),
22809 unop( Iop_1Uto32
, bit5
),
22812 unop( Iop_1Uto32
, bit6
),
22814 assign(CC
, binop( Iop_Or32
,
22817 unop( Iop_1Sto32
, bit7
) ),
22818 mkexpr( eq_lt_gt
) ),
22819 unop( Iop_1Uto32
, bit7
) ) );
22821 /* put result of the comparison into CC and FPCC */
22822 putGST_field( PPC_GST_CR
, mkexpr( CC
), BF
);
22823 putFPCC( mkexpr( CC
) );
22828 case 0x2C4: // xststdcqp (VSX Scalar Quad-Precision Test Data Class)
22830 UInt BF
= IFIELD( theInstr
, 23, 3 );
22831 UInt DCMX_mask
= IFIELD( theInstr
, 16, 7 );
22832 IRTemp CC
= newTemp( Ity_I64
);
22833 IRTemp NaN
= newTemp( Ity_I64
);
22834 IRTemp inf
= newTemp( Ity_I64
);
22835 IRTemp pos
= newTemp( Ity_I64
);
22836 IRTemp DCM
= newTemp( Ity_I64
);
22837 IRTemp zero
= newTemp( Ity_I64
);
22838 IRTemp dnorm
= newTemp( Ity_I64
);
22840 DIP("xststdcqp %u,v%d,%u\n", BF
, vB_addr
, DCMX_mask
);
22842 assign( zero
, unop( Iop_1Uto64
, is_Zero( Ity_V128
, vB
) ) );
22843 assign( pos
, unop( Iop_1Uto64
,
22844 binop( Iop_CmpEQ64
,
22846 unop( Iop_V128HIto64
,
22851 assign( NaN
, unop( Iop_1Uto64
, is_NaN( Ity_V128
, vB
) ) );
22852 assign( inf
, unop( Iop_1Uto64
, is_Inf( Ity_V128
, vB
) ) );
22854 assign( dnorm
, unop( Iop_1Uto64
, is_Denorm( Ity_V128
, vB
) ) );
22855 assign( DCM
, create_DCM( Ity_I64
, NaN
, inf
, zero
, dnorm
, pos
) );
22856 assign( CC
, binop( Iop_Or64
,
22857 binop( Iop_And64
, /* vB sign bit */
22859 unop( Iop_V128HIto64
, mkexpr( vB
) ),
22864 binop( Iop_CmpNE64
,
22867 mkU64( DCMX_mask
) ),
22871 putGST_field( PPC_GST_CR
, unop(Iop_64to32
, mkexpr( CC
) ), BF
);
22872 putFPCC( unop(Iop_64to32
, mkexpr( CC
) ) );
22877 case 0x324: // xsabsqp (VSX Scalar Absolute Quad-Precision)
22878 // xsxexpqp (VSX Scalaar Extract Exponent Quad-Precision)
22879 // xsnabsqp (VSX Scalar Negative Absolute Quad-Precision)
22880 // xsnegqp (VSX Scalar Negate Quad-Precision)
22881 // xsxsigqp (VSX Scalar Extract Significand Quad-Precision)
22883 UInt inst_select
= IFIELD( theInstr
, 16, 5);
22885 switch (inst_select
) {
22887 DIP("xsabsqp v%d,v%d\n", vT_addr
, vB_addr
);
22888 assign( vT
, binop( Iop_AndV128
, mkexpr( vB
),
22889 binop( Iop_64HLtoV128
,
22890 mkU64( 0x7FFFFFFFFFFFFFFF ),
22891 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) );
22895 DIP("xsxexpqp v%d,v%d\n", vT_addr
, vB_addr
);
22896 assign( vT
, binop( Iop_ShrV128
,
22897 binop( Iop_AndV128
, mkexpr( vB
),
22898 binop( Iop_64HLtoV128
,
22899 mkU64( 0x7FFF000000000000 ),
22900 mkU64( 0x0000000000000000 ) ) ),
22905 DIP("xsnabsqp v%d,v%d\n", vT_addr
, vB_addr
);
22906 assign( vT
, binop( Iop_OrV128
, mkexpr( vB
),
22907 binop( Iop_64HLtoV128
,
22908 mkU64( 0x8000000000000000 ),
22909 mkU64( 0x0000000000000000 ) ) ) );
22913 DIP("xsnegqp v%d,v%d\n", vT_addr
, vB_addr
);
22914 assign( vT
, binop( Iop_XorV128
, mkexpr( vB
),
22915 binop( Iop_64HLtoV128
,
22916 mkU64( 0x8000000000000000 ),
22917 mkU64( 0x0000000000000000 ) ) ) );
22922 IRTemp expZero
= newTemp( Ity_I64
);
22923 IRTemp expInfinity
= newTemp( Ity_I64
);
22925 DIP("xsxsigqp v%d,v%d\n", vT_addr
, vB_addr
);
22927 assign( expZero
, unop( Iop_1Uto64
,
22928 binop( Iop_CmpNE64
,
22930 unop( Iop_V128HIto64
,
22932 mkU64( 0x7FFF000000000000 ) ),
22933 mkU64( 0x0 ) ) ) );
22935 assign( expInfinity
,
22937 binop( Iop_CmpNE64
,
22939 unop( Iop_V128HIto64
,
22941 mkU64( 0x7FFF000000000000 ) ),
22942 mkU64( 0x7FFF000000000000 ) ) ) );
22944 /* Clear upper 16 bits to 0x0000. If the exp was zero or infinity
22945 * set bit 48 (lsb = 0) to 0, otherwise set bit 48 to 1.
22949 binop( Iop_ShrV128
,
22950 binop( Iop_ShlV128
,
22954 binop( Iop_64HLtoV128
,
22958 mkexpr( expInfinity
) ),
22965 vex_printf( "dis_vx_scalar_quad_precision invalid inst_select (ppc)(opc2)\n" );
22970 case 0x364: // xsiexpqp (VST Scalar Insert Exponent Quad-Precision)
22972 IRTemp exp
= newTemp( Ity_I64
);
22974 DIP("xsiexpqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
22976 assign( vA
, getVSReg( vA_addr
) );
22977 assign( exp
, binop( Iop_And64
,
22978 unop( Iop_V128HIto64
,
22980 mkU64( 0x7FFFULL
) ) );
22981 assign( vT
, binop( Iop_64HLtoV128
,
22984 unop( Iop_V128HIto64
,
22986 mkU64( 0x8000FFFFFFFFFFFFULL
) ),
22990 unop( Iop_V128to64
,
22991 mkexpr( vA
) ) ) );
22996 vex_printf( "dis_vx_scalar_quad_precision(ppc)(opc2)\n" );
23001 putVSReg( vT_addr
, mkexpr( vT
) );
23006 * VSX permute and other miscealleous instructions
23009 dis_vx_permute_misc( UInt theInstr
, UInt opc2
)
23012 UChar opc1
= ifieldOPC( theInstr
);
23013 UChar XT
= ifieldRegXT ( theInstr
);
23014 UChar XA
= ifieldRegXA ( theInstr
);
23015 UChar XB
= ifieldRegXB ( theInstr
);
23016 IRTemp vT
= newTemp( Ity_V128
);
23017 IRTemp vA
= newTemp( Ity_V128
);
23018 IRTemp vB
= newTemp( Ity_V128
);
23020 if (opc1
!= 0x3C) {
23021 vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
23025 assign( vA
, getVSReg( XA
) );
23026 assign( vB
, getVSReg( XB
) );
23029 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
23031 UChar SHW
= ifieldSHW ( theInstr
);
23032 IRTemp result
= newTemp(Ity_V128
);
23034 IRTemp hi
= newTemp(Ity_V128
);
23035 IRTemp lo
= newTemp(Ity_V128
);
23036 assign( hi
, binop(Iop_ShlV128
, mkexpr(vA
), mkU8(SHW
*32)) );
23037 assign( lo
, binop(Iop_ShrV128
, mkexpr(vB
), mkU8(128-SHW
*32)) );
23038 assign ( result
, binop(Iop_OrV128
, mkexpr(hi
), mkexpr(lo
)) );
23040 assign ( result
, mkexpr(vA
) );
23041 DIP("xxsldwi v%d,v%d,v%d,%d\n", XT
, XA
, XB
, SHW
);
23042 putVSReg( XT
, mkexpr(result
) );
23045 case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
23047 UChar DM
= ifieldDM ( theInstr
);
23048 IRTemp hi
= newTemp(Ity_I64
);
23049 IRTemp lo
= newTemp(Ity_I64
);
23052 assign( hi
, unop(Iop_V128to64
, mkexpr(vA
)) );
23054 assign( hi
, unop(Iop_V128HIto64
, mkexpr(vA
)) );
23057 assign( lo
, unop(Iop_V128to64
, mkexpr(vB
)) );
23059 assign( lo
, unop(Iop_V128HIto64
, mkexpr(vB
)) );
23061 assign( vT
, binop(Iop_64HLtoV128
, mkexpr(hi
), mkexpr(lo
)) );
23063 DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT
, XA
, XB
, DM
);
23064 putVSReg( XT
, mkexpr( vT
) );
23067 case 0x48: // xxmrghw (VSX Merge High Word)
23068 case 0xc8: // xxmrglw (VSX Merge Low Word)
23070 const HChar type
= (opc2
== 0x48) ? 'h' : 'l';
23071 IROp word_op
= (opc2
== 0x48) ? Iop_V128HIto64
: Iop_V128to64
;
23072 IRTemp a64
= newTemp(Ity_I64
);
23073 IRTemp ahi32
= newTemp(Ity_I32
);
23074 IRTemp alo32
= newTemp(Ity_I32
);
23075 IRTemp b64
= newTemp(Ity_I64
);
23076 IRTemp bhi32
= newTemp(Ity_I32
);
23077 IRTemp blo32
= newTemp(Ity_I32
);
23079 assign( a64
, unop(word_op
, mkexpr(vA
)) );
23080 assign( ahi32
, unop(Iop_64HIto32
, mkexpr(a64
)) );
23081 assign( alo32
, unop(Iop_64to32
, mkexpr(a64
)) );
23083 assign( b64
, unop(word_op
, mkexpr(vB
)) );
23084 assign( bhi32
, unop(Iop_64HIto32
, mkexpr(b64
)) );
23085 assign( blo32
, unop(Iop_64to32
, mkexpr(b64
)) );
23087 assign( vT
, binop(Iop_64HLtoV128
,
23088 binop(Iop_32HLto64
, mkexpr(ahi32
), mkexpr(bhi32
)),
23089 binop(Iop_32HLto64
, mkexpr(alo32
), mkexpr(blo32
))) );
23091 DIP("xxmrg%cw v%d,v%d,v%d\n", type
, XT
, XA
, XB
);
23092 putVSReg( XT
, mkexpr( vT
) );
23095 case 0x018: // xxsel (VSX Select)
23097 UChar XC
= ifieldRegXC(theInstr
);
23098 IRTemp vC
= newTemp( Ity_V128
);
23099 assign( vC
, getVSReg( XC
) );
23100 DIP("xxsel v%d,v%d,v%d,v%d\n", XT
, XA
, XB
, XC
);
23101 /* vD = (vA & ~vC) | (vB & vC) */
23102 putVSReg( XT
, binop(Iop_OrV128
,
23103 binop(Iop_AndV128
, mkexpr(vA
), unop(Iop_NotV128
, mkexpr(vC
))),
23104 binop(Iop_AndV128
, mkexpr(vB
), mkexpr(vC
))) );
23108 case 0x68: // xxperm (VSX Permute )
23109 case 0xE8: // xxpermr (VSX Permute right-index )
23112 /* The xxperm instruction performs the same operation as
23113 the vperm except the xxperm operates on the VSR register
23114 file. while vperm operates on the VR register file.
23115 Lets borrow some code here from vperm. The mapping of
23116 the source registers is also a little different.
23118 IRTemp a_perm
= newTemp(Ity_V128
);
23119 IRTemp b_perm
= newTemp(Ity_V128
);
23120 IRTemp mask
= newTemp(Ity_V128
);
23121 IRTemp perm_val
= newTemp(Ity_V128
);
23122 IRTemp vB_adj
= newTemp( Ity_V128
);
23124 if ( opc2
== 0x68 ) {
23125 DIP("xxperm v%u,v%u,v%u\n", (UInt
)XT
, (UInt
)XA
, (UInt
)XB
);
23128 /* Same as xperm just the index is 31 - idx */
23129 DIP("xxpermr v%u,v%u,v%u\n", (UInt
)XT
, (UInt
)XA
, (UInt
)XB
);
23132 assign( vT
, getVSReg( XT
) );
23134 if ( opc2
== 0x68 ) // xxperm
23135 assign( vB_adj
, mkexpr( vB
) );
23139 binop( Iop_Sub16x8
,
23140 unop( Iop_Dup8x16
, mkU8( 0x1F ) ),
23143 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
23144 IR specifies, and also to hide irrelevant bits from
23148 binop( Iop_AndV128
, mkexpr( vB_adj
),
23149 unop( Iop_Dup8x16
, mkU8( 0xF ) ) ) );
23151 binop( Iop_Perm8x16
, mkexpr( vA
), mkexpr( perm_val
) ) );
23153 binop( Iop_Perm8x16
, mkexpr( vT
), mkexpr( perm_val
) ) );
23154 assign( mask
, binop( Iop_SarN8x16
,
23155 binop( Iop_ShlN8x16
, mkexpr( vB_adj
),
23158 // dst = (a & ~mask) | (b & mask)
23159 putVSReg( XT
, binop( Iop_OrV128
,
23160 binop( Iop_AndV128
, mkexpr( a_perm
),
23161 unop( Iop_NotV128
, mkexpr( mask
) ) ),
23162 binop( Iop_AndV128
, mkexpr( b_perm
),
23163 mkexpr( mask
) ) ) );
23167 case 0x148: // xxspltw (VSX Splat Word)
23169 UChar UIM
= ifieldRegA(theInstr
) & 3;
23170 UChar sh_uim
= (3 - (UIM
)) * 32;
23171 DIP("xxspltw v%d,v%d,%d\n", XT
, XB
, UIM
);
23174 unop( Iop_V128to32
,
23175 binop( Iop_ShrV128
, mkexpr( vB
), mkU8( sh_uim
) ) ) ) );
23180 vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
23187 AltiVec Load Instructions
23189 static Bool
dis_av_load ( const VexAbiInfo
* vbi
, UInt theInstr
)
23192 UChar opc1
= ifieldOPC(theInstr
);
23193 UChar vD_addr
= ifieldRegDS(theInstr
);
23194 UChar rA_addr
= ifieldRegA(theInstr
);
23195 UChar rB_addr
= ifieldRegB(theInstr
);
23196 UInt opc2
= ifieldOPClo10(theInstr
);
23197 UChar b0
= ifieldBIT0(theInstr
);
23199 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
23200 IRTemp EA
= newTemp(ty
);
23201 IRTemp EA_align16
= newTemp(ty
);
23203 if (opc1
!= 0x1F || b0
!= 0) {
23204 vex_printf("dis_av_load(ppc)(instr)\n");
23208 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
23209 assign( EA_align16
, addr_align( mkexpr(EA
), 16 ) );
23213 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
23215 UInt vD_off
= vectorGuestRegOffset(vD_addr
);
23216 IRExpr
** args_be
= mkIRExprVec_5(
23219 binop(Iop_And32
, mkNarrowTo32(ty
, mkexpr(EA
)),
23222 mkU32(1)/*Big Endian*/);
23223 IRExpr
** args_le
= mkIRExprVec_5(
23226 binop(Iop_And32
, mkNarrowTo32(ty
, mkexpr(EA
)),
23229 mkU32(0)/*Little Endian*/);
23231 d
= unsafeIRDirty_0_N (
23233 "ppc32g_dirtyhelper_LVS",
23234 fnptr_to_fnentry(vbi
, &ppc32g_dirtyhelper_LVS
),
23237 if (host_endness
== VexEndnessBE
)
23238 d
= unsafeIRDirty_0_N (
23240 "ppc64g_dirtyhelper_LVS",
23241 fnptr_to_fnentry(vbi
, &ppc64g_dirtyhelper_LVS
),
23244 d
= unsafeIRDirty_0_N (
23246 "ppc64g_dirtyhelper_LVS",
23247 fnptr_to_fnentry( vbi
, &ppc64g_dirtyhelper_LVS
),
23250 DIP("lvsl v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
23251 /* declare guest state effects */
23253 vex_bzero(&d
->fxState
, sizeof(d
->fxState
));
23254 d
->fxState
[0].fx
= Ifx_Write
;
23255 d
->fxState
[0].offset
= vD_off
;
23256 d
->fxState
[0].size
= sizeof(U128
);
23258 /* execute the dirty call, side-effecting guest state */
23259 stmt( IRStmt_Dirty(d
) );
23262 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
23264 UInt vD_off
= vectorGuestRegOffset(vD_addr
);
23265 IRExpr
** args_be
= mkIRExprVec_5(
23268 binop(Iop_And32
, mkNarrowTo32(ty
, mkexpr(EA
)),
23271 mkU32(1)/*Big Endian*/);
23272 IRExpr
** args_le
= mkIRExprVec_5(
23275 binop(Iop_And32
, mkNarrowTo32(ty
, mkexpr(EA
)),
23278 mkU32(0)/*Little Endian*/);
23281 d
= unsafeIRDirty_0_N (
23283 "ppc32g_dirtyhelper_LVS",
23284 fnptr_to_fnentry(vbi
, &ppc32g_dirtyhelper_LVS
),
23287 if (host_endness
== VexEndnessBE
)
23288 d
= unsafeIRDirty_0_N (
23290 "ppc64g_dirtyhelper_LVS",
23291 fnptr_to_fnentry(vbi
, &ppc64g_dirtyhelper_LVS
),
23294 d
= unsafeIRDirty_0_N (
23296 "ppc64g_dirtyhelper_LVS",
23297 fnptr_to_fnentry( vbi
, &ppc64g_dirtyhelper_LVS
),
23300 DIP("lvsr v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
23301 /* declare guest state effects */
23303 vex_bzero(&d
->fxState
, sizeof(d
->fxState
));
23304 d
->fxState
[0].fx
= Ifx_Write
;
23305 d
->fxState
[0].offset
= vD_off
;
23306 d
->fxState
[0].size
= sizeof(U128
);
23308 /* execute the dirty call, side-effecting guest state */
23309 stmt( IRStmt_Dirty(d
) );
23312 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
23313 DIP("lvebx v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
23314 /* loads addressed byte into vector[EA[0:3]
23315 since all other destination bytes are undefined,
23316 can simply load entire vector from 16-aligned EA */
23317 putVReg( vD_addr
, load(Ity_V128
, mkexpr(EA_align16
)) );
23320 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
23321 DIP("lvehx v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
23322 /* see note for lvebx */
23323 putVReg( vD_addr
, load(Ity_V128
, mkexpr(EA_align16
)) );
23326 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
23327 DIP("lvewx v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
23328 /* see note for lvebx */
23329 putVReg( vD_addr
, load(Ity_V128
, mkexpr(EA_align16
)) );
23332 case 0x067: // lvx (Load Vector Indexed, AV p127)
23333 DIP("lvx v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
23334 putVReg( vD_addr
, load(Ity_V128
, mkexpr(EA_align16
)) );
23337 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
23338 DIP("lvxl v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
23339 putVReg( vD_addr
, load(Ity_V128
, mkexpr(EA_align16
)) );
23343 vex_printf("dis_av_load(ppc)(opc2)\n");
23350 AltiVec Store Instructions
23352 static Bool
dis_av_store ( UInt theInstr
)
23355 UChar opc1
= ifieldOPC(theInstr
);
23356 UChar vS_addr
= ifieldRegDS(theInstr
);
23357 UChar rA_addr
= ifieldRegA(theInstr
);
23358 UChar rB_addr
= ifieldRegB(theInstr
);
23359 UInt opc2
= ifieldOPClo10(theInstr
);
23360 UChar b0
= ifieldBIT0(theInstr
);
23362 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
23363 IRTemp EA
= newTemp(ty
);
23364 IRTemp addr_aligned
= newTemp(ty
);
23365 IRTemp vS
= newTemp(Ity_V128
);
23366 IRTemp eb
= newTemp(Ity_I8
);
23367 IRTemp idx
= newTemp(Ity_I8
);
23369 if (opc1
!= 0x1F || b0
!= 0) {
23370 vex_printf("dis_av_store(ppc)(instr)\n");
23374 assign( vS
, getVReg(vS_addr
));
23375 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
23378 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
23379 DIP("stvebx v%d,r%u,r%u\n", vS_addr
, rA_addr
, rB_addr
);
23380 assign( eb
, binop(Iop_And8
, mkU8(0xF),
23382 mkNarrowTo32(ty
, mkexpr(EA
)) )) );
23383 if (host_endness
== VexEndnessLE
) {
23384 assign( idx
, binop(Iop_Shl8
, mkexpr(eb
), mkU8(3)) );
23386 assign( idx
, binop(Iop_Shl8
,
23387 binop(Iop_Sub8
, mkU8(15), mkexpr(eb
)),
23391 unop( Iop_32to8
, unop(Iop_V128to32
,
23392 binop(Iop_ShrV128
, mkexpr(vS
), mkexpr(idx
)))) );
23395 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
23396 DIP("stvehx v%d,r%u,r%u\n", vS_addr
, rA_addr
, rB_addr
);
23397 assign( addr_aligned
, addr_align(mkexpr(EA
), 2) );
23398 assign( eb
, binop(Iop_And8
, mkU8(0xF),
23399 mkNarrowTo8(ty
, mkexpr(addr_aligned
) )) );
23400 if (host_endness
== VexEndnessLE
) {
23401 assign( idx
, binop(Iop_Shl8
, mkexpr(eb
), mkU8(3)) );
23403 assign( idx
, binop(Iop_Shl8
,
23404 binop(Iop_Sub8
, mkU8(14), mkexpr(eb
)),
23407 store( mkexpr(addr_aligned
),
23408 unop( Iop_32to16
, unop(Iop_V128to32
,
23409 binop(Iop_ShrV128
, mkexpr(vS
), mkexpr(idx
)))) );
23412 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
23413 DIP("stvewx v%d,r%u,r%u\n", vS_addr
, rA_addr
, rB_addr
);
23414 assign( addr_aligned
, addr_align(mkexpr(EA
), 4) );
23415 assign( eb
, binop(Iop_And8
, mkU8(0xF),
23416 mkNarrowTo8(ty
, mkexpr(addr_aligned
) )) );
23417 if (host_endness
== VexEndnessLE
) {
23418 assign( idx
, binop(Iop_Shl8
, mkexpr(eb
), mkU8(3)) );
23420 assign( idx
, binop(Iop_Shl8
,
23421 binop(Iop_Sub8
, mkU8(12), mkexpr(eb
)),
23424 store( mkexpr( addr_aligned
),
23425 unop( Iop_V128to32
,
23426 binop(Iop_ShrV128
, mkexpr(vS
), mkexpr(idx
))) );
23430 case 0x0E7: // stvx (Store Vector Indexed, AV p134)
23431 DIP("stvx v%d,r%u,r%u\n", vS_addr
, rA_addr
, rB_addr
);
23432 store( addr_align( mkexpr(EA
), 16 ), mkexpr(vS
) );
23435 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
23436 DIP("stvxl v%d,r%u,r%u\n", vS_addr
, rA_addr
, rB_addr
);
23437 store( addr_align( mkexpr(EA
), 16 ), mkexpr(vS
) );
23441 vex_printf("dis_av_store(ppc)(opc2)\n");
23448 AltiVec Arithmetic Instructions
23450 static Bool
dis_av_arith ( UInt theInstr
)
23453 UChar opc1
= ifieldOPC(theInstr
);
23454 UChar vD_addr
= ifieldRegDS(theInstr
);
23455 UChar vA_addr
= ifieldRegA(theInstr
);
23456 UChar vB_addr
= ifieldRegB(theInstr
);
23457 UInt opc2
= IFIELD( theInstr
, 0, 11 );
23459 IRTemp vA
= newTemp(Ity_V128
);
23460 IRTemp vB
= newTemp(Ity_V128
);
23461 IRTemp z3
= newTemp(Ity_I64
);
23462 IRTemp z2
= newTemp(Ity_I64
);
23463 IRTemp z1
= newTemp(Ity_I64
);
23464 IRTemp z0
= newTemp(Ity_I64
);
23466 IRTemp a15
, a14
, a13
, a12
, a11
, a10
, a9
, a8
;
23467 IRTemp a7
, a6
, a5
, a4
, a3
, a2
, a1
, a0
;
23468 IRTemp b3
, b2
, b1
, b0
;
23470 aEvn
= aOdd
= IRTemp_INVALID
;
23471 a15
= a14
= a13
= a12
= a11
= a10
= a9
= a8
= IRTemp_INVALID
;
23472 a7
= a6
= a5
= a4
= a3
= a2
= a1
= a0
= IRTemp_INVALID
;
23473 b3
= b2
= b1
= b0
= IRTemp_INVALID
;
23475 assign( vA
, getVReg( vA_addr
) );
23476 assign( vB
, getVReg( vB_addr
) );
23479 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
23485 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
23486 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23487 /* unsigned_ov(x+y) = (y >u not(x)) */
23488 putVReg( vD_addr
, binop( Iop_ShrN32x4
,
23489 binop( Iop_CmpGT32Ux4
, mkexpr( vB
),
23490 unop( Iop_NotV128
, mkexpr( vA
) ) ),
23494 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
23495 DIP("vaddubm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23496 putVReg( vD_addr
, binop(Iop_Add8x16
, mkexpr(vA
), mkexpr(vB
)) );
23499 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
23500 DIP("vadduhm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23501 putVReg( vD_addr
, binop(Iop_Add16x8
, mkexpr(vA
), mkexpr(vB
)) );
23504 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
23505 DIP("vadduwm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23506 putVReg( vD_addr
, binop(Iop_Add32x4
, mkexpr(vA
), mkexpr(vB
)) );
23509 case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
23510 DIP("vaddudm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23511 putVReg( vD_addr
, binop(Iop_Add64x2
, mkexpr(vA
), mkexpr(vB
)) );
23514 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
23515 DIP("vaddubs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23516 putVReg( vD_addr
, binop(Iop_QAdd8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
23517 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
23520 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
23521 DIP("vadduhs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23522 putVReg( vD_addr
, binop(Iop_QAdd16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
23523 // TODO: set VSCR[SAT]
23526 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
23527 DIP("vadduws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23528 putVReg( vD_addr
, binop(Iop_QAdd32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
23529 // TODO: set VSCR[SAT]
23532 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
23533 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23534 putVReg( vD_addr
, binop(Iop_QAdd8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
23535 // TODO: set VSCR[SAT]
23538 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
23539 DIP("vaddshs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23540 putVReg( vD_addr
, binop(Iop_QAdd16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
23541 // TODO: set VSCR[SAT]
23544 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
23545 DIP("vaddsws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23546 putVReg( vD_addr
, binop(Iop_QAdd32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
23547 // TODO: set VSCR[SAT]
23552 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
23553 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23554 /* unsigned_ov(x-y) = (y >u x) */
23555 putVReg( vD_addr
, binop(Iop_ShrN32x4
,
23557 binop(Iop_CmpGT32Ux4
, mkexpr(vB
),
23562 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
23563 DIP("vsububm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23564 putVReg( vD_addr
, binop(Iop_Sub8x16
, mkexpr(vA
), mkexpr(vB
)) );
23567 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
23568 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23569 putVReg( vD_addr
, binop(Iop_Sub16x8
, mkexpr(vA
), mkexpr(vB
)) );
23572 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
23573 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23574 putVReg( vD_addr
, binop(Iop_Sub32x4
, mkexpr(vA
), mkexpr(vB
)) );
23577 case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
23578 DIP("vsubudm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23579 putVReg( vD_addr
, binop(Iop_Sub64x2
, mkexpr(vA
), mkexpr(vB
)) );
23582 case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
23583 DIP("vsububs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23584 putVReg( vD_addr
, binop(Iop_QSub8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
23585 // TODO: set VSCR[SAT]
23588 case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
23589 DIP("vsubuhs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23590 putVReg( vD_addr
, binop(Iop_QSub16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
23591 // TODO: set VSCR[SAT]
23594 case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
23595 DIP("vsubuws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23596 putVReg( vD_addr
, binop(Iop_QSub32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
23597 // TODO: set VSCR[SAT]
23600 case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
23601 DIP("vsubsbs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23602 putVReg( vD_addr
, binop(Iop_QSub8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
23603 // TODO: set VSCR[SAT]
23606 case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
23607 DIP("vsubshs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23608 putVReg( vD_addr
, binop(Iop_QSub16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
23609 // TODO: set VSCR[SAT]
23612 case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
23613 DIP("vsubsws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23614 putVReg( vD_addr
, binop(Iop_QSub32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
23615 // TODO: set VSCR[SAT]
23620 case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
23621 DIP("vmaxub v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23622 putVReg( vD_addr
, binop(Iop_Max8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
23625 case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
23626 DIP("vmaxuh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23627 putVReg( vD_addr
, binop(Iop_Max16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
23630 case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
23631 DIP("vmaxuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23632 putVReg( vD_addr
, binop(Iop_Max32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
23635 case 0x0C2: // vmaxud (Maximum Unsigned Double word)
23636 DIP("vmaxud v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23637 putVReg( vD_addr
, binop(Iop_Max64Ux2
, mkexpr(vA
), mkexpr(vB
)) );
23640 case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
23641 DIP("vmaxsb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23642 putVReg( vD_addr
, binop(Iop_Max8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
23645 case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
23646 DIP("vmaxsh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23647 putVReg( vD_addr
, binop(Iop_Max16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
23650 case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
23651 DIP("vmaxsw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23652 putVReg( vD_addr
, binop(Iop_Max32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
23655 case 0x1C2: // vmaxsd (Maximum Signed Double word)
23656 DIP("vmaxsd v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23657 putVReg( vD_addr
, binop(Iop_Max64Sx2
, mkexpr(vA
), mkexpr(vB
)) );
23661 case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
23662 DIP("vminub v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23663 putVReg( vD_addr
, binop(Iop_Min8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
23666 case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
23667 DIP("vminuh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23668 putVReg( vD_addr
, binop(Iop_Min16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
23671 case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
23672 DIP("vminuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23673 putVReg( vD_addr
, binop(Iop_Min32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
23676 case 0x2C2: // vminud (Minimum Unsigned Double Word)
23677 DIP("vminud v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23678 putVReg( vD_addr
, binop(Iop_Min64Ux2
, mkexpr(vA
), mkexpr(vB
)) );
23681 case 0x302: // vminsb (Minimum Signed Byte, AV p188)
23682 DIP("vminsb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23683 putVReg( vD_addr
, binop(Iop_Min8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
23686 case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
23687 DIP("vminsh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23688 putVReg( vD_addr
, binop(Iop_Min16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
23691 case 0x382: // vminsw (Minimum Signed Word, AV p190)
23692 DIP("vminsw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23693 putVReg( vD_addr
, binop(Iop_Min32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
23696 case 0x3C2: // vminsd (Minimum Signed Double Word)
23697 DIP("vminsd v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23698 putVReg( vD_addr
, binop(Iop_Min64Sx2
, mkexpr(vA
), mkexpr(vB
)) );
23703 case 0x402: // vavgub (Average Unsigned Byte, AV p152)
23704 DIP("vavgub v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23705 putVReg( vD_addr
, binop(Iop_Avg8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
23708 case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
23709 DIP("vavguh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23710 putVReg( vD_addr
, binop(Iop_Avg16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
23713 case 0x482: // vavguw (Average Unsigned Word, AV p154)
23714 DIP("vavguw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23715 putVReg( vD_addr
, binop(Iop_Avg32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
23718 case 0x502: // vavgsb (Average Signed Byte, AV p149)
23719 DIP("vavgsb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23720 putVReg( vD_addr
, binop(Iop_Avg8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
23723 case 0x542: // vavgsh (Average Signed Half Word, AV p150)
23724 DIP("vavgsh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23725 putVReg( vD_addr
, binop(Iop_Avg16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
23728 case 0x582: // vavgsw (Average Signed Word, AV p151)
23729 DIP("vavgsw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23730 putVReg( vD_addr
, binop(Iop_Avg32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
23735 case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
23736 DIP("vmuloub v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23738 binop(Iop_MullEven8Ux16
, mkexpr(vA
), mkexpr(vB
)));
23741 case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
23742 DIP("vmulouh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23744 binop(Iop_MullEven16Ux8
, mkexpr(vA
), mkexpr(vB
)));
23747 case 0x088: // vmulouw (Multiply Odd Unsigned Word)
23748 DIP("vmulouw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23749 putVReg( vD_addr
, binop( Iop_MullEven32Ux4
, mkexpr(vA
), mkexpr(vB
) ) );
23752 case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
23753 DIP("vmuluwm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23754 putVReg( vD_addr
, binop( Iop_Mul32x4
, mkexpr(vA
), mkexpr(vB
) ) );
23757 case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
23758 DIP("vmulosb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23760 binop(Iop_MullEven8Sx16
, mkexpr(vA
), mkexpr(vB
)));
23763 case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
23764 DIP("vmulosh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23766 binop(Iop_MullEven16Sx8
, mkexpr(vA
), mkexpr(vB
)));
23769 case 0x188: // vmulosw (Multiply Odd Signed Word)
23770 DIP("vmulosw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23771 putVReg( vD_addr
, binop( Iop_MullEven32Sx4
, mkexpr(vA
), mkexpr(vB
) ) );
23774 case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
23775 DIP("vmuleub v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23776 putVReg( vD_addr
, MK_Iop_MullOdd8Ux16( mkexpr(vA
), mkexpr(vB
) ));
23779 case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
23780 DIP("vmuleuh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23781 putVReg( vD_addr
, MK_Iop_MullOdd16Ux8( mkexpr(vA
), mkexpr(vB
) ));
23784 case 0x288: // vmuleuw (Multiply Even Unsigned Word)
23785 DIP("vmuleuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23786 putVReg( vD_addr
, MK_Iop_MullOdd32Ux4( mkexpr(vA
), mkexpr(vB
) ) );
23789 case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
23790 DIP("vmulesb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23791 putVReg( vD_addr
, MK_Iop_MullOdd8Sx16( mkexpr(vA
), mkexpr(vB
) ));
23794 case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
23795 DIP("vmulesh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23796 putVReg( vD_addr
, MK_Iop_MullOdd16Sx8( mkexpr(vA
), mkexpr(vB
) ));
23799 case 0x388: // vmulesw (Multiply Even Signed Word)
23800 DIP("vmulesw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23801 putVReg( vD_addr
, MK_Iop_MullOdd32Sx4( mkexpr(vA
), mkexpr(vB
) ) );
23804 /* Sum Across Partial */
23805 case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
23806 IRTemp aEE
, aEO
, aOE
, aOO
;
23807 aEE
= aEO
= aOE
= aOO
= IRTemp_INVALID
;
23808 DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23810 /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
23811 expand8Ux16( mkexpr(vA
), &aEvn
, &aOdd
); // (15,13...),(14,12...)
23812 expand16Ux8( mkexpr(aEvn
), &aEE
, &aEO
); // (15,11...),(13, 9...)
23813 expand16Ux8( mkexpr(aOdd
), &aOE
, &aOO
); // (14,10...),(12, 8...)
23815 /* break V128 to 4xI32's, zero-extending to I64's */
23816 breakV128to4x64U( mkexpr(aEE
), &a15
, &a11
, &a7
, &a3
);
23817 breakV128to4x64U( mkexpr(aOE
), &a14
, &a10
, &a6
, &a2
);
23818 breakV128to4x64U( mkexpr(aEO
), &a13
, &a9
, &a5
, &a1
);
23819 breakV128to4x64U( mkexpr(aOO
), &a12
, &a8
, &a4
, &a0
);
23820 breakV128to4x64U( mkexpr(vB
), &b3
, &b2
, &b1
, &b0
);
23823 assign( z3
, binop(Iop_Add64
, mkexpr(b3
),
23825 binop(Iop_Add64
, mkexpr(a15
), mkexpr(a14
)),
23826 binop(Iop_Add64
, mkexpr(a13
), mkexpr(a12
)))) );
23827 assign( z2
, binop(Iop_Add64
, mkexpr(b2
),
23829 binop(Iop_Add64
, mkexpr(a11
), mkexpr(a10
)),
23830 binop(Iop_Add64
, mkexpr(a9
), mkexpr(a8
)))) );
23831 assign( z1
, binop(Iop_Add64
, mkexpr(b1
),
23833 binop(Iop_Add64
, mkexpr(a7
), mkexpr(a6
)),
23834 binop(Iop_Add64
, mkexpr(a5
), mkexpr(a4
)))) );
23835 assign( z0
, binop(Iop_Add64
, mkexpr(b0
),
23837 binop(Iop_Add64
, mkexpr(a3
), mkexpr(a2
)),
23838 binop(Iop_Add64
, mkexpr(a1
), mkexpr(a0
)))) );
23840 /* saturate-narrow to 32bit, and combine to V128 */
23841 putVReg( vD_addr
, mkV128from4x64U( mkexpr(z3
), mkexpr(z2
),
23842 mkexpr(z1
), mkexpr(z0
)) );
23845 case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
23846 IRTemp aEE
, aEO
, aOE
, aOO
;
23847 aEE
= aEO
= aOE
= aOO
= IRTemp_INVALID
;
23848 DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23850 /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
23851 expand8Sx16( mkexpr(vA
), &aEvn
, &aOdd
); // (15,13...),(14,12...)
23852 expand16Sx8( mkexpr(aEvn
), &aEE
, &aEO
); // (15,11...),(13, 9...)
23853 expand16Sx8( mkexpr(aOdd
), &aOE
, &aOO
); // (14,10...),(12, 8...)
23855 /* break V128 to 4xI32's, sign-extending to I64's */
23856 breakV128to4x64S( mkexpr(aEE
), &a15
, &a11
, &a7
, &a3
);
23857 breakV128to4x64S( mkexpr(aOE
), &a14
, &a10
, &a6
, &a2
);
23858 breakV128to4x64S( mkexpr(aEO
), &a13
, &a9
, &a5
, &a1
);
23859 breakV128to4x64S( mkexpr(aOO
), &a12
, &a8
, &a4
, &a0
);
23860 breakV128to4x64S( mkexpr(vB
), &b3
, &b2
, &b1
, &b0
);
23863 assign( z3
, binop(Iop_Add64
, mkexpr(b3
),
23865 binop(Iop_Add64
, mkexpr(a15
), mkexpr(a14
)),
23866 binop(Iop_Add64
, mkexpr(a13
), mkexpr(a12
)))) );
23867 assign( z2
, binop(Iop_Add64
, mkexpr(b2
),
23869 binop(Iop_Add64
, mkexpr(a11
), mkexpr(a10
)),
23870 binop(Iop_Add64
, mkexpr(a9
), mkexpr(a8
)))) );
23871 assign( z1
, binop(Iop_Add64
, mkexpr(b1
),
23873 binop(Iop_Add64
, mkexpr(a7
), mkexpr(a6
)),
23874 binop(Iop_Add64
, mkexpr(a5
), mkexpr(a4
)))) );
23875 assign( z0
, binop(Iop_Add64
, mkexpr(b0
),
23877 binop(Iop_Add64
, mkexpr(a3
), mkexpr(a2
)),
23878 binop(Iop_Add64
, mkexpr(a1
), mkexpr(a0
)))) );
23880 /* saturate-narrow to 32bit, and combine to V128 */
23881 putVReg( vD_addr
, mkV128from4x64S( mkexpr(z3
), mkexpr(z2
),
23882 mkexpr(z1
), mkexpr(z0
)) );
23885 case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
23886 DIP("vsum4shs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23888 /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
23889 expand16Sx8( mkexpr(vA
), &aEvn
, &aOdd
); // (7,5...),(6,4...)
23891 /* break V128 to 4xI32's, sign-extending to I64's */
23892 breakV128to4x64S( mkexpr(aEvn
), &a7
, &a5
, &a3
, &a1
);
23893 breakV128to4x64S( mkexpr(aOdd
), &a6
, &a4
, &a2
, &a0
);
23894 breakV128to4x64S( mkexpr(vB
), &b3
, &b2
, &b1
, &b0
);
23897 assign( z3
, binop(Iop_Add64
, mkexpr(b3
),
23898 binop(Iop_Add64
, mkexpr(a7
), mkexpr(a6
))));
23899 assign( z2
, binop(Iop_Add64
, mkexpr(b2
),
23900 binop(Iop_Add64
, mkexpr(a5
), mkexpr(a4
))));
23901 assign( z1
, binop(Iop_Add64
, mkexpr(b1
),
23902 binop(Iop_Add64
, mkexpr(a3
), mkexpr(a2
))));
23903 assign( z0
, binop(Iop_Add64
, mkexpr(b0
),
23904 binop(Iop_Add64
, mkexpr(a1
), mkexpr(a0
))));
23906 /* saturate-narrow to 32bit, and combine to V128 */
23907 putVReg( vD_addr
, mkV128from4x64S( mkexpr(z3
), mkexpr(z2
),
23908 mkexpr(z1
), mkexpr(z0
)) );
23911 case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
23912 DIP("vsum2sws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23914 /* break V128 to 4xI32's, sign-extending to I64's */
23915 breakV128to4x64S( mkexpr(vA
), &a3
, &a2
, &a1
, &a0
);
23916 breakV128to4x64S( mkexpr(vB
), &b3
, &b2
, &b1
, &b0
);
23919 assign( z2
, binop(Iop_Add64
, mkexpr(b2
),
23920 binop(Iop_Add64
, mkexpr(a3
), mkexpr(a2
))) );
23921 assign( z0
, binop(Iop_Add64
, mkexpr(b0
),
23922 binop(Iop_Add64
, mkexpr(a1
), mkexpr(a0
))) );
23924 /* saturate-narrow to 32bit, and combine to V128 */
23925 putVReg( vD_addr
, mkV128from4x64S( mkU64(0), mkexpr(z2
),
23926 mkU64(0), mkexpr(z0
)) );
23929 case 0x788: { // vsumsws (Sum SW Saturate, AV p271)
23930 DIP("vsumsws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23932 /* break V128 to 4xI32's, sign-extending to I64's */
23933 breakV128to4x64S( mkexpr(vA
), &a3
, &a2
, &a1
, &a0
);
23934 breakV128to4x64S( mkexpr(vB
), &b3
, &b2
, &b1
, &b0
);
23937 assign( z0
, binop(Iop_Add64
, mkexpr(b0
),
23939 binop(Iop_Add64
, mkexpr(a3
), mkexpr(a2
)),
23940 binop(Iop_Add64
, mkexpr(a1
), mkexpr(a0
)))) );
23942 /* saturate-narrow to 32bit, and combine to V128 */
23943 putVReg( vD_addr
, mkV128from4x64S( mkU64(0), mkU64(0),
23944 mkU64(0), mkexpr(z0
)) );
23948 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2
);
23955 AltiVec Logic Instructions
23957 static Bool
dis_av_logic ( UInt theInstr
)
23960 UChar opc1
= ifieldOPC(theInstr
);
23961 UChar vD_addr
= ifieldRegDS(theInstr
);
23962 UChar vA_addr
= ifieldRegA(theInstr
);
23963 UChar vB_addr
= ifieldRegB(theInstr
);
23964 UInt opc2
= IFIELD( theInstr
, 0, 11 );
23966 IRTemp vA
= newTemp(Ity_V128
);
23967 IRTemp vB
= newTemp(Ity_V128
);
23968 assign( vA
, getVReg(vA_addr
));
23969 assign( vB
, getVReg(vB_addr
));
23972 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
23977 case 0x404: // vand (And, AV p147)
23978 DIP("vand v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23979 putVReg( vD_addr
, binop(Iop_AndV128
, mkexpr(vA
), mkexpr(vB
)) );
23982 case 0x444: // vandc (And, AV p148)
23983 DIP("vandc v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23984 putVReg( vD_addr
, binop(Iop_AndV128
, mkexpr(vA
),
23985 unop(Iop_NotV128
, mkexpr(vB
))) );
23988 case 0x484: // vor (Or, AV p217)
23989 DIP("vor v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23990 putVReg( vD_addr
, binop(Iop_OrV128
, mkexpr(vA
), mkexpr(vB
)) );
23993 case 0x4C4: // vxor (Xor, AV p282)
23994 DIP("vxor v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
23995 putVReg( vD_addr
, binop(Iop_XorV128
, mkexpr(vA
), mkexpr(vB
)) );
23998 case 0x504: // vnor (Nor, AV p216)
23999 DIP("vnor v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24001 unop(Iop_NotV128
, binop(Iop_OrV128
, mkexpr(vA
), mkexpr(vB
))) );
24004 case 0x544: // vorc (vA Or'd with complement of vb)
24005 DIP("vorc v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24006 putVReg( vD_addr
, binop( Iop_OrV128
,
24008 unop( Iop_NotV128
, mkexpr( vB
) ) ) );
24011 case 0x584: // vnand (Nand)
24012 DIP("vnand v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24013 putVReg( vD_addr
, unop( Iop_NotV128
,
24014 binop(Iop_AndV128
, mkexpr( vA
),
24015 mkexpr( vB
) ) ) );
24018 case 0x684: // veqv (complemented XOr)
24019 DIP("veqv v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24020 putVReg( vD_addr
, unop( Iop_NotV128
,
24021 binop( Iop_XorV128
, mkexpr( vA
),
24022 mkexpr( vB
) ) ) );
24026 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2
);
24033 AltiVec Compare Instructions
24035 static Bool
dis_av_cmp ( UInt theInstr
)
24038 UChar opc1
= ifieldOPC(theInstr
);
24039 UChar vD_addr
= ifieldRegDS(theInstr
);
24040 UChar vA_addr
= ifieldRegA(theInstr
);
24041 UChar vB_addr
= ifieldRegB(theInstr
);
24042 UChar flag_rC
= ifieldBIT10(theInstr
);
24043 UInt opc2
= IFIELD( theInstr
, 0, 10 );
24045 IRTemp vA
= newTemp(Ity_V128
);
24046 IRTemp vB
= newTemp(Ity_V128
);
24047 IRTemp vD
= newTemp(Ity_V128
);
24048 assign( vA
, getVReg(vA_addr
));
24049 assign( vB
, getVReg(vB_addr
));
24052 vex_printf("dis_av_cmp(ppc)(instr)\n");
24057 case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
24058 DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24059 vD_addr
, vA_addr
, vB_addr
);
24060 assign( vD
, binop(Iop_CmpEQ8x16
, mkexpr(vA
), mkexpr(vB
)) );
24063 case 0x007: // vcmpneb (Compare Not Equal byte)
24064 DIP("vcmpneb%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24065 vD_addr
, vA_addr
, vB_addr
);
24066 assign( vD
, unop( Iop_NotV128
,
24067 binop( Iop_CmpEQ8x16
, mkexpr( vA
), mkexpr( vB
) ) ) );
24070 case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
24071 DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24072 vD_addr
, vA_addr
, vB_addr
);
24073 assign( vD
, binop(Iop_CmpEQ16x8
, mkexpr(vA
), mkexpr(vB
)) );
24076 case 0x047: // vcmpneh (Compare Not Equal-to Halfword)
24077 DIP("vcmpneh%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24078 vD_addr
, vA_addr
, vB_addr
);
24079 assign( vD
, unop( Iop_NotV128
,
24080 binop( Iop_CmpEQ16x8
, mkexpr( vA
), mkexpr( vB
) ) ) );
24083 case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
24084 DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24085 vD_addr
, vA_addr
, vB_addr
);
24086 assign( vD
, binop(Iop_CmpEQ32x4
, mkexpr(vA
), mkexpr(vB
)) );
24089 case 0x087: // vcmpnew (Compare Not Equal-to Word)
24090 DIP("vcmpnew%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24091 vD_addr
, vA_addr
, vB_addr
);
24092 assign( vD
, unop( Iop_NotV128
,
24093 binop( Iop_CmpEQ32x4
, mkexpr( vA
), mkexpr( vB
) ) ) );
24096 case 0x107: // vcmpnezb (Compare Not Equal or Zero byte)
24098 IRTemp vAeqvB
= newTemp( Ity_V128
);
24099 IRTemp vAeq0
= newTemp( Ity_V128
);
24100 IRTemp vBeq0
= newTemp( Ity_V128
);
24101 IRTemp zero
= newTemp( Ity_V128
);
24103 DIP("vcmpnezb%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24104 vD_addr
, vA_addr
, vB_addr
);
24106 assign( zero
, binop( Iop_64HLtoV128
, mkU64( 0 ), mkU64( 0 ) ) );
24107 assign( vAeq0
, binop( Iop_CmpEQ8x16
, mkexpr( vA
), mkexpr( zero
) ) );
24108 assign( vBeq0
, binop( Iop_CmpEQ8x16
, mkexpr( vB
), mkexpr( zero
) ) );
24109 assign( vAeqvB
, unop( Iop_NotV128
,
24110 binop( Iop_CmpEQ8x16
, mkexpr( vA
),
24111 mkexpr( vB
) ) ) );
24113 assign( vD
, mkOr3_V128( vAeqvB
, vAeq0
, vBeq0
) );
24117 case 0x147: // vcmpnezh (Compare Not Equal or Zero Halfword)
24119 IRTemp vAeqvB
= newTemp( Ity_V128
);
24120 IRTemp vAeq0
= newTemp( Ity_V128
);
24121 IRTemp vBeq0
= newTemp( Ity_V128
);
24122 IRTemp zero
= newTemp( Ity_V128
);
24124 DIP("vcmpnezh%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24125 vD_addr
, vA_addr
, vB_addr
);
24127 assign( zero
, binop( Iop_64HLtoV128
, mkU64( 0 ), mkU64( 0 ) ) );
24128 assign( vAeq0
, binop( Iop_CmpEQ16x8
, mkexpr( vA
), mkexpr( zero
) ) );
24129 assign( vBeq0
, binop( Iop_CmpEQ16x8
, mkexpr( vB
), mkexpr( zero
) ) );
24130 assign( vAeqvB
, unop( Iop_NotV128
,
24131 binop(Iop_CmpEQ16x8
, mkexpr( vA
),
24132 mkexpr( vB
) ) ) );
24134 assign( vD
, binop( Iop_OrV128
,
24138 mkexpr( vAeqvB
) ) );
24142 case 0x187: // vcmpnezw (Compare Not Equal or Zero Word)
24144 IRTemp vAeqvB
= newTemp( Ity_V128
);
24145 IRTemp vAeq0
= newTemp( Ity_V128
);
24146 IRTemp vBeq0
= newTemp( Ity_V128
);
24147 IRTemp zero
= newTemp( Ity_V128
);
24149 DIP("vcmpnezw%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24150 vD_addr
, vA_addr
, vB_addr
);
24152 assign( zero
, binop( Iop_64HLtoV128
, mkU64( 0 ), mkU64( 0 ) ) );
24153 assign( vAeq0
, binop( Iop_CmpEQ32x4
, mkexpr( vA
), mkexpr( zero
) ) );
24154 assign( vBeq0
, binop( Iop_CmpEQ32x4
, mkexpr( vB
), mkexpr( zero
) ) );
24155 assign( vAeqvB
, unop( Iop_NotV128
,
24156 binop(Iop_CmpEQ32x4
, mkexpr( vA
),
24157 mkexpr( vB
) ) ) );
24159 assign( vD
, binop( Iop_OrV128
,
24163 mkexpr( vAeqvB
) ) );
24167 case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
24168 DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24169 vD_addr
, vA_addr
, vB_addr
);
24170 assign( vD
, binop(Iop_CmpEQ64x2
, mkexpr(vA
), mkexpr(vB
)) );
24173 case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
24174 DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24175 vD_addr
, vA_addr
, vB_addr
);
24176 assign( vD
, binop(Iop_CmpGT8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
24179 case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
24180 DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24181 vD_addr
, vA_addr
, vB_addr
);
24182 assign( vD
, binop(Iop_CmpGT16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
24185 case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
24186 DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24187 vD_addr
, vA_addr
, vB_addr
);
24188 assign( vD
, binop(Iop_CmpGT32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
24191 case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
24192 DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24193 vD_addr
, vA_addr
, vB_addr
);
24194 assign( vD
, binop(Iop_CmpGT64Ux2
, mkexpr(vA
), mkexpr(vB
)) );
24197 case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
24198 DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24199 vD_addr
, vA_addr
, vB_addr
);
24200 assign( vD
, binop(Iop_CmpGT8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
24203 case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
24204 DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24205 vD_addr
, vA_addr
, vB_addr
);
24206 assign( vD
, binop(Iop_CmpGT16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
24209 case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
24210 DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24211 vD_addr
, vA_addr
, vB_addr
);
24212 assign( vD
, binop(Iop_CmpGT32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
24215 case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
24216 DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
24217 vD_addr
, vA_addr
, vB_addr
);
24218 assign( vD
, binop(Iop_CmpGT64Sx2
, mkexpr(vA
), mkexpr(vB
)) );
24222 vex_printf("dis_av_cmp(ppc)(opc2)\n");
24226 putVReg( vD_addr
, mkexpr(vD
) );
24229 set_AV_CR6( mkexpr(vD
), True
);
24235 AltiVec Multiply-Sum Instructions
24237 static Bool
dis_av_multarith ( UInt theInstr
)
24240 UChar opc1
= ifieldOPC(theInstr
);
24241 UChar vD_addr
= ifieldRegDS(theInstr
);
24242 UChar vA_addr
= ifieldRegA(theInstr
);
24243 UChar vB_addr
= ifieldRegB(theInstr
);
24244 UChar vC_addr
= ifieldRegC(theInstr
);
24245 UChar opc2
= toUChar( IFIELD( theInstr
, 0, 6 ) );
24247 IRTemp vA
= newTemp(Ity_V128
);
24248 IRTemp vB
= newTemp(Ity_V128
);
24249 IRTemp vC
= newTemp(Ity_V128
);
24250 IRTemp zeros
= newTemp(Ity_V128
);
24251 IRTemp aLo
= newTemp(Ity_V128
);
24252 IRTemp bLo
= newTemp(Ity_V128
);
24253 IRTemp cLo
= newTemp(Ity_V128
);
24254 IRTemp zLo
= newTemp(Ity_V128
);
24255 IRTemp aHi
= newTemp(Ity_V128
);
24256 IRTemp bHi
= newTemp(Ity_V128
);
24257 IRTemp cHi
= newTemp(Ity_V128
);
24258 IRTemp zHi
= newTemp(Ity_V128
);
24259 IRTemp abEvn
= newTemp(Ity_V128
);
24260 IRTemp abOdd
= newTemp(Ity_V128
);
24261 IRTemp z3
= newTemp(Ity_I64
);
24262 IRTemp z2
= newTemp(Ity_I64
);
24263 IRTemp z1
= newTemp(Ity_I64
);
24264 IRTemp z0
= newTemp(Ity_I64
);
24265 IRTemp ab7
, ab6
, ab5
, ab4
, ab3
, ab2
, ab1
, ab0
;
24266 IRTemp c3
, c2
, c1
, c0
;
24268 ab7
= ab6
= ab5
= ab4
= ab3
= ab2
= ab1
= ab0
= IRTemp_INVALID
;
24269 c3
= c2
= c1
= c0
= IRTemp_INVALID
;
24271 assign( vA
, getVReg(vA_addr
));
24272 assign( vB
, getVReg(vB_addr
));
24273 assign( vC
, getVReg(vC_addr
));
24274 assign( zeros
, unop(Iop_Dup32x4
, mkU32(0)) );
24277 vex_printf("dis_av_multarith(ppc)(instr)\n");
24283 case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
24284 IRTemp cSigns
= newTemp(Ity_V128
);
24285 DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
24286 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24287 assign(cSigns
, binop(Iop_CmpGT16Sx8
, mkexpr(zeros
), mkexpr(vC
)));
24288 assign(aLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vA
)));
24289 assign(bLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vB
)));
24290 assign(cLo
, binop(Iop_InterleaveLO16x8
, mkexpr(cSigns
),mkexpr(vC
)));
24291 assign(aHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vA
)));
24292 assign(bHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vB
)));
24293 assign(cHi
, binop(Iop_InterleaveHI16x8
, mkexpr(cSigns
),mkexpr(vC
)));
24295 assign( zLo
, binop(Iop_Add32x4
, mkexpr(cLo
),
24296 binop(Iop_SarN32x4
,
24297 binop(Iop_MullEven16Sx8
,
24298 mkexpr(aLo
), mkexpr(bLo
)),
24301 assign( zHi
, binop(Iop_Add32x4
, mkexpr(cHi
),
24302 binop(Iop_SarN32x4
,
24303 binop(Iop_MullEven16Sx8
,
24304 mkexpr(aHi
), mkexpr(bHi
)),
24308 binop(Iop_QNarrowBin32Sto16Sx8
, mkexpr(zHi
), mkexpr(zLo
)) );
24311 case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
24312 IRTemp zKonst
= newTemp(Ity_V128
);
24313 IRTemp cSigns
= newTemp(Ity_V128
);
24314 DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
24315 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24316 assign(cSigns
, binop(Iop_CmpGT16Sx8
, mkexpr(zeros
), mkexpr(vC
)) );
24317 assign(aLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vA
)));
24318 assign(bLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vB
)));
24319 assign(cLo
, binop(Iop_InterleaveLO16x8
, mkexpr(cSigns
),mkexpr(vC
)));
24320 assign(aHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vA
)));
24321 assign(bHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vB
)));
24322 assign(cHi
, binop(Iop_InterleaveHI16x8
, mkexpr(cSigns
),mkexpr(vC
)));
24324 /* shifting our const avoids store/load version of Dup */
24325 assign( zKonst
, binop(Iop_ShlN32x4
, unop(Iop_Dup32x4
, mkU32(0x1)),
24328 assign( zLo
, binop(Iop_Add32x4
, mkexpr(cLo
),
24329 binop(Iop_SarN32x4
,
24330 binop(Iop_Add32x4
, mkexpr(zKonst
),
24331 binop(Iop_MullEven16Sx8
,
24332 mkexpr(aLo
), mkexpr(bLo
))),
24335 assign( zHi
, binop(Iop_Add32x4
, mkexpr(cHi
),
24336 binop(Iop_SarN32x4
,
24337 binop(Iop_Add32x4
, mkexpr(zKonst
),
24338 binop(Iop_MullEven16Sx8
,
24339 mkexpr(aHi
), mkexpr(bHi
))),
24343 binop(Iop_QNarrowBin32Sto16Sx8
, mkexpr(zHi
), mkexpr(zLo
)) );
24346 case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
24347 DIP("vmladduhm v%d,v%d,v%d,v%d\n",
24348 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24349 assign(aLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vA
)));
24350 assign(bLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vB
)));
24351 assign(cLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vC
)));
24352 assign(aHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vA
)));
24353 assign(bHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vB
)));
24354 assign(cHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vC
)));
24355 assign(zLo
, binop(Iop_Add32x4
,
24356 binop(Iop_MullEven16Ux8
, mkexpr(aLo
), mkexpr(bLo
)),
24358 assign(zHi
, binop(Iop_Add32x4
,
24359 binop(Iop_MullEven16Ux8
, mkexpr(aHi
), mkexpr(bHi
)),
24362 binop(Iop_NarrowBin32to16x8
, mkexpr(zHi
), mkexpr(zLo
)) );
24366 case 0x23: { // vmsumudm
24367 DIP("vmsumudm v%d,v%d,v%d,v%d\n",
24368 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24369 /* This instruction takes input vectors VA, VB consisting of 2 usigned
24370 64-bit integer elements and a 128 bit unsigned input U128_C. The
24371 instruction performs the following operation:
24373 VA[0] * VB[0] -> U128_mul_result0;
24374 VA[1] * VB[1] -> U128_mul_result1;
24375 U128_C + U128_mul_result0 + U128_mul_result1 -> U128_partial_sum;
24376 carry out and overflow is discarded.
24379 /* The Iop_MulI128low assumes the upper 64-bits in the two input operands
24381 IRTemp mul_result0
= newTemp( Ity_I128
);
24382 IRTemp mul_result1
= newTemp( Ity_I128
);
24383 IRTemp partial_sum_hi
= newTemp( Ity_I64
);
24384 IRTemp partial_sum_low
= newTemp( Ity_I64
);
24385 IRTemp result_hi
= newTemp( Ity_I64
);
24386 IRTemp result_low
= newTemp( Ity_I64
);
24387 IRExpr
*ca_sum
, *ca_result
;
24390 /* Do multiplications */
24391 assign ( mul_result0
, binop( Iop_MullU64
,
24392 unop( Iop_V128to64
, mkexpr( vA
) ),
24393 unop( Iop_V128to64
, mkexpr( vB
) ) ) );
24395 assign ( mul_result1
, binop( Iop_MullU64
,
24396 unop( Iop_V128HIto64
, mkexpr( vA
) ),
24397 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
24399 /* Add the two 128-bit results using 64-bit unsigned adds, calculate carry
24400 from low 64-bits add into sum of upper 64-bits. Throw away carry out
24401 of the upper 64-bit sum. */
24402 assign ( partial_sum_low
, binop( Iop_Add64
,
24403 unop( Iop_128to64
, mkexpr( mul_result0
) ),
24404 unop( Iop_128to64
, mkexpr( mul_result1
) )
24407 /* ca_sum is type U32 */
24408 ca_sum
= calculate_XER_CA_64 ( PPCG_FLAG_OP_ADD
,
24409 mkexpr(partial_sum_low
),
24410 unop( Iop_128to64
, mkexpr( mul_result0
) ),
24411 unop( Iop_128to64
, mkexpr( mul_result1
) ),
24414 assign ( partial_sum_hi
,
24417 unop( Iop_128HIto64
, mkexpr( mul_result0
) ),
24418 unop( Iop_128HIto64
, mkexpr( mul_result1
) ) ),
24419 binop( Iop_32HLto64
, mkU32( 0 ), ca_sum
) ) );
24421 /* Now add in the value of C */
24422 assign ( result_low
, binop( Iop_Add64
,
24423 mkexpr( partial_sum_low
),
24424 unop( Iop_V128to64
, mkexpr( vC
) ) ) );
24426 /* ca_result is type U32 */
24427 ca_result
= calculate_XER_CA_64( PPCG_FLAG_OP_ADD
,
24428 mkexpr( result_low
),
24429 mkexpr( partial_sum_low
),
24430 unop( Iop_V128to64
,
24434 assign ( result_hi
,
24437 mkexpr( partial_sum_hi
),
24438 unop( Iop_V128HIto64
, mkexpr( vC
) ) ),
24439 binop( Iop_32HLto64
, mkU32( 0 ), ca_result
) ) );
24441 putVReg( vD_addr
, binop( Iop_64HLtoV128
,
24442 mkexpr( result_hi
), mkexpr ( result_low
) ) );
24447 case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
24448 IRTemp abEE
, abEO
, abOE
, abOO
;
24449 abEE
= abEO
= abOE
= abOO
= IRTemp_INVALID
;
24450 DIP("vmsumubm v%d,v%d,v%d,v%d\n",
24451 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24453 /* multiply vA,vB (unsigned, widening) */
24454 assign( abEvn
, MK_Iop_MullOdd8Ux16( mkexpr(vA
), mkexpr(vB
) ));
24455 assign( abOdd
, binop(Iop_MullEven8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
24457 /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
24458 expand16Ux8( mkexpr(abEvn
), &abEE
, &abEO
);
24459 expand16Ux8( mkexpr(abOdd
), &abOE
, &abOO
);
24462 binop(Iop_Add32x4
, mkexpr(vC
),
24464 binop(Iop_Add32x4
, mkexpr(abEE
), mkexpr(abEO
)),
24465 binop(Iop_Add32x4
, mkexpr(abOE
), mkexpr(abOO
)))) );
24468 case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
24469 IRTemp aEvn
, aOdd
, bEvn
, bOdd
;
24470 IRTemp abEE
= newTemp(Ity_V128
);
24471 IRTemp abEO
= newTemp(Ity_V128
);
24472 IRTemp abOE
= newTemp(Ity_V128
);
24473 IRTemp abOO
= newTemp(Ity_V128
);
24474 IRTemp prod
= newTemp(Ity_V128
);
24475 IRTemp sum0
= newTemp(Ity_I32
);
24476 IRTemp sum1
= newTemp(Ity_I32
);
24477 IRTemp sum2
= newTemp(Ity_I32
);
24478 IRTemp sum3
= newTemp(Ity_I32
);
24480 aEvn
= aOdd
= bEvn
= bOdd
= IRTemp_INVALID
;
24481 DIP("vmsummbm v%d,v%d,v%d,v%d\n",
24482 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24484 /* sign-extend vA, zero-extend vB, for mixed-sign multiply
24485 (separating out adjacent lanes to different vectors) */
24486 expand8Sx16( mkexpr(vA
), &aEvn
, &aOdd
);
24487 expand8Ux16( mkexpr(vB
), &bEvn
, &bOdd
);
24489 /* multiply vA, vB, again separating adjacent lanes */
24490 assign( abEE
, MK_Iop_MullOdd16Sx8( mkexpr(aEvn
), mkexpr(bEvn
) ));
24491 assign( abEO
, binop(Iop_MullEven16Sx8
, mkexpr(aEvn
), mkexpr(bEvn
)) );
24492 assign( abOE
, MK_Iop_MullOdd16Sx8( mkexpr(aOdd
), mkexpr(bOdd
) ));
24493 assign( abOO
, binop(Iop_MullEven16Sx8
, mkexpr(aOdd
), mkexpr(bOdd
)) );
24495 /* add results together, + vC */
24496 /* Unfortunately, we need to chop the results of the adds to 32-bits. The
24497 following lane based calculations don't handle the overflow correctly. Need
24498 to explicitly do the adds and 32-bit chops.
24501 binop(Iop_QAdd32Sx4, mkexpr(vC),
24502 binop(Iop_QAdd32Sx4,
24503 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
24504 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
24508 binop(Iop_QAdd32Sx4
,
24509 binop(Iop_QAdd32Sx4
, mkexpr(abEE
), mkexpr(abEO
)),
24510 binop(Iop_QAdd32Sx4
, mkexpr(abOE
), mkexpr(abOO
))));
24515 unop(Iop_64HIto32
, unop(Iop_V128HIto64
, mkexpr(prod
)))),
24517 unop(Iop_64HIto32
, unop(Iop_V128HIto64
, mkexpr(vC
)))))));
24522 unop(Iop_64to32
, unop(Iop_V128HIto64
, mkexpr(prod
)))),
24524 unop(Iop_64to32
, unop(Iop_V128HIto64
, mkexpr(vC
)))))));
24529 unop(Iop_64HIto32
, unop(Iop_V128to64
, mkexpr(prod
)))),
24531 unop(Iop_64HIto32
, unop(Iop_V128to64
, mkexpr(vC
)))))));
24536 unop(Iop_64to32
, unop(Iop_V128to64
, mkexpr(prod
)))),
24538 unop(Iop_64to32
, unop(Iop_V128to64
, mkexpr(vC
)))))));
24539 putVReg( vD_addr
, binop(Iop_64HLtoV128
,
24540 binop(Iop_32HLto64
, mkexpr(sum0
), mkexpr(sum1
)),
24541 binop(Iop_32HLto64
, mkexpr(sum2
), mkexpr(sum3
))));
24545 case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
24546 DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
24547 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24548 assign( abEvn
, MK_Iop_MullOdd16Ux8( mkexpr(vA
), mkexpr(vB
) ));
24549 assign( abOdd
, binop(Iop_MullEven16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
24551 binop(Iop_Add32x4
, mkexpr(vC
),
24552 binop(Iop_Add32x4
, mkexpr(abEvn
), mkexpr(abOdd
))) );
24555 case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
24556 DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
24557 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24558 /* widening multiply, separating lanes */
24559 assign( abEvn
, MK_Iop_MullOdd16Ux8(mkexpr(vA
), mkexpr(vB
) ));
24560 assign( abOdd
, binop(Iop_MullEven16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
24562 /* break V128 to 4xI32's, zero-extending to I64's */
24563 breakV128to4x64U( mkexpr(abEvn
), &ab7
, &ab5
, &ab3
, &ab1
);
24564 breakV128to4x64U( mkexpr(abOdd
), &ab6
, &ab4
, &ab2
, &ab0
);
24565 breakV128to4x64U( mkexpr(vC
), &c3
, &c2
, &c1
, &c0
);
24568 assign( z3
, binop(Iop_Add64
, mkexpr(c3
),
24569 binop(Iop_Add64
, mkexpr(ab7
), mkexpr(ab6
))));
24570 assign( z2
, binop(Iop_Add64
, mkexpr(c2
),
24571 binop(Iop_Add64
, mkexpr(ab5
), mkexpr(ab4
))));
24572 assign( z1
, binop(Iop_Add64
, mkexpr(c1
),
24573 binop(Iop_Add64
, mkexpr(ab3
), mkexpr(ab2
))));
24574 assign( z0
, binop(Iop_Add64
, mkexpr(c0
),
24575 binop(Iop_Add64
, mkexpr(ab1
), mkexpr(ab0
))));
24577 /* saturate-narrow to 32bit, and combine to V128 */
24578 putVReg( vD_addr
, mkV128from4x64U( mkexpr(z3
), mkexpr(z2
),
24579 mkexpr(z1
), mkexpr(z0
)) );
24583 case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
24584 DIP("vmsumshm v%d,v%d,v%d,v%d\n",
24585 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24586 assign( abEvn
, MK_Iop_MullOdd16Sx8( mkexpr(vA
), mkexpr(vB
) ));
24587 assign( abOdd
, binop(Iop_MullEven16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
24589 binop(Iop_Add32x4
, mkexpr(vC
),
24590 binop(Iop_Add32x4
, mkexpr(abOdd
), mkexpr(abEvn
))) );
24593 case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
24594 DIP("vmsumshs v%d,v%d,v%d,v%d\n",
24595 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24596 /* widening multiply, separating lanes */
24597 assign( abEvn
, MK_Iop_MullOdd16Sx8( mkexpr(vA
), mkexpr(vB
) ));
24598 assign( abOdd
, binop(Iop_MullEven16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
24600 /* break V128 to 4xI32's, sign-extending to I64's */
24601 breakV128to4x64S( mkexpr(abEvn
), &ab7
, &ab5
, &ab3
, &ab1
);
24602 breakV128to4x64S( mkexpr(abOdd
), &ab6
, &ab4
, &ab2
, &ab0
);
24603 breakV128to4x64S( mkexpr(vC
), &c3
, &c2
, &c1
, &c0
);
24606 assign( z3
, binop(Iop_Add64
, mkexpr(c3
),
24607 binop(Iop_Add64
, mkexpr(ab7
), mkexpr(ab6
))));
24608 assign( z2
, binop(Iop_Add64
, mkexpr(c2
),
24609 binop(Iop_Add64
, mkexpr(ab5
), mkexpr(ab4
))));
24610 assign( z1
, binop(Iop_Add64
, mkexpr(c1
),
24611 binop(Iop_Add64
, mkexpr(ab3
), mkexpr(ab2
))));
24612 assign( z0
, binop(Iop_Add64
, mkexpr(c0
),
24613 binop(Iop_Add64
, mkexpr(ab1
), mkexpr(ab0
))));
24615 /* saturate-narrow to 32bit, and combine to V128 */
24616 putVReg( vD_addr
, mkV128from4x64S( mkexpr(z3
), mkexpr(z2
),
24617 mkexpr(z1
), mkexpr(z0
)) );
24621 vex_printf("dis_av_multarith(ppc)(opc2)\n");
24628 AltiVec Polynomial Multiply-Sum Instructions
24630 static Bool
dis_av_polymultarith ( UInt theInstr
)
24633 UChar opc1
= ifieldOPC(theInstr
);
24634 UChar vD_addr
= ifieldRegDS(theInstr
);
24635 UChar vA_addr
= ifieldRegA(theInstr
);
24636 UChar vB_addr
= ifieldRegB(theInstr
);
24637 UChar vC_addr
= ifieldRegC(theInstr
);
24638 UInt opc2
= IFIELD(theInstr
, 0, 11);
24639 IRTemp vA
= newTemp(Ity_V128
);
24640 IRTemp vB
= newTemp(Ity_V128
);
24641 IRTemp vC
= newTemp(Ity_V128
);
24643 assign( vA
, getVReg(vA_addr
));
24644 assign( vB
, getVReg(vB_addr
));
24645 assign( vC
, getVReg(vC_addr
));
24648 vex_printf("dis_av_polymultarith(ppc)(instr)\n");
24653 /* Polynomial Multiply-Add */
24654 case 0x408: // vpmsumb Vector Polynomial Multiply-sum Byte
24655 DIP("vpmsumb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24656 putVReg( vD_addr
, binop(Iop_PolynomialMulAdd8x16
,
24657 mkexpr(vA
), mkexpr(vB
)) );
24659 case 0x448: // vpmsumd Vector Polynomial Multiply-sum Double Word
24660 DIP("vpmsumd v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24661 putVReg( vD_addr
, binop(Iop_PolynomialMulAdd64x2
,
24662 mkexpr(vA
), mkexpr(vB
)) );
24664 case 0x488: // vpmsumw Vector Polynomial Multiply-sum Word
24665 DIP("vpmsumw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24666 putVReg( vD_addr
, binop(Iop_PolynomialMulAdd32x4
,
24667 mkexpr(vA
), mkexpr(vB
)) );
24669 case 0x4C8: // vpmsumh Vector Polynomial Multiply-sum Half Word
24670 DIP("vpmsumh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24671 putVReg( vD_addr
, binop(Iop_PolynomialMulAdd16x8
,
24672 mkexpr(vA
), mkexpr(vB
)) );
24675 vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2
);
24682 AltiVec Shift/Rotate Instructions
24684 static Bool
dis_av_shift ( UInt theInstr
)
24687 UChar opc1
= ifieldOPC(theInstr
);
24688 UChar vD_addr
= ifieldRegDS(theInstr
);
24689 UChar vA_addr
= ifieldRegA(theInstr
);
24690 UChar vB_addr
= ifieldRegB(theInstr
);
24691 UInt opc2
= IFIELD( theInstr
, 0, 11 );
24693 IRTemp vA
= newTemp(Ity_V128
);
24694 IRTemp vB
= newTemp(Ity_V128
);
24695 assign( vA
, getVReg(vA_addr
));
24696 assign( vB
, getVReg(vB_addr
));
24699 vex_printf("dis_av_shift(ppc)(instr)\n");
24705 case 0x004: // vrlb (Rotate Left Integer B, AV p234)
24706 DIP("vrlb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24707 putVReg( vD_addr
, binop(Iop_Rol8x16
, mkexpr(vA
), mkexpr(vB
)) );
24710 case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
24711 DIP("vrlh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24712 putVReg( vD_addr
, binop(Iop_Rol16x8
, mkexpr(vA
), mkexpr(vB
)) );
24715 case 0x084: // vrlw (Rotate Left Integer W, AV p236)
24716 DIP("vrlw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24717 putVReg( vD_addr
, binop(Iop_Rol32x4
, mkexpr(vA
), mkexpr(vB
)) );
24720 case 0x0C4: // vrld (Rotate Left Integer Double Word)
24721 DIP("vrld v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24722 putVReg( vD_addr
, binop(Iop_Rol64x2
, mkexpr(vA
), mkexpr(vB
)) );
24727 case 0x104: // vslb (Shift Left Integer B, AV p240)
24728 DIP("vslb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24729 putVReg( vD_addr
, binop(Iop_Shl8x16
, mkexpr(vA
), mkexpr(vB
)) );
24732 case 0x144: // vslh (Shift Left Integer HW, AV p242)
24733 DIP("vslh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24734 putVReg( vD_addr
, binop(Iop_Shl16x8
, mkexpr(vA
), mkexpr(vB
)) );
24737 case 0x184: // vslw (Shift Left Integer W, AV p244)
24738 DIP("vslw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24739 putVReg( vD_addr
, binop(Iop_Shl32x4
, mkexpr(vA
), mkexpr(vB
)) );
24742 case 0x5C4: // vsld (Shift Left Integer Double Word)
24743 DIP("vsld v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24744 putVReg( vD_addr
, binop(Iop_Shl64x2
, mkexpr(vA
), mkexpr(vB
)) );
24747 case 0x1C4: { // vsl (Shift Left, AV p239)
24748 IRTemp sh
= newTemp(Ity_I8
);
24749 DIP("vsl v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24750 assign( sh
, binop(Iop_And8
, mkU8(0x7),
24752 unop(Iop_V128to32
, mkexpr(vB
)))) );
24754 binop(Iop_ShlV128
, mkexpr(vA
), mkexpr(sh
)) );
24757 case 0x40C: { // vslo (Shift Left by Octet, AV p243)
24758 IRTemp sh
= newTemp(Ity_I8
);
24759 DIP("vslo v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24760 assign( sh
, binop(Iop_And8
, mkU8(0x78),
24762 unop(Iop_V128to32
, mkexpr(vB
)))) );
24764 binop(Iop_ShlV128
, mkexpr(vA
), mkexpr(sh
)) );
24770 case 0x204: // vsrb (Shift Right B, AV p256)
24771 DIP("vsrb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24772 putVReg( vD_addr
, binop(Iop_Shr8x16
, mkexpr(vA
), mkexpr(vB
)) );
24775 case 0x244: // vsrh (Shift Right HW, AV p257)
24776 DIP("vsrh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24777 putVReg( vD_addr
, binop(Iop_Shr16x8
, mkexpr(vA
), mkexpr(vB
)) );
24780 case 0x284: // vsrw (Shift Right W, AV p259)
24781 DIP("vsrw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24782 putVReg( vD_addr
, binop(Iop_Shr32x4
, mkexpr(vA
), mkexpr(vB
)) );
24785 case 0x2C4: { // vsr (Shift Right, AV p251)
24786 IRTemp sh
= newTemp(Ity_I8
);
24787 DIP("vsr v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24788 assign( sh
, binop(Iop_And8
, mkU8(0x7),
24790 unop(Iop_V128to32
, mkexpr(vB
)))) );
24792 binop(Iop_ShrV128
, mkexpr(vA
), mkexpr(sh
)) );
24795 case 0x304: // vsrab (Shift Right Alg B, AV p253)
24796 DIP("vsrab v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24797 putVReg( vD_addr
, binop(Iop_Sar8x16
, mkexpr(vA
), mkexpr(vB
)) );
24800 case 0x344: // vsrah (Shift Right Alg HW, AV p254)
24801 DIP("vsrah v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24802 putVReg( vD_addr
, binop(Iop_Sar16x8
, mkexpr(vA
), mkexpr(vB
)) );
24805 case 0x384: // vsraw (Shift Right Alg W, AV p255)
24806 DIP("vsraw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24807 putVReg( vD_addr
, binop(Iop_Sar32x4
, mkexpr(vA
), mkexpr(vB
)) );
24810 case 0x3C4: // vsrad (Shift Right Alg Double Word)
24811 DIP("vsrad v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24812 putVReg( vD_addr
, binop(Iop_Sar64x2
, mkexpr(vA
), mkexpr(vB
)) );
24815 case 0x44C: { // vsro (Shift Right by Octet, AV p258)
24816 IRTemp sh
= newTemp(Ity_I8
);
24817 DIP("vsro v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24818 assign( sh
, binop(Iop_And8
, mkU8(0x78),
24820 unop(Iop_V128to32
, mkexpr(vB
)))) );
24822 binop(Iop_ShrV128
, mkexpr(vA
), mkexpr(sh
)) );
24826 case 0x6C4: // vsrd (Shift Right Double Word)
24827 DIP("vsrd v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24828 putVReg( vD_addr
, binop(Iop_Shr64x2
, mkexpr(vA
), mkexpr(vB
)) );
24833 vex_printf("dis_av_shift(ppc)(opc2)\n");
24840 AltiVec Permute Instructions
24842 static Bool
dis_av_permute ( UInt theInstr
)
24844 /* VA-Form, VX-Form */
24845 UChar opc1
= ifieldOPC(theInstr
);
24846 UChar vD_addr
= ifieldRegDS(theInstr
);
24847 UChar vA_addr
= ifieldRegA(theInstr
);
24848 UChar UIMM_5
= vA_addr
;
24849 UChar vB_addr
= ifieldRegB(theInstr
);
24850 UChar vC_addr
= ifieldRegC(theInstr
);
24851 UChar b10
= ifieldBIT10(theInstr
);
24852 UChar SHB_uimm4
= toUChar( IFIELD( theInstr
, 6, 4 ) );
24853 UInt opc2
= toUChar( IFIELD( theInstr
, 0, 6 ) );
24855 UChar SIMM_8
= extend_s_5to8(UIMM_5
);
24857 IRTemp vA
= newTemp(Ity_V128
);
24858 IRTemp vB
= newTemp(Ity_V128
);
24859 IRTemp vC
= newTemp(Ity_V128
);
24860 assign( vA
, getVReg(vA_addr
));
24861 assign( vB
, getVReg(vB_addr
));
24862 assign( vC
, getVReg(vC_addr
));
24865 vex_printf("dis_av_permute(ppc)(instr)\n");
24870 case 0x2A: // vsel (Conditional Select, AV p238)
24871 DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24872 /* vD = (vA & ~vC) | (vB & vC) */
24873 putVReg( vD_addr
, binop(Iop_OrV128
,
24874 binop(Iop_AndV128
, mkexpr(vA
), unop(Iop_NotV128
, mkexpr(vC
))),
24875 binop(Iop_AndV128
, mkexpr(vB
), mkexpr(vC
))) );
24878 case 0x2B: { // vperm (Permute, AV p218)
24879 /* limited to two args for IR, so have to play games... */
24880 IRTemp a_perm
= newTemp(Ity_V128
);
24881 IRTemp b_perm
= newTemp(Ity_V128
);
24882 IRTemp mask
= newTemp(Ity_V128
);
24883 IRTemp vC_andF
= newTemp(Ity_V128
);
24884 DIP("vperm v%d,v%d,v%d,v%d\n",
24885 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24886 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
24887 IR specifies, and also to hide irrelevant bits from
24890 binop(Iop_AndV128
, mkexpr(vC
),
24891 unop(Iop_Dup8x16
, mkU8(0xF))) );
24893 binop(Iop_Perm8x16
, mkexpr(vA
), mkexpr(vC_andF
)) );
24895 binop(Iop_Perm8x16
, mkexpr(vB
), mkexpr(vC_andF
)) );
24896 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
24897 assign( mask
, binop(Iop_SarN8x16
,
24898 binop(Iop_ShlN8x16
, mkexpr(vC
), mkU8(3)),
24900 // dst = (a & ~mask) | (b & mask)
24901 putVReg( vD_addr
, binop(Iop_OrV128
,
24902 binop(Iop_AndV128
, mkexpr(a_perm
),
24903 unop(Iop_NotV128
, mkexpr(mask
))),
24904 binop(Iop_AndV128
, mkexpr(b_perm
),
24908 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
24910 vex_printf("dis_av_permute(ppc)(vsldoi)\n");
24913 DIP("vsldoi v%d,v%d,v%d,%d\n",
24914 vD_addr
, vA_addr
, vB_addr
, SHB_uimm4
);
24915 if (SHB_uimm4
== 0)
24916 putVReg( vD_addr
, mkexpr(vA
) );
24920 binop(Iop_ShlV128
, mkexpr(vA
), mkU8(SHB_uimm4
*8)),
24921 binop(Iop_ShrV128
, mkexpr(vB
), mkU8((16-SHB_uimm4
)*8))) );
24923 case 0x2D: { // vpermxor (Vector Permute and Exclusive-OR)
24924 IRTemp a_perm
= newTemp(Ity_V128
);
24925 IRTemp b_perm
= newTemp(Ity_V128
);
24926 IRTemp vrc_a
= newTemp(Ity_V128
);
24927 IRTemp vrc_b
= newTemp(Ity_V128
);
24929 DIP("vpermxor v%d,v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24931 /* IBM index is 0:7, Change index value to index 7:0 */
24932 assign( vrc_b
, binop( Iop_AndV128
, mkexpr( vC
),
24933 unop( Iop_Dup8x16
, mkU8( 0xF ) ) ) );
24934 assign( vrc_a
, binop( Iop_ShrV128
,
24935 binop( Iop_AndV128
, mkexpr( vC
),
24936 unop( Iop_Dup8x16
, mkU8( 0xF0 ) ) ),
24938 assign( a_perm
, binop( Iop_Perm8x16
, mkexpr( vA
), mkexpr( vrc_a
) ) );
24939 assign( b_perm
, binop( Iop_Perm8x16
, mkexpr( vB
), mkexpr( vrc_b
) ) );
24940 putVReg( vD_addr
, binop( Iop_XorV128
,
24941 mkexpr( a_perm
), mkexpr( b_perm
) ) );
24945 case 0x3B: { // vpermr (Vector Permute Right-indexed)
24946 /* limited to two args for IR, so have to play games... */
24947 IRTemp a_perm
= newTemp( Ity_V128
);
24948 IRTemp b_perm
= newTemp( Ity_V128
);
24949 IRTemp mask
= newTemp( Ity_V128
);
24950 IRTemp vC_andF
= newTemp( Ity_V128
);
24951 IRTemp vC_adj
= newTemp( Ity_V128
);
24953 DIP( "vpermr v%d,v%d,v%d,v%d\n",
24954 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
24955 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
24956 IR specifies, and also to hide irrelevant bits from
24961 binop( Iop_Sub16x8
,
24962 unop( Iop_Dup8x16
, mkU8( 0x1F ) ),
24965 binop( Iop_AndV128
, mkexpr( vC_adj
),
24966 unop( Iop_Dup8x16
, mkU8( 0xF ) ) ) );
24968 binop( Iop_Perm8x16
, mkexpr( vA
), mkexpr( vC_andF
) ) );
24970 binop( Iop_Perm8x16
, mkexpr( vB
), mkexpr( vC_andF
) ) );
24971 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
24972 assign( mask
, binop(Iop_SarN8x16
,
24973 binop( Iop_ShlN8x16
, mkexpr( vC_adj
),
24974 mkU8( 3 ) ), mkU8( 7 ) ) );
24975 // dst = (a & ~mask) | (b & mask)
24976 putVReg( vD_addr
, binop( Iop_OrV128
,
24977 binop( Iop_AndV128
, mkexpr( a_perm
),
24978 unop( Iop_NotV128
, mkexpr( mask
) ) ),
24979 binop( Iop_AndV128
, mkexpr( b_perm
),
24980 mkexpr( mask
) ) ) );
24985 break; // Fall through...
24988 opc2
= IFIELD( theInstr
, 0, 11 );
24992 case 0x00C: // vmrghb (Merge High B, AV p195)
24993 DIP("vmrghb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
24995 binop(Iop_InterleaveHI8x16
, mkexpr(vA
), mkexpr(vB
)) );
24998 case 0x04C: // vmrghh (Merge High HW, AV p196)
24999 DIP("vmrghh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25001 binop(Iop_InterleaveHI16x8
, mkexpr(vA
), mkexpr(vB
)) );
25004 case 0x08C: // vmrghw (Merge High W, AV p197)
25005 DIP("vmrghw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25007 binop(Iop_InterleaveHI32x4
, mkexpr(vA
), mkexpr(vB
)) );
25010 case 0x10C: // vmrglb (Merge Low B, AV p198)
25011 DIP("vmrglb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25013 binop(Iop_InterleaveLO8x16
, mkexpr(vA
), mkexpr(vB
)) );
25016 case 0x14C: // vmrglh (Merge Low HW, AV p199)
25017 DIP("vmrglh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25019 binop(Iop_InterleaveLO16x8
, mkexpr(vA
), mkexpr(vB
)) );
25022 case 0x18C: // vmrglw (Merge Low W, AV p200)
25023 DIP("vmrglw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25025 binop(Iop_InterleaveLO32x4
, mkexpr(vA
), mkexpr(vB
)) );
25028 /* Extract instructions */
25029 case 0x20D: // vextractub (Vector Extract Unsigned Byte)
25031 UChar uim
= IFIELD( theInstr
, 16, 4 );
25033 DIP("vextractub v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
25035 putVReg( vD_addr
, binop( Iop_ShlV128
,
25036 binop( Iop_AndV128
,
25037 binop( Iop_ShrV128
,
25042 mkU32( 31 - uim
) ) ) ),
25043 binop( Iop_64HLtoV128
,
25045 mkU64( 0xFFULL
) ) ),
25050 case 0x24D: // vextractuh (Vector Extract Unsigned Halfword)
25052 UChar uim
= IFIELD( theInstr
, 16, 4 );
25054 DIP("vextractuh v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
25056 putVReg( vD_addr
, binop( Iop_ShlV128
,
25057 binop( Iop_AndV128
,
25058 binop( Iop_ShrV128
,
25063 mkU32( 30 - uim
) ) ) ),
25064 binop( Iop_64HLtoV128
,
25066 mkU64( 0xFFFFULL
) ) ),
25071 case 0x28D: // vextractuw (Vector Extract Unsigned Word)
25073 UChar uim
= IFIELD( theInstr
, 16, 4 );
25075 DIP("vextractuw v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
25078 binop( Iop_ShlV128
,
25079 binop( Iop_AndV128
,
25080 binop( Iop_ShrV128
,
25085 mkU32( 28 - uim
) ) ) ),
25086 binop( Iop_64HLtoV128
,
25088 mkU64( 0xFFFFFFFFULL
) ) ),
25093 case 0x2CD: // vextractd (Vector Extract Double Word)
25095 UChar uim
= IFIELD( theInstr
, 16, 4 );
25097 DIP("vextractd v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
25100 binop( Iop_ShlV128
,
25101 binop( Iop_AndV128
,
25102 binop( Iop_ShrV128
,
25107 mkU32( 24 - uim
) ) ) ),
25108 binop( Iop_64HLtoV128
,
25110 mkU64( 0xFFFFFFFFFFFFFFFFULL
) ) ),
25115 /* Insert instructions */
25116 case 0x30D: // vinsertb (Vector insert Unsigned Byte)
25118 UChar uim
= IFIELD( theInstr
, 16, 4 );
25119 IRTemp shift
= newTemp( Ity_I8
);
25120 IRTemp vD
= newTemp( Ity_V128
);
25122 DIP("vinsertb v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
25124 assign( vD
, getVReg( vD_addr
) );
25126 assign( shift
, unop( Iop_32to8
,
25129 mkU32( 15 - ( uim
+ 0 ) ) ) ) );
25133 binop( Iop_ShlV128
,
25134 binop( Iop_AndV128
,
25135 binop( Iop_ShrV128
,
25137 mkU8( ( 15 - 7 )*8 ) ),
25138 binop( Iop_64HLtoV128
,
25140 mkU64( 0xFFULL
) ) ),
25142 binop( Iop_AndV128
,
25144 binop( Iop_ShlV128
,
25145 binop( Iop_64HLtoV128
,
25147 mkU64( 0xFFULL
) ),
25148 mkexpr( shift
) ) ),
25149 mkexpr( vD
) ) ) );
25153 case 0x34D: // vinserth (Vector insert Halfword)
25155 UChar uim
= IFIELD( theInstr
, 16, 4 );
25156 IRTemp shift
= newTemp( Ity_I8
);
25157 IRTemp vD
= newTemp( Ity_V128
);
25159 DIP("vinserth v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
25161 assign( vD
, getVReg( vD_addr
) );
25163 assign( shift
, unop( Iop_32to8
,
25166 mkU32( 15 - ( uim
+ 1 ) ) ) ) );
25170 binop( Iop_ShlV128
,
25171 binop( Iop_AndV128
,
25172 binop( Iop_ShrV128
,
25174 mkU8( (7 - 3)*16 ) ),
25175 binop( Iop_64HLtoV128
,
25177 mkU64( 0xFFFFULL
) ) ),
25179 binop( Iop_AndV128
,
25181 binop( Iop_ShlV128
,
25182 binop( Iop_64HLtoV128
,
25184 mkU64( 0xFFFFULL
) ),
25185 mkexpr( shift
) ) ),
25186 mkexpr( vD
) ) ) );
25190 case 0x38D: // vinsertw (Vector insert Word)
25192 UChar uim
= IFIELD( theInstr
, 16, 4 );
25193 IRTemp shift
= newTemp( Ity_I8
);
25194 IRTemp vD
= newTemp( Ity_V128
);
25196 DIP("vinsertw v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
25198 assign( vD
, getVReg( vD_addr
) );
25200 assign( shift
, unop( Iop_32to8
,
25203 mkU32( 15 - ( uim
+ 3 ) ) ) ) );
25207 binop( Iop_ShlV128
,
25208 binop( Iop_AndV128
,
25209 binop( Iop_ShrV128
,
25211 mkU8( (3 - 1) * 32 ) ),
25212 binop( Iop_64HLtoV128
,
25214 mkU64( 0xFFFFFFFFULL
) ) ),
25216 binop( Iop_AndV128
,
25218 binop( Iop_ShlV128
,
25219 binop( Iop_64HLtoV128
,
25221 mkU64( 0xFFFFFFFFULL
) ),
25222 mkexpr( shift
) ) ),
25223 mkexpr( vD
) ) ) );
25227 case 0x3CD: // vinsertd (Vector insert Doubleword)
25229 UChar uim
= IFIELD( theInstr
, 16, 4 );
25230 IRTemp shift
= newTemp( Ity_I8
);
25231 IRTemp vD
= newTemp( Ity_V128
);
25233 DIP("vinsertd v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
25235 assign( vD
, getVReg( vD_addr
) );
25237 assign( shift
, unop( Iop_32to8
,
25240 mkU32( 15 - ( uim
+ 7 ) ) ) ) );
25244 binop( Iop_ShlV128
,
25245 binop( Iop_AndV128
,
25246 binop( Iop_ShrV128
,
25248 mkU8( ( 1 - 0 ) * 64 ) ),
25249 binop( Iop_64HLtoV128
,
25251 mkU64( 0xFFFFFFFFFFFFFFFFULL
) ) ),
25253 binop( Iop_AndV128
,
25255 binop( Iop_ShlV128
,
25256 binop( Iop_64HLtoV128
,
25258 mkU64( 0xFFFFFFFFFFFFFFFFULL
) ),
25259 mkexpr( shift
) ) ),
25260 mkexpr( vD
) ) ) );
25265 case 0x20C: { // vspltb (Splat Byte, AV p245)
25266 /* vD = Dup8x16( vB[UIMM_5] ) */
25267 UChar sh_uimm
= (15 - (UIMM_5
& 15)) * 8;
25268 DIP("vspltb v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
25269 putVReg( vD_addr
, unop(Iop_Dup8x16
,
25270 unop(Iop_32to8
, unop(Iop_V128to32
,
25271 binop(Iop_ShrV128
, mkexpr(vB
), mkU8(sh_uimm
))))) );
25274 case 0x24C: { // vsplth (Splat Half Word, AV p246)
25275 UChar sh_uimm
= (7 - (UIMM_5
& 7)) * 16;
25276 DIP("vsplth v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
25277 putVReg( vD_addr
, unop(Iop_Dup16x8
,
25278 unop(Iop_32to16
, unop(Iop_V128to32
,
25279 binop(Iop_ShrV128
, mkexpr(vB
), mkU8(sh_uimm
))))) );
25282 case 0x28C: { // vspltw (Splat Word, AV p250)
25283 /* vD = Dup32x4( vB[UIMM_5] ) */
25284 UChar sh_uimm
= (3 - (UIMM_5
& 3)) * 32;
25285 DIP("vspltw v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
25286 putVReg( vD_addr
, unop(Iop_Dup32x4
,
25288 binop(Iop_ShrV128
, mkexpr(vB
), mkU8(sh_uimm
)))) );
25291 case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
25292 DIP("vspltisb v%d,%d\n", vD_addr
, (Char
)SIMM_8
);
25293 putVReg( vD_addr
, unop(Iop_Dup8x16
, mkU8(SIMM_8
)) );
25296 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
25297 DIP("vspltish v%d,%d\n", vD_addr
, (Char
)SIMM_8
);
25299 unop(Iop_Dup16x8
, mkU16(extend_s_8to32(SIMM_8
))) );
25302 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
25303 DIP("vspltisw v%d,%d\n", vD_addr
, (Char
)SIMM_8
);
25305 unop(Iop_Dup32x4
, mkU32(extend_s_8to32(SIMM_8
))) );
25308 case 0x68C: // vmrgow (Merge Odd Word)
25309 DIP("vmrgow v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25316 binop(Iop_CatOddLanes32x4
, mkexpr(vA
), mkexpr(vB
) ) );
25319 case 0x78C: // vmrgew (Merge Even Word)
25320 DIP("vmrgew v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25327 binop(Iop_CatEvenLanes32x4
, mkexpr(vA
), mkexpr(vB
) ) );
25331 vex_printf("dis_av_permute(ppc)(opc2)\n");
25338 Vector Integer Absolute Difference
25340 static Bool
dis_abs_diff ( UInt theInstr
)
25343 UChar opc1
= ifieldOPC( theInstr
);
25344 UChar vT_addr
= ifieldRegDS( theInstr
);
25345 UChar vA_addr
= ifieldRegA( theInstr
);
25346 UChar vB_addr
= ifieldRegB( theInstr
);
25347 UInt opc2
= IFIELD( theInstr
, 0, 11 );
25349 IRTemp vA
= newTemp( Ity_V128
);
25350 IRTemp vB
= newTemp( Ity_V128
);
25351 IRTemp vT
= newTemp( Ity_V128
);
25353 IRTemp vAminusB
= newTemp( Ity_V128
);
25354 IRTemp vBminusA
= newTemp( Ity_V128
);
25355 IRTemp vMask
= newTemp( Ity_V128
);
25357 assign( vA
, getVReg( vA_addr
) );
25358 assign( vB
, getVReg( vB_addr
) );
25360 if ( opc1
!= 0x4 ) {
25361 vex_printf("dis_abs_diff(ppc)(instr)\n");
25366 case 0x403: // vabsdub Vector absolute difference Unsigned Byte
25368 DIP("vabsdub v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
25370 /* Determine which of the corresponding bytes is larger,
25371 * create mask with 1's in byte positions where vA[i] > vB[i]
25373 assign( vMask
, binop( Iop_CmpGT8Ux16
, mkexpr( vA
), mkexpr( vB
) ) );
25376 binop( Iop_AndV128
,
25377 binop( Iop_Sub8x16
, mkexpr( vA
), mkexpr( vB
) ),
25378 mkexpr( vMask
) ) );
25381 binop( Iop_AndV128
,
25382 binop( Iop_Sub8x16
, mkexpr( vB
), mkexpr( vA
) ),
25383 unop ( Iop_NotV128
, mkexpr( vMask
) ) ) );
25385 assign( vT
, binop( Iop_OrV128
,
25386 mkexpr( vAminusB
),
25387 mkexpr( vBminusA
) ) );
25391 case 0x443: // vabsduh Vector absolute difference Unsigned Halfword
25393 DIP("vabsduh v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
25395 /* Determine which of the corresponding halfwords is larger,
25396 * create mask with 1's in halfword positions where vA[i] > vB[i]
25398 assign( vMask
, binop( Iop_CmpGT16Ux8
, mkexpr( vA
), mkexpr( vB
) ) );
25401 binop( Iop_AndV128
,
25402 binop( Iop_Sub16x8
, mkexpr( vA
), mkexpr( vB
) ),
25403 mkexpr( vMask
) ) );
25406 binop( Iop_AndV128
,
25407 binop( Iop_Sub16x8
, mkexpr( vB
), mkexpr( vA
) ),
25408 unop ( Iop_NotV128
, mkexpr( vMask
) ) ) );
25410 assign( vT
, binop( Iop_OrV128
,
25411 mkexpr( vAminusB
),
25412 mkexpr( vBminusA
) ) );
25416 case 0x483: // vabsduw Vector absolute difference Unsigned Word
25418 DIP("vabsduw v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
25420 /* Determine which of the corresponding words is larger,
25421 * create mask with 1's in word positions where vA[i] > vB[i]
25423 assign( vMask
, binop( Iop_CmpGT32Ux4
, mkexpr( vA
), mkexpr( vB
) ) );
25426 binop( Iop_AndV128
,
25427 binop( Iop_Sub32x4
, mkexpr( vA
), mkexpr( vB
) ),
25428 mkexpr( vMask
) ) );
25431 binop( Iop_AndV128
,
25432 binop( Iop_Sub32x4
, mkexpr( vB
), mkexpr( vA
) ),
25433 unop ( Iop_NotV128
, mkexpr( vMask
) ) ) );
25435 assign( vT
, binop( Iop_OrV128
,
25436 mkexpr( vAminusB
),
25437 mkexpr( vBminusA
) ) );
25445 putVReg( vT_addr
, mkexpr( vT
) );
25451 AltiVec 128 bit integer multiply by 10 Instructions
25453 static Bool
dis_av_mult10 ( UInt theInstr
)
25456 UChar opc1
= ifieldOPC(theInstr
);
25457 UChar vT_addr
= ifieldRegDS(theInstr
);
25458 UChar vA_addr
= ifieldRegA(theInstr
);
25459 UChar vB_addr
= ifieldRegB(theInstr
);
25460 UInt opc2
= IFIELD( theInstr
, 0, 11 );
25462 IRTemp vA
= newTemp(Ity_V128
);
25463 assign( vA
, getVReg(vA_addr
));
25466 vex_printf("dis_av_mult10(ppc)(instr)\n");
25470 case 0x001: { // vmul10cuq (Vector Multiply-by-10 and write carry
25471 DIP("vmul10cuq v%d,v%d\n", vT_addr
, vA_addr
);
25473 unop( Iop_MulI128by10Carry
, mkexpr( vA
) ) );
25476 case 0x041: { // vmul10uq (Vector Multiply-by-10 Extended and write carry
25477 // Unsigned Quadword VX form)
25478 IRTemp vB
= newTemp(Ity_V128
);
25479 assign( vB
, getVReg(vB_addr
));
25480 DIP("vmul10ecuq v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
25482 binop( Iop_MulI128by10ECarry
, mkexpr( vA
), mkexpr( vB
) ) );
25485 case 0x201: { // vmul10uq (Vector Multiply-by-10 Unsigned Quadword VX form)
25486 DIP("vmul10uq v%d,v%d\n", vT_addr
, vA_addr
);
25488 unop( Iop_MulI128by10
, mkexpr( vA
) ) );
25491 case 0x241: { // vmul10uq (Vector Multiply-by-10 Extended
25492 // Unsigned Quadword VX form)
25493 IRTemp vB
= newTemp(Ity_V128
);
25494 assign( vB
, getVReg(vB_addr
));
25495 DIP("vmul10euq v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
25497 binop( Iop_MulI128by10E
, mkexpr( vA
), mkexpr( vB
) ) );
25501 vex_printf("dis_av_mult10(ppc)(opc2)\n");
25508 AltiVec Pack/Unpack Instructions
25510 static Bool
dis_av_pack ( UInt theInstr
)
25513 UChar opc1
= ifieldOPC(theInstr
);
25514 UChar vD_addr
= ifieldRegDS(theInstr
);
25515 UChar vA_addr
= ifieldRegA(theInstr
);
25516 UChar vB_addr
= ifieldRegB(theInstr
);
25517 UInt opc2
= IFIELD( theInstr
, 0, 11 );
25519 IRTemp signs
= IRTemp_INVALID
;
25520 IRTemp zeros
= IRTemp_INVALID
;
25521 IRTemp vA
= newTemp(Ity_V128
);
25522 IRTemp vB
= newTemp(Ity_V128
);
25523 assign( vA
, getVReg(vA_addr
));
25524 assign( vB
, getVReg(vB_addr
));
25527 vex_printf("dis_av_pack(ppc)(instr)\n");
25532 case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
25533 DIP("vpkuhum v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25535 binop(Iop_NarrowBin16to8x16
, mkexpr(vA
), mkexpr(vB
)) );
25538 case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
25539 DIP("vpkuwum v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25541 binop(Iop_NarrowBin32to16x8
, mkexpr(vA
), mkexpr(vB
)) );
25544 case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
25545 DIP("vpkuhus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25547 binop(Iop_QNarrowBin16Uto8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
25548 // TODO: set VSCR[SAT]
25551 case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
25552 DIP("vpkuwus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25554 binop(Iop_QNarrowBin32Uto16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
25555 // TODO: set VSCR[SAT]
25558 case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
25559 // This insn does a signed->unsigned saturating conversion.
25560 // Conversion done here, then uses unsigned->unsigned vpk insn:
25561 // => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
25562 IRTemp vA_tmp
= newTemp(Ity_V128
);
25563 IRTemp vB_tmp
= newTemp(Ity_V128
);
25564 DIP("vpkshus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25565 assign( vA_tmp
, binop(Iop_AndV128
, mkexpr(vA
),
25567 binop(Iop_SarN16x8
,
25568 mkexpr(vA
), mkU8(15)))) );
25569 assign( vB_tmp
, binop(Iop_AndV128
, mkexpr(vB
),
25571 binop(Iop_SarN16x8
,
25572 mkexpr(vB
), mkU8(15)))) );
25573 putVReg( vD_addr
, binop(Iop_QNarrowBin16Uto8Ux16
,
25574 mkexpr(vA_tmp
), mkexpr(vB_tmp
)) );
25575 // TODO: set VSCR[SAT]
25578 case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
25579 // This insn does a signed->unsigned saturating conversion.
25580 // Conversion done here, then uses unsigned->unsigned vpk insn:
25581 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
25582 IRTemp vA_tmp
= newTemp(Ity_V128
);
25583 IRTemp vB_tmp
= newTemp(Ity_V128
);
25584 DIP("vpkswus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25585 assign( vA_tmp
, binop(Iop_AndV128
, mkexpr(vA
),
25587 binop(Iop_SarN32x4
,
25588 mkexpr(vA
), mkU8(31)))) );
25589 assign( vB_tmp
, binop(Iop_AndV128
, mkexpr(vB
),
25591 binop(Iop_SarN32x4
,
25592 mkexpr(vB
), mkU8(31)))) );
25593 putVReg( vD_addr
, binop(Iop_QNarrowBin32Uto16Ux8
,
25594 mkexpr(vA_tmp
), mkexpr(vB_tmp
)) );
25595 // TODO: set VSCR[SAT]
25598 case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
25599 DIP("vpkshss v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25601 binop(Iop_QNarrowBin16Sto8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
25602 // TODO: set VSCR[SAT]
25605 case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
25606 DIP("vpkswss v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25608 binop(Iop_QNarrowBin32Sto16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
25609 // TODO: set VSCR[SAT]
25612 case 0x30E: { // vpkpx (Pack Pixel, AV p219)
25613 /* CAB: Worth a new primop? */
25614 /* Using shifts to compact pixel elements, then packing them */
25615 IRTemp a1
= newTemp(Ity_V128
);
25616 IRTemp a2
= newTemp(Ity_V128
);
25617 IRTemp a3
= newTemp(Ity_V128
);
25618 IRTemp a_tmp
= newTemp(Ity_V128
);
25619 IRTemp b1
= newTemp(Ity_V128
);
25620 IRTemp b2
= newTemp(Ity_V128
);
25621 IRTemp b3
= newTemp(Ity_V128
);
25622 IRTemp b_tmp
= newTemp(Ity_V128
);
25623 DIP("vpkpx v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25624 assign( a1
, binop(Iop_ShlN16x8
,
25625 binop(Iop_ShrN32x4
, mkexpr(vA
), mkU8(19)),
25627 assign( a2
, binop(Iop_ShlN16x8
,
25628 binop(Iop_ShrN16x8
, mkexpr(vA
), mkU8(11)),
25630 assign( a3
, binop(Iop_ShrN16x8
,
25631 binop(Iop_ShlN16x8
, mkexpr(vA
), mkU8(8)),
25633 assign( a_tmp
, binop(Iop_OrV128
, mkexpr(a1
),
25634 binop(Iop_OrV128
, mkexpr(a2
), mkexpr(a3
))) );
25636 assign( b1
, binop(Iop_ShlN16x8
,
25637 binop(Iop_ShrN32x4
, mkexpr(vB
), mkU8(19)),
25639 assign( b2
, binop(Iop_ShlN16x8
,
25640 binop(Iop_ShrN16x8
, mkexpr(vB
), mkU8(11)),
25642 assign( b3
, binop(Iop_ShrN16x8
,
25643 binop(Iop_ShlN16x8
, mkexpr(vB
), mkU8(8)),
25645 assign( b_tmp
, binop(Iop_OrV128
, mkexpr(b1
),
25646 binop(Iop_OrV128
, mkexpr(b2
), mkexpr(b3
))) );
25648 putVReg( vD_addr
, binop(Iop_NarrowBin32to16x8
,
25649 mkexpr(a_tmp
), mkexpr(b_tmp
)) );
25653 case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
25654 DIP("vpkudum v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25656 binop(Iop_NarrowBin64to32x4
, mkexpr(vA
), mkexpr(vB
)) );
25659 case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
25660 DIP("vpkudus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25662 binop(Iop_QNarrowBin64Uto32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
25663 // TODO: set VSCR[SAT]
25666 case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
25667 // This insn does a doubled signed->double unsigned saturating conversion
25668 // Conversion done here, then uses unsigned->unsigned vpk insn:
25669 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
25670 // This is similar to the technique used for vpkswus, except done
25671 // with double word integers versus word integers.
25672 IRTemp vA_tmp
= newTemp(Ity_V128
);
25673 IRTemp vB_tmp
= newTemp(Ity_V128
);
25674 DIP("vpksdus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25675 assign( vA_tmp
, binop(Iop_AndV128
, mkexpr(vA
),
25677 binop(Iop_SarN64x2
,
25678 mkexpr(vA
), mkU8(63)))) );
25679 assign( vB_tmp
, binop(Iop_AndV128
, mkexpr(vB
),
25681 binop(Iop_SarN64x2
,
25682 mkexpr(vB
), mkU8(63)))) );
25683 putVReg( vD_addr
, binop(Iop_QNarrowBin64Uto32Ux4
,
25684 mkexpr(vA_tmp
), mkexpr(vB_tmp
)) );
25685 // TODO: set VSCR[SAT]
25689 case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
25690 DIP("vpksdss v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25692 binop(Iop_QNarrowBin64Sto32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
25693 // TODO: set VSCR[SAT]
25696 break; // Fall through...
25700 if (vA_addr
!= 0) {
25701 vex_printf("dis_av_pack(ppc)(vA_addr)\n");
25705 signs
= newTemp(Ity_V128
);
25706 zeros
= newTemp(Ity_V128
);
25707 assign( zeros
, unop(Iop_Dup32x4
, mkU32(0)) );
25711 case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
25712 DIP("vupkhsb v%d,v%d\n", vD_addr
, vB_addr
);
25713 assign( signs
, binop(Iop_CmpGT8Sx16
, mkexpr(zeros
), mkexpr(vB
)) );
25715 binop(Iop_InterleaveHI8x16
, mkexpr(signs
), mkexpr(vB
)) );
25718 case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
25719 DIP("vupkhsh v%d,v%d\n", vD_addr
, vB_addr
);
25720 assign( signs
, binop(Iop_CmpGT16Sx8
, mkexpr(zeros
), mkexpr(vB
)) );
25722 binop(Iop_InterleaveHI16x8
, mkexpr(signs
), mkexpr(vB
)) );
25725 case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
25726 DIP("vupklsb v%d,v%d\n", vD_addr
, vB_addr
);
25727 assign( signs
, binop(Iop_CmpGT8Sx16
, mkexpr(zeros
), mkexpr(vB
)) );
25729 binop(Iop_InterleaveLO8x16
, mkexpr(signs
), mkexpr(vB
)) );
25732 case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
25733 DIP("vupklsh v%d,v%d\n", vD_addr
, vB_addr
);
25734 assign( signs
, binop(Iop_CmpGT16Sx8
, mkexpr(zeros
), mkexpr(vB
)) );
25736 binop(Iop_InterleaveLO16x8
, mkexpr(signs
), mkexpr(vB
)) );
25739 case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
25740 /* CAB: Worth a new primop? */
25741 /* Using shifts to isolate pixel elements, then expanding them */
25742 IRTemp z0
= newTemp(Ity_V128
);
25743 IRTemp z1
= newTemp(Ity_V128
);
25744 IRTemp z01
= newTemp(Ity_V128
);
25745 IRTemp z2
= newTemp(Ity_V128
);
25746 IRTemp z3
= newTemp(Ity_V128
);
25747 IRTemp z23
= newTemp(Ity_V128
);
25748 DIP("vupkhpx v%d,v%d\n", vD_addr
, vB_addr
);
25749 assign( z0
, binop(Iop_ShlN16x8
,
25750 binop(Iop_SarN16x8
, mkexpr(vB
), mkU8(15)),
25752 assign( z1
, binop(Iop_ShrN16x8
,
25753 binop(Iop_ShlN16x8
, mkexpr(vB
), mkU8(1)),
25755 assign( z01
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
),
25756 binop(Iop_OrV128
, mkexpr(z0
), mkexpr(z1
))) );
25757 assign( z2
, binop(Iop_ShrN16x8
,
25758 binop(Iop_ShlN16x8
,
25759 binop(Iop_ShrN16x8
, mkexpr(vB
), mkU8(5)),
25762 assign( z3
, binop(Iop_ShrN16x8
,
25763 binop(Iop_ShlN16x8
, mkexpr(vB
), mkU8(11)),
25765 assign( z23
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
),
25766 binop(Iop_OrV128
, mkexpr(z2
), mkexpr(z3
))) );
25769 binop(Iop_ShlN32x4
, mkexpr(z01
), mkU8(16)),
25773 case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
25774 /* identical to vupkhpx, except interleaving LO */
25775 IRTemp z0
= newTemp(Ity_V128
);
25776 IRTemp z1
= newTemp(Ity_V128
);
25777 IRTemp z01
= newTemp(Ity_V128
);
25778 IRTemp z2
= newTemp(Ity_V128
);
25779 IRTemp z3
= newTemp(Ity_V128
);
25780 IRTemp z23
= newTemp(Ity_V128
);
25781 DIP("vupklpx v%d,v%d\n", vD_addr
, vB_addr
);
25782 assign( z0
, binop(Iop_ShlN16x8
,
25783 binop(Iop_SarN16x8
, mkexpr(vB
), mkU8(15)),
25785 assign( z1
, binop(Iop_ShrN16x8
,
25786 binop(Iop_ShlN16x8
, mkexpr(vB
), mkU8(1)),
25788 assign( z01
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
),
25789 binop(Iop_OrV128
, mkexpr(z0
), mkexpr(z1
))) );
25790 assign( z2
, binop(Iop_ShrN16x8
,
25791 binop(Iop_ShlN16x8
,
25792 binop(Iop_ShrN16x8
, mkexpr(vB
), mkU8(5)),
25795 assign( z3
, binop(Iop_ShrN16x8
,
25796 binop(Iop_ShlN16x8
, mkexpr(vB
), mkU8(11)),
25798 assign( z23
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
),
25799 binop(Iop_OrV128
, mkexpr(z2
), mkexpr(z3
))) );
25802 binop(Iop_ShlN32x4
, mkexpr(z01
), mkU8(16)),
25806 case 0x64E: { // vupkhsw (Unpack High Signed Word)
25807 DIP("vupkhsw v%d,v%d\n", vD_addr
, vB_addr
);
25808 assign( signs
, binop(Iop_CmpGT32Sx4
, mkexpr(zeros
), mkexpr(vB
)) );
25810 binop(Iop_InterleaveHI32x4
, mkexpr(signs
), mkexpr(vB
)) );
25813 case 0x6CE: { // vupklsw (Unpack Low Signed Word)
25814 DIP("vupklsw v%d,v%d\n", vD_addr
, vB_addr
);
25815 assign( signs
, binop(Iop_CmpGT32Sx4
, mkexpr(zeros
), mkexpr(vB
)) );
25817 binop(Iop_InterleaveLO32x4
, mkexpr(signs
), mkexpr(vB
)) );
25821 vex_printf("dis_av_pack(ppc)(opc2)\n");
25828 AltiVec Cipher Instructions
25830 static Bool
dis_av_cipher ( UInt theInstr
)
25833 UChar opc1
= ifieldOPC(theInstr
);
25834 UChar vD_addr
= ifieldRegDS(theInstr
);
25835 UChar vA_addr
= ifieldRegA(theInstr
);
25836 UChar vB_addr
= ifieldRegB(theInstr
);
25837 UInt opc2
= IFIELD( theInstr
, 0, 11 );
25839 IRTemp vA
= newTemp(Ity_V128
);
25840 IRTemp vB
= newTemp(Ity_V128
);
25841 assign( vA
, getVReg(vA_addr
));
25842 assign( vB
, getVReg(vB_addr
));
25845 vex_printf("dis_av_cipher(ppc)(instr)\n");
25849 case 0x508: // vcipher (Vector Inverser Cipher)
25850 DIP("vcipher v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25852 binop(Iop_CipherV128
, mkexpr(vA
), mkexpr(vB
)) );
25855 case 0x509: // vcipherlast (Vector Inverser Cipher Last)
25856 DIP("vcipherlast v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25858 binop(Iop_CipherLV128
, mkexpr(vA
), mkexpr(vB
)) );
25861 case 0x548: // vncipher (Vector Inverser Cipher)
25862 DIP("vncipher v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25864 binop(Iop_NCipherV128
, mkexpr(vA
), mkexpr(vB
)) );
25867 case 0x549: // vncipherlast (Vector Inverser Cipher Last)
25868 DIP("vncipherlast v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
25870 binop(Iop_NCipherLV128
, mkexpr(vA
), mkexpr(vB
)) );
25873 case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
25874 * subBytes transform)
25876 DIP("vsbox v%d,v%d\n", vD_addr
, vA_addr
);
25878 unop(Iop_CipherSV128
, mkexpr(vA
) ) );
25882 vex_printf("dis_av_cipher(ppc)(opc2)\n");
25889 AltiVec Secure Hash Instructions
25891 static Bool
dis_av_hash ( UInt theInstr
)
25894 UChar opc1
= ifieldOPC(theInstr
);
25895 UChar vRT_addr
= ifieldRegDS(theInstr
);
25896 UChar vRA_addr
= ifieldRegA(theInstr
);
25897 UChar s_field
= IFIELD( theInstr
, 11, 5 ); // st and six field
25898 UChar st
= IFIELD( theInstr
, 15, 1 ); // st
25899 UChar six
= IFIELD( theInstr
, 11, 4 ); // six field
25900 UInt opc2
= IFIELD( theInstr
, 0, 11 );
25902 IRTemp vA
= newTemp(Ity_V128
);
25903 IRTemp dst
= newTemp(Ity_V128
);
25904 assign( vA
, getVReg(vRA_addr
));
25907 vex_printf("dis_av_hash(ppc)(instr)\n");
25912 case 0x682: // vshasigmaw
25913 DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr
, vRA_addr
, st
, six
);
25914 assign( dst
, binop( Iop_SHA256
, mkexpr( vA
), mkU8( s_field
) ) );
25915 putVReg( vRT_addr
, mkexpr(dst
));
25918 case 0x6C2: // vshasigmad,
25919 DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr
, vRA_addr
, st
, six
);
25920 putVReg( vRT_addr
, binop( Iop_SHA512
, mkexpr( vA
), mkU8( s_field
) ) );
25924 vex_printf("dis_av_hash(ppc)(opc2)\n");
25931 * This function is used by the Vector add/subtract [extended] modulo/carry
25933 * - For the non-extended add instructions, the cin arg is set to zero.
25934 * - For the extended add instructions, cin is the integer value of
25936 * - For the non-extended subtract instructions, src1 is added to the one's
25937 * complement of src2 + 1. We re-use the cin argument to hold the '1'
25938 * value for this operation.
25939 * - For the extended subtract instructions, cin is the integer value of src3.bit[127].
25941 static IRTemp
_get_quad_modulo_or_carry(IRExpr
* vecA
, IRExpr
* vecB
,
25942 IRExpr
* cin
, Bool modulo
)
25944 IRTemp _vecA_32
= IRTemp_INVALID
;
25945 IRTemp _vecB_32
= IRTemp_INVALID
;
25946 IRTemp res_32
= IRTemp_INVALID
;
25947 IRTemp res_64
= IRTemp_INVALID
;
25948 IRTemp result
= IRTemp_INVALID
;
25949 IRTemp tmp_result
= IRTemp_INVALID
;
25950 IRTemp carry
= IRTemp_INVALID
;
25952 IRExpr
* _vecA_low64
= unop( Iop_V128to64
, vecA
);
25953 IRExpr
* _vecB_low64
= unop( Iop_V128to64
, vecB
);
25954 IRExpr
* _vecA_high64
= unop( Iop_V128HIto64
, vecA
);
25955 IRExpr
* _vecB_high64
= unop( Iop_V128HIto64
, vecB
);
25957 carry
= newTemp(Ity_I32
);
25958 assign( carry
, cin
);
25960 for (i
= 0; i
< 4; i
++) {
25961 _vecA_32
= newTemp(Ity_I32
);
25962 _vecB_32
= newTemp(Ity_I32
);
25963 res_32
= newTemp(Ity_I32
);
25964 res_64
= newTemp(Ity_I64
);
25968 assign(_vecA_32
, unop( Iop_64to32
, _vecA_low64
) );
25969 assign(_vecB_32
, unop( Iop_64to32
, _vecB_low64
) );
25972 assign(_vecA_32
, unop( Iop_64HIto32
, _vecA_low64
) );
25973 assign(_vecB_32
, unop( Iop_64HIto32
, _vecB_low64
) );
25976 assign(_vecA_32
, unop( Iop_64to32
, _vecA_high64
) );
25977 assign(_vecB_32
, unop( Iop_64to32
, _vecB_high64
) );
25980 assign(_vecA_32
, unop( Iop_64HIto32
, _vecA_high64
) );
25981 assign(_vecB_32
, unop( Iop_64HIto32
, _vecB_high64
) );
25985 assign( res_64
, binop( Iop_Add64
,
25987 binop( Iop_32HLto64
,
25989 mkexpr(_vecA_32
) ),
25990 binop( Iop_32HLto64
,
25992 mkexpr(_vecB_32
) ) ),
25993 binop( Iop_32HLto64
,
25995 mkexpr( carry
) ) ) );
25997 /* Calculate the carry to the next higher 32 bits. */
25998 carry
= newTemp(Ity_I32
);
25999 assign(carry
, unop( Iop_64HIto32
, mkexpr( res_64
) ) );
26001 /* result is the lower 32-bits */
26002 assign(res_32
, unop( Iop_64to32
, mkexpr( res_64
) ) );
26005 result
= newTemp(Ity_V128
);
26006 assign(result
, binop( Iop_OrV128
,
26007 (i
== 0) ? binop( Iop_64HLtoV128
,
26009 mkU64(0) ) : mkexpr(tmp_result
),
26010 binop( Iop_ShlV128
,
26011 binop( Iop_64HLtoV128
,
26013 binop( Iop_32HLto64
,
26015 mkexpr(res_32
) ) ),
26016 mkU8(i
* 32) ) ) );
26017 tmp_result
= newTemp(Ity_V128
);
26018 assign(tmp_result
, mkexpr(result
));
26028 static Bool
dis_av_quad ( UInt theInstr
)
26031 UChar opc1
= ifieldOPC(theInstr
);
26032 UChar vRT_addr
= ifieldRegDS(theInstr
);
26033 UChar vRA_addr
= ifieldRegA(theInstr
);
26034 UChar vRB_addr
= ifieldRegB(theInstr
);
26036 UInt opc2
= IFIELD( theInstr
, 0, 11 );
26038 IRTemp vA
= newTemp(Ity_V128
);
26039 IRTemp vB
= newTemp(Ity_V128
);
26040 IRTemp vC
= IRTemp_INVALID
;
26041 IRTemp cin
= IRTemp_INVALID
;
26042 assign( vA
, getVReg(vRA_addr
));
26043 assign( vB
, getVReg(vRB_addr
));
26046 vex_printf("dis_av_quad(ppc)(instr)\n");
26051 case 0x140: // vaddcuq
26052 DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
26053 putVReg( vRT_addr
, unop( Iop_32UtoV128
,
26054 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
26056 mkU32(0), False
) ) ) );
26058 case 0x100: // vadduqm
26059 DIP("vadduqm v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
26060 putVReg( vRT_addr
, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
26061 mkexpr(vB
), mkU32(0), True
) ) );
26063 case 0x540: // vsubcuq
26064 DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
26066 unop( Iop_32UtoV128
,
26067 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
26070 mkU32(1), False
) ) ) );
26072 case 0x500: // vsubuqm
26073 DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
26075 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
26076 unop( Iop_NotV128
, mkexpr(vB
) ),
26077 mkU32(1), True
) ) );
26079 case 0x054C: // vbpermq
26081 #define BPERMD_IDX_MASK 0x00000000000000FFULL
26082 #define BPERMD_BIT_MASK 0x8000000000000000ULL
26084 IRExpr
* vB_expr
= mkexpr(vB
);
26085 IRExpr
* res
= binop(Iop_AndV128
, mkV128(0), mkV128(0));
26086 DIP("vbpermq v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
26087 for (i
= 0; i
< 16; i
++) {
26088 IRTemp idx_tmp
= newTemp( Ity_V128
);
26089 IRTemp perm_bit
= newTemp( Ity_V128
);
26090 IRTemp idx
= newTemp( Ity_I8
);
26091 IRTemp idx_LT127
= newTemp( Ity_I1
);
26092 IRTemp idx_LT127_ity128
= newTemp( Ity_V128
);
26095 binop( Iop_AndV128
,
26096 binop( Iop_64HLtoV128
,
26098 mkU64(BPERMD_IDX_MASK
) ),
26101 binop( Iop_CmpEQ32
,
26103 unop( Iop_V128to64
, binop( Iop_ShrV128
,
26108 /* Below, we set idx to determine which bit of vA to use for the
26109 * perm bit. If idx_LT127 is 0, the perm bit is forced to '0'.
26114 mkexpr(idx_LT127
) ),
26116 unop( Iop_V128to32
, mkexpr( idx_tmp
) ) ) ) );
26118 assign( idx_LT127_ity128
,
26119 binop( Iop_64HLtoV128
,
26122 unop( Iop_1Uto32
, mkexpr(idx_LT127
) ) ) ) );
26124 binop( Iop_AndV128
,
26125 mkexpr( idx_LT127_ity128
),
26126 binop( Iop_ShrV128
,
26127 binop( Iop_AndV128
,
26128 binop (Iop_64HLtoV128
,
26129 mkU64( BPERMD_BIT_MASK
),
26131 binop( Iop_ShlV128
,
26135 res
= binop( Iop_OrV128
,
26137 binop( Iop_ShlV128
,
26138 mkexpr( perm_bit
),
26139 mkU8( i
+ 64 ) ) );
26140 vB_expr
= binop( Iop_ShrV128
, vB_expr
, mkU8( 8 ) );
26142 putVReg( vRT_addr
, res
);
26144 #undef BPERMD_IDX_MASK
26145 #undef BPERMD_BIT_MASK
26149 break; // fall through
26152 opc2
= IFIELD( theInstr
, 0, 6 );
26153 vRC_addr
= ifieldRegC(theInstr
);
26154 vC
= newTemp(Ity_V128
);
26155 cin
= newTemp(Ity_I32
);
26157 case 0x3D: // vaddecuq
26158 assign( vC
, getVReg(vRC_addr
));
26159 DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
,
26161 assign(cin
, binop( Iop_And32
,
26163 unop( Iop_V128to64
, mkexpr(vC
) ) ),
26166 unop( Iop_32UtoV128
,
26167 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
), mkexpr(vB
),
26171 case 0x3C: // vaddeuqm
26172 assign( vC
, getVReg(vRC_addr
));
26173 DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
,
26175 assign(cin
, binop( Iop_And32
,
26177 unop( Iop_V128to64
, mkexpr(vC
) ) ),
26180 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
), mkexpr(vB
),
26184 case 0x3F: // vsubecuq
26185 assign( vC
, getVReg(vRC_addr
));
26186 DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
,
26188 assign(cin
, binop( Iop_And32
,
26190 unop( Iop_V128to64
, mkexpr(vC
) ) ),
26193 unop( Iop_32UtoV128
,
26194 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
26200 case 0x3E: // vsubeuqm
26201 assign( vC
, getVReg(vRC_addr
));
26202 DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
,
26204 assign(cin
, binop( Iop_And32
,
26206 unop( Iop_V128to64
, mkexpr(vC
) ) ),
26209 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
26210 unop( Iop_NotV128
, mkexpr(vB
) ),
26215 vex_printf("dis_av_quad(ppc)(opc2.2)\n");
26222 static IRExpr
* bcd_sign_code_adjust( UInt ps
, IRExpr
* tmp
)
26224 /* The Iop_BCDAdd and Iop_BCDSub will result in the corresponding Power PC
26225 * instruction being issued with ps = 0. If ps = 1, the sign code, which
26226 * is in the least significant four bits of the result, needs to be updated
26229 * If PS=0, the sign code of the result is set to 0b1100.
26230 * If PS=1, the sign code of the result is set to 0b1111.
26232 * Note, the ps value is NOT being passed down to the instruction issue
26233 * because passing a constant via triop() breaks the vbit-test test. The
26234 * vbit-tester assumes it can set non-zero shadow bits for the triop()
26235 * arguments. Thus they have to be expressions not a constant.
26236 * Use 32-bit compare instructiions as 64-bit compares are not supported
26239 IRTemp mask
= newTemp(Ity_I64
);
26243 /* sign code is correct, just return it. */
26247 /* Check if lower four bits are 0b1100, if so, change to 0b1111 */
26248 /* Make this work in 32-bit mode using only 32-bit compares */
26249 assign( mask
, unop( Iop_1Sto64
,
26250 binop( Iop_CmpEQ32
, mkU32( 0xC ),
26251 binop( Iop_And32
, mkU32( 0xF ),
26253 unop( Iop_V128to64
, tmp
)
26255 rtn
= binop( Iop_64HLtoV128
,
26256 unop( Iop_V128HIto64
, tmp
),
26258 binop( Iop_And64
, mkU64( 0xF ), mkexpr( mask
) ),
26259 unop( Iop_V128to64
, tmp
) ) );
26266 AltiVec BCD Arithmetic instructions.
26267 These instructions modify CR6 for various conditions in the result,
26268 including when an overflow occurs. We could easily detect all conditions
26269 except when an overflow occurs. But since we can't be 100% accurate
26270 in our emulation of CR6, it seems best to just not support it all.
26272 static Bool
dis_av_bcd_misc ( UInt theInstr
, const VexAbiInfo
* vbi
)
26274 UChar opc1
= ifieldOPC(theInstr
);
26275 UChar vRT_addr
= ifieldRegDS(theInstr
);
26276 UChar vRA_addr
= ifieldRegA(theInstr
);
26277 UChar vRB_addr
= ifieldRegB(theInstr
);
26278 IRTemp vA
= newTemp(Ity_V128
);
26279 IRTemp vB
= newTemp(Ity_V128
);
26280 UInt opc2
= IFIELD( theInstr
, 0, 11 );
26281 IRExpr
*pos
, *neg
, *valid
, *zero
, *sign
;
26282 IRTemp eq_lt_gt
= newTemp( Ity_I32
);
26284 assign( vA
, getVReg(vRA_addr
));
26285 assign( vB
, getVReg(vRB_addr
));
26288 vex_printf("dis_av_bcd_misc(ppc)(instr)\n");
26293 case 0x341: // bcdcpsgn. Decimal Copy Sign VX-form
26295 IRExpr
*sign_vb
, *value_va
;
26296 DIP("bcdcpsgn. v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
26299 BCDstring_zero( binop( Iop_AndV128
,
26300 binop( Iop_64HLtoV128
,
26301 mkU64( 0xFFFFFFFFFFFFFFFF ),
26302 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26305 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26306 * codes 0xB and 0xD are negative.
26308 sign
= binop( Iop_And64
, mkU64( 0xF ),
26309 unop( Iop_V128to64
, mkexpr( vB
) ) );
26311 neg
= mkOR1( binop( Iop_CmpEQ64
,
26314 binop( Iop_CmpEQ64
,
26318 pos
= mkNOT1( neg
);
26320 /* invalid if vA or vB is not valid */
26324 is_BCDstring128( vbi
,
26325 /*Signed*/True
, mkexpr( vA
) ),
26326 is_BCDstring128( vbi
,
26327 /*Signed*/True
, mkexpr( vB
) ) ) );
26329 sign_vb
= binop( Iop_AndV128
,
26330 binop( Iop_64HLtoV128
,
26335 value_va
= binop( Iop_AndV128
,
26336 binop( Iop_64HLtoV128
,
26337 mkU64( 0xFFFFFFFFFFFFFFFF ),
26338 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26340 putVReg( vRT_addr
, binop( Iop_OrV128
, sign_vb
, value_va
) );
26345 vex_printf("dis_av_bcd_misc(ppc)(opc2)\n");
26349 /* set CR field 6 to:
26350 * 0b1000 if vB less then 0, i.e. vB is neg and not zero,
26351 * 0b0100 if vB greter then 0, i.e. vB is pos and not zero,
26352 * 0b1000 if vB equals 0,
26353 * 0b0001 if vB is invalid over rules lt, gt, eq
26360 mkNOT1( zero
) ) ),
26366 mkNOT1( zero
) ) ),
26369 unop( Iop_1Uto32
, zero
),
26372 IRTemp valid_mask
= newTemp( Ity_I32
);
26374 assign( valid_mask
, unop( Iop_1Sto32
, unop( Iop_32to1
, valid
) ) );
26376 putGST_field( PPC_GST_CR
,
26379 mkexpr( valid_mask
),
26380 mkexpr( eq_lt_gt
) ),
26382 unop( Iop_Not32
, mkexpr( valid_mask
) ),
26388 static Bool
dis_av_bcd ( UInt theInstr
, const VexAbiInfo
* vbi
)
26391 UChar opc1
= ifieldOPC(theInstr
);
26392 UChar vRT_addr
= ifieldRegDS(theInstr
);
26393 UChar vRA_addr
= ifieldRegA(theInstr
);
26394 UChar vRB_addr
= ifieldRegB(theInstr
);
26395 UChar ps
= IFIELD( theInstr
, 9, 1 );
26396 UInt opc2
= IFIELD( theInstr
, 0, 9 );
26397 IRTemp vA
= newTemp(Ity_V128
);
26398 IRTemp vB
= newTemp(Ity_V128
);
26399 IRTemp dst
= newTemp(Ity_V128
);
26400 IRExpr
*pos
, *neg
, *valid
, *zero
, *sign_digit
, *in_range
;
26401 IRTemp eq_lt_gt
= newTemp( Ity_I32
);
26402 IRExpr
*overflow
, *value
;
26404 assign( vA
, getVReg(vRA_addr
));
26405 assign( vB
, getVReg(vRB_addr
));
26408 vex_printf("dis_av_bcd(ppc)(instr)\n");
26413 case 0x1: // bcdadd.
26414 case 0x41: // bcdsub.
26416 /* NOTE 64 bit compares are not supported in 32-bit mode. Use
26417 * 32-bit compares only.
26420 IRExpr
*sign
, *res_smaller
;
26421 IRExpr
*signA
, *signB
, *sign_digitA
, *sign_digitB
;
26422 IRExpr
*zeroA
, *zeroB
, *posA
, *posB
, *negA
, *negB
;
26424 if ( opc2
== 0x1 ) {
26425 DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr
, vRA_addr
, vRB_addr
, ps
);
26426 assign( dst
, bcd_sign_code_adjust( ps
,
26429 mkexpr( vB
) ) ) );
26431 DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr
, vRA_addr
, vRB_addr
, ps
);
26432 assign( dst
, bcd_sign_code_adjust( ps
,
26435 mkexpr( vB
) ) ) );
26438 putVReg( vRT_addr
, mkexpr( dst
) );
26439 /* set CR field 6 */
26441 zero
= BCDstring_zero( binop( Iop_AndV128
,
26442 binop( Iop_64HLtoV128
,
26443 mkU64( 0xFFFFFFFFFFFFFFFF ),
26444 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26445 mkexpr(dst
) ) ); // ignore sign
26447 sign_digit
= binop( Iop_And32
, mkU32( 0xF ),
26449 unop( Iop_V128to64
, mkexpr( dst
) ) ) );
26451 sign
= mkOR1( binop( Iop_CmpEQ32
,
26454 binop( Iop_CmpEQ32
,
26457 neg
= mkAND1( sign
, mkNOT1( zero
) );
26459 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
26460 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
26461 valid
= unop( Iop_64to32
,
26463 is_BCDstring128( vbi
,
26464 /*Signed*/True
, mkexpr( vA
) ),
26465 is_BCDstring128( vbi
,
26466 /*Signed*/True
, mkexpr( vB
) )
26470 zeroA
= BCDstring_zero( binop( Iop_AndV128
,
26471 binop( Iop_64HLtoV128
,
26472 mkU64( 0xFFFFFFFFFFFFFFFF ),
26473 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26474 mkexpr( vA
) ) ); // ignore sign
26475 sign_digitA
= binop( Iop_And32
, mkU32( 0xF ),
26477 unop( Iop_V128to64
, mkexpr( vA
) ) ) );
26479 signA
= mkOR1( binop( Iop_CmpEQ32
,
26482 binop( Iop_CmpEQ32
,
26485 negA
= mkAND1( signA
, mkNOT1( zeroA
) );
26486 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
26487 posA
= mkAND1( mkNOT1( signA
), mkNOT1( zeroA
) );
26490 zeroB
= BCDstring_zero( binop( Iop_AndV128
,
26491 binop( Iop_64HLtoV128
,
26492 mkU64( 0xFFFFFFFFFFFFFFFF ),
26493 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26494 mkexpr( vB
) ) ); // ignore sign
26495 sign_digitB
= binop( Iop_And32
, mkU32( 0xF ),
26497 unop( Iop_V128to64
, mkexpr( vB
) ) ) );
26499 signB
= mkOR1( binop( Iop_CmpEQ32
,
26502 binop( Iop_CmpEQ32
,
26505 negB
= mkAND1( signB
, mkNOT1( zeroB
) );
26508 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
26509 posB
= mkAND1( mkNOT1( signB
), mkNOT1( zeroB
) );
26513 res_smaller
= mkAND1( CmpGT128U( mkexpr( vA
), mkexpr( dst
) ),
26514 CmpGT128U( mkexpr( vB
), mkexpr( dst
) ) );
26517 /* Have to do this with 32-bit compares, expensive */
26518 res_smaller
= mkAND1( UNSIGNED_CMP_GT_V128( mkexpr( vA
),
26520 UNSIGNED_CMP_GT_V128( mkexpr( vB
),
26524 if ( opc2
== 0x1) {
26525 /* Overflow for Add can only occur if the signs of the operands
26526 * are the same and the two operands are non-zero. On overflow,
26527 * the PPC hardware produces a result consisting of just the lower
26528 * digits of the result. So, if the result is less then both
26529 * operands and the sign of the operands are the same overflow
26532 overflow
= mkOR1( mkAND1( res_smaller
, mkAND1( negA
, negB
) ),
26533 mkAND1( res_smaller
, mkAND1( posA
, posB
) ) );
26535 /* Overflow for Add can only occur if the signs of the operands
26536 * are the different and the two operands are non-zero. On overflow,
26537 * the PPC hardware produces a result consisting of just the lower
26538 * digits of the result. So, if the result is less then both
26539 * operands and the sign of the operands are different overflow
26542 overflow
= mkOR1( mkAND1( res_smaller
, mkAND1( negA
, posB
) ),
26543 mkAND1( res_smaller
, mkAND1( posA
, negB
) ) );
26548 case 0x081: // bcdus. Decimal Unsigned Shift VX-form
26549 case 0x0C1: // bcds. Decimal Shift VX-form
26550 case 0x1C1: // bcdsr. Decimal Shift and Round VX-form
26553 IRExpr
*shift_mask
, *result
, *new_sign_val
, *sign
;
26554 IRExpr
*not_excess_shift
, *not_excess_shift_mask
;
26555 IRTemp shift_dir_mask
= newTemp( Ity_I64
);
26556 IRTemp shift_by
= newTemp( Ity_I64
);
26557 IRTemp shift_field
= newTemp( Ity_I64
);
26558 IRTemp shifted_out
= newTemp( Ity_V128
);
26559 IRTemp value_shl
= newTemp( Ity_V128
);
26560 IRTemp value_shr
= newTemp( Ity_V128
);
26561 IRTemp round
= newTemp( Ity_I32
);
26563 ULong value_mask_low
= 0;
26564 UInt max_shift
= 0;
26566 if (opc2
== 0x0C1) {
26567 DIP("bcds. v%d,v%d,v%d,%d\n", vRT_addr
, vRA_addr
, vRB_addr
, ps
);
26568 value_mask_low
= 0xFFFFFFFFFFFFFFF0;
26569 max_shift
= 30 * 4; /* maximum without shifting all digits out */
26571 } else if (opc2
== 0x1C1) {
26572 DIP("bcdsr. v%d,v%d,v%d,%d\n", vRT_addr
, vRA_addr
, vRB_addr
, ps
);
26574 value_mask_low
= 0xFFFFFFFFFFFFFFF0;
26575 max_shift
= 30 * 4; /* maximum without shifting all digits out */
26578 DIP("bcdus. v%d,v%d,v%d,%d\n", vRT_addr
, vRA_addr
,
26580 value_mask_low
= 0xFFFFFFFFFFFFFFFF;
26581 max_shift
= 31 * 4; /* maximum without shifting all digits out */
26584 value
= binop( Iop_AndV128
,
26585 binop( Iop_64HLtoV128
,
26586 mkU64( 0xFFFFFFFFFFFFFFFF ),
26587 mkU64( value_mask_low
) ),
26590 zero
= BCDstring_zero( value
);
26592 /* Shift field is 2's complement value */
26593 assign( shift_field
, unop( Iop_V128to64
,
26594 binop( Iop_ShrV128
,
26595 binop( Iop_AndV128
,
26596 binop( Iop_64HLtoV128
,
26602 /* if shift_dir = 0 shift left, otherwise shift right */
26603 shift_dir
= binop( Iop_CmpEQ64
,
26605 mkexpr( shift_field
),
26609 assign( shift_dir_mask
, unop( Iop_1Sto64
, shift_dir
) );
26611 /* Shift field is stored in 2's complement form */
26617 mkexpr( shift_dir_mask
) ),
26618 mkexpr( shift_field
) ),
26620 mkexpr( shift_dir_mask
),
26625 mkexpr( shift_field
) ) ),
26626 mkU64( 0xFF ) ) ) ),
26629 /* If the shift exceeds 128 bits, we need to force the result
26630 * to zero because Valgrind shift amount is only 7-bits. Otherwise,
26631 * we get a shift amount of mod(shift_by, 127)
26633 not_excess_shift
= unop( Iop_1Sto64
,
26634 binop( Iop_CmpLE64U
,
26635 mkexpr( shift_by
),
26636 mkU64( max_shift
) ) );
26638 not_excess_shift_mask
= binop( Iop_64HLtoV128
,
26640 not_excess_shift
);
26643 binop( Iop_ShlV128
, value
, unop( Iop_64to8
,
26644 mkexpr( shift_by
) ) ) );
26646 binop( Iop_AndV128
,
26647 binop( Iop_64HLtoV128
,
26648 mkU64( 0xFFFFFFFFFFFFFFFF ),
26649 mkU64( value_mask_low
) ),
26650 binop( Iop_ShrV128
,
26653 mkexpr( shift_by
) ) ) ) );
26655 /* Overflow occurs if the shift amount is greater than zero, the
26656 * operation is a left shift and any non-zero digits are left
26659 assign( shifted_out
,
26661 binop( Iop_ShrV128
,
26666 mkexpr( shift_by
) ) ) ),
26667 binop( Iop_AndV128
,
26669 not_excess_shift_mask
),
26672 overflow
= mkAND1( mkNOT1( BCDstring_zero( mkexpr( shifted_out
) ) ),
26673 mkAND1( mkNOT1( shift_dir
),
26674 binop( Iop_CmpNE64
,
26675 mkexpr( shift_by
),
26678 if ((opc2
== 0xC1) || (opc2
== 0x1C1)) {
26679 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26680 * codes 0xB and 0xD are negative.
26682 sign_digit
= binop( Iop_And64
, mkU64( 0xF ),
26683 unop( Iop_V128to64
, mkexpr( vB
) ) );
26685 sign
= mkOR1( binop( Iop_CmpEQ64
,
26688 binop( Iop_CmpEQ64
,
26691 neg
= mkAND1( sign
, mkNOT1( zero
) );
26693 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
26694 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
26698 is_BCDstring128( vbi
, /* Signed */True
, mkexpr( vB
) ) );
26701 /* string is an unsigned BCD value */
26708 is_BCDstring128( vbi
, /* Unsigned */False
,
26713 vB positive, sign is C
26714 vB negative, sign is D
26716 vB positive, sign is F
26717 vB negative, sign is D
26718 Note can't use pos or neg here since they are ANDed with zero,
26722 new_sign_val
= binop( Iop_Or64
,
26723 unop( Iop_1Uto64
, sign
),
26727 new_sign_val
= binop( Iop_Xor64
,
26729 unop( Iop_1Uto64
, sign
),
26734 shift_mask
= binop( Iop_64HLtoV128
,
26735 unop( Iop_1Sto64
, shift_dir
),
26736 unop( Iop_1Sto64
, shift_dir
) );
26738 result
= binop( Iop_OrV128
,
26739 binop( Iop_AndV128
, mkexpr( value_shr
), shift_mask
),
26740 binop( Iop_AndV128
,
26741 mkexpr( value_shl
),
26742 unop( Iop_NotV128
, shift_mask
) ) );
26744 if (opc2
== 0xC1) { // bcds.
26745 putVReg( vRT_addr
, binop( Iop_OrV128
,
26746 binop( Iop_64HLtoV128
,
26749 binop( Iop_AndV128
,
26750 not_excess_shift_mask
,
26752 } else if (opc2
== 0x1C1) { //bcdsr.
26753 /* If shifting right, need to round up if needed */
26754 assign( round
, unop( Iop_1Uto32
,
26756 check_BCD_round( value
,
26761 binop( Iop_64HLtoV128
,
26764 binop( Iop_AndV128
,
26765 not_excess_shift_mask
,
26766 mkexpr( increment_BCDstring( vbi
, result
,
26770 putVReg( vRT_addr
, binop( Iop_AndV128
,
26771 not_excess_shift_mask
,
26777 case 0x101: // bcdtrunc. Decimal Truncate VX-form
26778 case 0x141: // bcdutrunc. Decimal Unsigned Truncate VX-form
26780 IRTemp length
= newTemp( Ity_I64
);
26781 IRTemp masked_out
= newTemp( Ity_V128
);
26782 IRExpr
*new_sign_val
, *result
, *shift
;
26783 IRExpr
*length_neq_128
, *sign
;
26784 ULong value_mask_low
;
26787 if ( opc2
== 0x101) { // bcdtrunc.
26788 value_mask_low
= 0xFFFFFFFFFFFFFFF0;
26791 value_mask_low
= 0xFFFFFFFFFFFFFFFF;
26795 assign( length
, binop( Iop_And64
,
26796 unop( Iop_V128HIto64
,
26798 mkU64( 0xFFFF ) ) );
26799 shift
= unop( Iop_64to8
,
26802 mkU64( max_digits
),
26803 mkexpr( length
) ),
26806 /* Note ShrV128 gets masked by 127 so a shift of 128 results in
26807 * the value not being shifted. A shift of 128 sets the register
26808 * zero. So if length+1 = 128, just set the value to 0.
26810 length_neq_128
= mkNOT1( binop( Iop_CmpEQ64
,
26814 assign( masked_out
,
26815 binop( Iop_AndV128
,
26816 binop( Iop_64HLtoV128
,
26817 unop( Iop_1Sto64
, length_neq_128
),
26818 unop( Iop_1Sto64
, length_neq_128
) ),
26819 binop( Iop_ShrV128
,
26826 mkexpr( length
) ) ) ) )
26829 /* Overflow occurs if any of the left most 31-length digits of vB
26832 overflow
= mkNOT1( BCDstring_zero( mkexpr( masked_out
) ) );
26834 value
= binop( Iop_AndV128
,
26835 binop( Iop_64HLtoV128
,
26836 mkU64( 0xFFFFFFFFFFFFFFFF ),
26837 mkU64( value_mask_low
) ),
26841 if ( opc2
== 0x101 ) { // bcdtrunc.
26842 /* Check if all of the non-sign digits are zero */
26843 zero
= BCDstring_zero( binop( Iop_AndV128
,
26844 binop( Iop_64HLtoV128
,
26845 mkU64( 0xFFFFFFFFFFFFFFFF ),
26846 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26849 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26850 * codes 0xB and 0xD are negative.
26852 sign_digit
= binop( Iop_And64
, mkU64( 0xF ),
26853 unop( Iop_V128to64
, mkexpr( vB
) ) );
26855 sign
= mkOR1( binop( Iop_CmpEQ64
,
26858 binop( Iop_CmpEQ64
,
26861 neg
= mkAND1( sign
, mkNOT1( zero
) );
26863 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
26864 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
26866 /* Note can't use pos or neg here since they are ANDed with zero,
26870 new_sign_val
= binop( Iop_Or64
,
26871 unop( Iop_1Uto64
, sign
),
26874 new_sign_val
= binop( Iop_Xor64
,
26876 unop( Iop_1Uto64
, sign
),
26882 is_BCDstring128( vbi
, /* Signed */True
, mkexpr( vB
) ) );
26884 } else { // bcdutrunc.
26885 /* Check if all of the digits are zero */
26886 zero
= BCDstring_zero( value
);
26888 /* unsigned value, need to make CC code happy */
26891 /* Pos position AKA gt = 1 if (not eq zero) */
26892 pos
= mkNOT1( zero
);
26895 is_BCDstring128( vbi
, /* Unsigned */False
,
26899 /* If vB is not valid, the result is undefined, but we need to
26900 * match the hardware so the output of the test suite will match.
26901 * Hardware sets result to 0x0.
26903 result
= binop( Iop_AndV128
,
26905 binop( Iop_ShrV128
,
26906 binop( Iop_ShlV128
, value
, shift
),
26909 if ( opc2
== 0x101) { // bcdtrunc.
26910 putVReg( vRT_addr
, binop( Iop_OrV128
,
26911 binop( Iop_64HLtoV128
,
26916 putVReg( vRT_addr
, result
);
26921 case 0x181: // bcdctz., bcdctn., bcdcfz., bcdcfn., bcdsetsgn.,
26922 // bcdcfsq., bcdctsq.
26924 UInt inst_select
= IFIELD( theInstr
, 16, 5);
26926 switch (inst_select
) {
26927 case 0: // bcdctsq. (Decimal Convert to Signed Quadword VX-form)
26931 /* The instruction takes a 32-bit integer in a vector source
26932 * register and returns the signed packed decimal number
26933 * in a vector register. The source integer needs to be moved
26934 * from the V128 to an I32 for the Iop.
26937 DIP("bcdctsq v%d, v%d\n", vRT_addr
, vRB_addr
);
26939 putVReg( vRT_addr
, unop( Iop_BCD128toI128S
, mkexpr( vB
) ) );
26941 sign
= binop( Iop_And64
,
26942 unop( Iop_V128to64
, mkexpr( vB
) ),
26944 zero
= mkAND1( binop( Iop_CmpEQ64
,
26945 unop( Iop_V128HIto64
, mkexpr( vB
) ),
26947 binop( Iop_CmpEQ64
,
26949 unop( Iop_V128to64
, mkexpr( vB
) ),
26950 mkU64( 0xFFFFFFF0 ) ),
26952 pos
= mkAND1( mkNOT1( zero
),
26953 mkOR1( mkOR1( binop( Iop_CmpEQ64
,
26954 sign
, mkU64( 0xA ) ),
26955 binop( Iop_CmpEQ64
,
26956 sign
, mkU64( 0xC ) ) ),
26957 mkOR1( binop( Iop_CmpEQ64
,
26958 sign
, mkU64( 0xE ) ),
26959 binop( Iop_CmpEQ64
,
26960 sign
, mkU64( 0xF ) ) ) ) );
26961 neg
= mkAND1( mkNOT1( zero
),
26962 mkOR1( binop( Iop_CmpEQ64
, sign
, mkU64( 0xB ) ),
26963 binop( Iop_CmpEQ64
, sign
, mkU64( 0xD ) ) ) );
26965 /* Check each of the nibbles for a valid digit 0 to 9 */
26968 is_BCDstring128( vbi
, /* Signed */True
,
26970 overflow
= mkU1( 0 ); // not used
26974 case 2: // bcdcfsq. (Decimal Convert from Signed Quadword VX-form)
26976 IRExpr
*pos_upper_gt
, *pos_upper_eq
, *pos_lower_gt
;
26977 IRExpr
*neg_upper_lt
, *neg_upper_eq
, *neg_lower_lt
;
26979 DIP("bcdcfsq v%d, v%d, %d\n", vRT_addr
, vRB_addr
, ps
);
26981 /* The instruction takes a signed packed decimal number and
26982 * returns the integer value in the vector register. The Iop
26983 * returns an I32 which needs to be moved to the destination
26987 binop( Iop_I128StoBCD128
, mkexpr( vB
), mkU8( ps
) ) );
26989 zero
= mkAND1( binop( Iop_CmpEQ64
, mkU64( 0 ),
26990 unop( Iop_V128to64
, mkexpr( vB
) ) ),
26991 binop( Iop_CmpEQ64
, mkU64( 0 ),
26992 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
26993 pos
= mkAND1( mkNOT1 ( zero
),
26994 binop( Iop_CmpEQ64
, mkU64( 0 ),
26996 unop( Iop_V128HIto64
,
26998 mkU64( 0x8000000000000000UL
) ) ) );
26999 neg
= mkAND1( mkNOT1 ( zero
),
27000 binop( Iop_CmpEQ64
, mkU64( 0x8000000000000000UL
),
27002 unop( Iop_V128HIto64
,
27004 mkU64( 0x8000000000000000UL
) ) ) );
27006 /* Overflow occurs if: vB > 10^31-1 OR vB < -10^31-1
27007 * do not have a 128 bit compare. Will have to compare the
27008 * upper 64 bit and athe lower 64 bits. If the upper 64-bits
27009 * are equal then overflow if the lower 64 bits of vB is greater
27010 * otherwise if the upper bits of vB is greater then the max
27011 * for the upper 64-bits then overflow
27013 * 10^31-1 = 0x7E37BE2022C0914B267FFFFFFF
27015 pos_upper_gt
= binop( Iop_CmpLT64U
,
27016 mkU64( 0x7E37BE2022 ),
27017 unop( Iop_V128HIto64
, mkexpr( vB
) ) );
27018 pos_upper_eq
= binop( Iop_CmpEQ64
,
27019 unop( Iop_V128HIto64
, mkexpr( vB
) ),
27020 mkU64( 0x7E37BE2022 ) );
27021 pos_lower_gt
= binop( Iop_CmpLT64U
,
27022 mkU64( 0x0914B267FFFFFFF ),
27023 unop( Iop_V128to64
, mkexpr( vB
) ) );
27024 /* -10^31-1 = 0X81C841DFDD3F6EB4D97FFFFFFF */
27025 neg_upper_lt
= binop( Iop_CmpLT64U
,
27026 mkU64( 0X81C841DFDD ),
27027 unop( Iop_V128HIto64
, mkexpr( vB
) ) );
27028 neg_upper_eq
= binop( Iop_CmpEQ64
,
27029 unop( Iop_V128HIto64
, mkexpr( vB
) ),
27030 mkU64( 0X81C841DFDD ) );
27031 neg_lower_lt
= binop( Iop_CmpLT64U
,
27032 mkU64( 0x3F6EB4D97FFFFFFF ),
27033 unop( Iop_V128to64
, mkexpr( vB
) ) );
27035 /* calculate overflow, masking for positive and negative */
27036 overflow
= mkOR1( mkAND1( pos
,
27037 mkOR1( pos_upper_gt
,
27038 mkAND1( pos_upper_eq
,
27039 pos_lower_gt
) ) ),
27041 mkOR1( neg_upper_lt
,
27042 mkAND1( neg_upper_eq
,
27045 valid
= mkU32( 1 );
27049 case 4: // bcdctz. (Decimal Convert to Zoned VX-form)
27051 IRExpr
*ox_flag
, *sign
, *vrb_nibble30
;
27053 unsigned int upper_byte
, sign_byte
;
27054 IRTemp tmp
= newTemp( Ity_V128
);
27056 DIP("bcdctz. v%d,v%d,%d\n", vRT_addr
, vRB_addr
, ps
);
27061 neg_bit_shift
= 4+2; /* sign byte is in bits [7:4] */
27065 neg_bit_shift
= 4+0;
27068 /* Grab vB bits[7:4]. It goes into bits [3:0] of the
27071 vrb_nibble30
= binop( Iop_Shr64
,
27073 unop( Iop_V128to64
, mkexpr( vB
) ),
27077 /* Upper 24 hex digits of VB, i.e. hex digits vB[0:23],
27078 * must be zero for the value to be zero. This goes
27079 * in the overflow position of the condition code register.
27081 ox_flag
= binop( Iop_CmpEQ64
,
27083 unop( Iop_V128to64
, mkexpr( vB
) ),
27084 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
27087 /* zero is the same as eq_flag */
27088 zero
= mkAND1( binop( Iop_CmpEQ64
,
27090 unop( Iop_V128HIto64
, mkexpr( vB
) ),
27091 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
27093 binop( Iop_CmpEQ64
,
27095 unop( Iop_V128to64
, mkexpr( vB
) ),
27096 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
27099 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
27100 * codes 0xB and 0xD are negative.
27102 sign_digit
= binop( Iop_And64
, mkU64( 0xF ),
27103 unop( Iop_V128to64
, mkexpr( vB
) ) );
27105 /* The negative value goes in the LT bit position of the
27106 * condition code register. Set neg if the sign of vB
27107 * is negative and zero is true.
27109 sign
= mkOR1( binop( Iop_CmpEQ64
,
27112 binop( Iop_CmpEQ64
,
27115 neg
= mkAND1( sign
, mkNOT1( zero
) );
27117 /* The positive value goes in the LT bit position of the
27118 * condition code register. Set positive if the sign of the
27119 * value is not negative.
27121 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
27124 convert_to_zoned( vbi
, mkexpr( vB
),
27125 mkU64( upper_byte
) ) );
27127 /* Insert the sign based on ps and sign of vB
27128 * in the lower byte.
27132 binop( Iop_64HLtoV128
,
27137 binop( Iop_64HLtoV128
,
27140 mkU64( sign_byte
),
27144 mkU8( neg_bit_shift
)
27147 /* A valid number must have a value that is less then or
27148 * equal to 10^16 - 1. This is checked by making sure
27149 * bytes [31:16] of vB are zero.
27151 in_range
= binop( Iop_CmpEQ64
,
27153 mkU64( 0xFFFFFFFFFFFFFFF0 ),
27154 unop( Iop_V128HIto64
, mkexpr( vB
) ) ),
27157 /* overflow is set if ox_flag or not in_inrange. Setting is
27158 * ORed with the other condition code values.
27160 overflow
= mkOR1( ox_flag
, mkNOT1( in_range
) );
27162 /* The sign code must be between 0xA and 0xF and all digits are
27163 * between 0x0 and 0x9. The vB must be in range to be valid.
27164 * If not valid, condition code set to 0x0001.
27168 is_BCDstring128( vbi
, /* Signed */True
,
27173 case 5: // bcdctn. (Decimal Convert to National VX-form)
27175 IRExpr
*ox_flag
, *sign
;
27176 IRTemp tmp
= newTemp( Ity_V128
);;
27178 DIP("bcdctn. v%d,v%d\n", vRT_addr
, vRB_addr
);
27180 value
= binop( Iop_And64
,
27181 mkU64( 0xFFFFFFFF ),
27182 unop( Iop_V128to64
, mkexpr( vB
) ) );
27184 /* A valid number must have a value that is less then or
27185 * equal to 10^7 - 1. This is checked by making sure
27186 * bytes [31:8] of vB are zero.
27188 in_range
= mkAND1( binop( Iop_CmpEQ64
,
27189 unop( Iop_V128HIto64
, mkexpr( vB
) ),
27191 binop( Iop_CmpEQ64
,
27193 unop( Iop_V128to64
,
27198 /* The sign code must be between 0xA and 0xF and all digits are
27199 * between 0x0 and 0x9.
27203 is_BCDstring128( vbi
, /* Signed */True
,
27206 /* Upper 24 hex digits of VB, i.e. hex ditgits vB[0:23],
27207 * must be zero for the ox_flag to be zero. This goes
27208 * in the LSB position (variable overflow) of the
27209 * condition code register.
27212 mkNOT1( mkAND1( binop( Iop_CmpEQ64
,
27214 unop( Iop_V128HIto64
,
27216 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
27218 binop( Iop_CmpEQ64
,
27220 unop( Iop_V128to64
,
27222 mkU64( 0xFFFFFFFF00000000 ) ),
27225 /* Set zero to 1 if all of the bytes in vB are zero. This is
27226 * used when setting the lt_flag (variable neg) and the gt_flag
27229 zero
= mkAND1( binop( Iop_CmpEQ64
,
27231 unop( Iop_V128HIto64
,
27233 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
27235 binop( Iop_CmpEQ64
,
27237 unop( Iop_V128to64
, mkexpr( vB
) ),
27238 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
27241 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
27242 * codes 0xB and 0xD are negative.
27244 sign_digit
= binop( Iop_And64
, mkU64( 0xF ), value
);
27246 /* The negative value goes in the LT bit position of the
27247 * condition code register. Set neg if the sign of the
27248 * value is negative and the value is zero.
27250 sign
= mkOR1( binop( Iop_CmpEQ64
,
27253 binop( Iop_CmpEQ64
,
27256 neg
= mkAND1( sign
, mkNOT1( zero
) );
27258 /* The positive value goes in the LT bit position of the
27259 * condition code register. Set neg if the sign of the
27260 * value is not negative and the value is zero.
27262 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
27265 convert_to_national( vbi
, mkexpr( vB
) ) );
27267 /* If vB is positive insert sign value 0x002B, otherwise
27268 * insert 0x002D for negative. Have to use sign not neg
27269 * because neg has been ANDed with zero. This is 0x29
27270 * OR'd with (sign << 1 | NOT sign) << 1.
27271 * sign = 1 if vB is negative.
27276 binop( Iop_64HLtoV128
,
27292 /* The sign code must be between 0xA and 0xF and all digits are
27293 * between 0x0 and 0x9. The vB must be in range to be valid.
27297 is_BCDstring128( vbi
, /* Signed */True
,
27300 overflow
= ox_flag
;
27304 case 6: // bcdcfz. (Decimal Convert From Zoned VX-form)
27307 IRTemp tmp
= newTemp( Ity_V128
);;
27309 DIP("bcdcfz. v%d,v%d,%d\n", vRT_addr
, vRB_addr
, ps
);
27311 valid
= unop( Iop_1Uto32
, is_Zoned_decimal( vB
, ps
) );
27314 convert_from_zoned( vbi
, mkexpr( vB
) ) );
27316 /* If the result of checking the lower 4 bits of each 8-bit
27317 * value is zero, then the "number" was zero.
27320 binop( Iop_CmpEQ64
,
27323 unop( Iop_V128to64
, mkexpr( vB
) ),
27324 mkU64( 0x0F0F0F0F0F0F0F0FULL
) ),
27326 unop( Iop_V128to64
, mkexpr( vB
) ),
27327 mkU64( 0x0F0F0F0F0F0F0F0FULL
) ) ),
27330 /* Sign bit is in bit 6 of vB. */
27331 sign_digit
= binop( Iop_And64
, mkU64( 0xF0 ),
27332 unop( Iop_V128to64
, mkexpr( vB
) ) );
27335 /* sign will be equal to 0 for positive number */
27336 sign
= binop( Iop_CmpEQ64
,
27343 binop( Iop_CmpEQ64
, sign_digit
, mkU64( 0xB0 ) ),
27344 binop( Iop_CmpEQ64
, sign_digit
, mkU64( 0xD0 ) ) );
27347 /* The negative value goes in the LT bit position of the
27348 * condition code register. Set neg if the sign of the
27349 * value is negative and the value is zero.
27351 neg
= mkAND1( sign
, mkNOT1( zero
) );
27353 /* The positive value goes in the GT bit position of the
27354 * condition code register. Set neg if the sign of the
27355 * value is not negative and the value is zero.
27357 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
27359 /* sign of the result is 0xC for positive, 0xD for negative */
27363 binop( Iop_64HLtoV128
,
27367 unop( Iop_1Uto64
, sign
)
27369 /* For this instructions the LSB position in the CC
27370 * field, the overflow position in the other instructions,
27371 * is given by 0. There is nothing to or with LT, EQ or GT.
27373 overflow
= mkU1( 0 );
27377 case 7: // bcdcfn. (Decimal Convert From National VX-form)
27379 IRTemp hword_7
= newTemp( Ity_I64
);
27381 IRTemp tmp
= newTemp( Ity_I64
);;
27383 DIP("bcdcfn. v%d,v%d,%d\n", vRT_addr
, vRB_addr
, ps
);
27385 /* check that the value is valid */
27386 valid
= unop( Iop_1Uto32
, is_National_decimal( vB
) );
27388 assign( hword_7
, binop( Iop_And64
,
27389 unop( Iop_V128to64
, mkexpr( vB
) ),
27390 mkU64( 0xFFF ) ) );
27391 /* sign = 1 if vB is negative */
27392 sign
= binop( Iop_CmpEQ64
, mkexpr( hword_7
), mkU64( 0x002D ) );
27394 assign( tmp
, convert_from_national( vbi
, mkexpr( vB
) ) );
27396 /* If the result of checking the lower 4 bits of each 16-bit
27397 * value is zero, then the "number" was zero.
27400 binop( Iop_CmpEQ64
,
27403 unop( Iop_V128HIto64
, mkexpr( vB
) ),
27404 mkU64( 0x000F000F000F000FULL
) ),
27406 unop( Iop_V128to64
, mkexpr( vB
) ),
27407 mkU64( 0x000F000F000F0000ULL
) ) ),
27411 /* The negative value goes in the LT bit position of the
27412 * condition code register. Set neg if the sign of the
27413 * value is negative and the value is zero.
27415 neg
= mkAND1( sign
, mkNOT1( zero
) );
27417 /* The positive value goes in the GT bit position of the
27418 * condition code register. Set neg if the sign of the
27419 * value is not negative and the value is zero.
27421 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
27423 /* For this instructions the LSB position in the CC
27424 * field, the overflow position in the other instructions,
27425 * is given by invalid. There is nothing to OR with the valid
27428 overflow
= mkU1( 0 );
27430 /* sign of the result is:
27431 ( 0b1100 OR neg) OR (ps OR (ps AND pos) << 1 )
27435 binop( Iop_64HLtoV128
,
27449 unop( Iop_1Uto64
, sign
) ),
27450 mkexpr( tmp
) ) ) ) );
27455 case 31: // bcdsetsgn. (BCD set sign)
27457 IRExpr
*new_sign_val
, *sign
;
27459 DIP("bcdsetsgn. v%d,v%d,%d\n", vRT_addr
, vRB_addr
, ps
);
27461 value
= binop( Iop_AndV128
,
27462 binop( Iop_64HLtoV128
,
27463 mkU64( 0xFFFFFFFFFFFFFFFF ),
27464 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
27466 zero
= BCDstring_zero( value
);
27468 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
27469 * codes 0xB and 0xD are negative.
27471 sign_digit
= binop( Iop_And64
, mkU64( 0xF ),
27472 unop( Iop_V128to64
, mkexpr( vB
) ) );
27474 sign
= mkOR1( binop( Iop_CmpEQ64
,
27477 binop( Iop_CmpEQ64
,
27480 neg
= mkAND1( sign
, mkNOT1( zero
) );
27482 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
27486 is_BCDstring128( vbi
, /* Signed */True
,
27490 vB positive, sign is C
27491 vB negative, sign is D
27493 vB positive, sign is F
27494 vB negative, sign is D
27495 Note can't use pos or neg here since they are ANDed with
27496 zero, use sign instead.
27499 new_sign_val
= binop( Iop_Or64
,
27500 unop( Iop_1Uto64
, sign
),
27504 new_sign_val
= binop( Iop_Xor64
,
27506 unop( Iop_1Uto64
, sign
),
27511 putVReg( vRT_addr
, binop( Iop_OrV128
,
27512 binop( Iop_64HLtoV128
,
27516 /* For this instructions the LSB position in the CC
27517 * field, the overflow position in the other instructions,
27518 * is given by invalid.
27520 overflow
= unop( Iop_32to1
, unop( Iop_Not32
, valid
) );
27525 vex_printf("dis_av_bcd(ppc)(invalid inst_select)\n");
27532 vex_printf("dis_av_bcd(ppc)(opc2)\n");
27536 IRTemp valid_mask
= newTemp( Ity_I32
);
27538 assign( valid_mask
, unop( Iop_1Sto32
, unop( Iop_32to1
, valid
) ) );
27540 /* set CR field 6 to:
27541 * 0b1000 if vB less then 0, i.e. vB is neg and not zero,
27542 * 0b0100 if vB greter then 0, i.e. vB is pos and not zero,
27543 * 0b0010 if vB equals 0,
27544 * 0b0001 if vB is invalid over rules lt, gt, eq
27549 unop( Iop_1Uto32
, neg
),
27553 unop( Iop_1Uto32
, pos
),
27556 unop( Iop_1Uto32
, zero
),
27558 /* valid is 1 if it is a valid number, complement and put in the
27559 * invalid bit location, overriding ls, eq, gt, overflow.
27561 putGST_field( PPC_GST_CR
,
27564 mkexpr( valid_mask
),
27566 mkexpr( eq_lt_gt
),
27567 unop( Iop_1Uto32
, overflow
) ) ),
27569 unop( Iop_Not32
, mkexpr( valid_mask
) ),
27576 AltiVec Floating Point Arithmetic Instructions
27578 static Bool
dis_av_fp_arith ( UInt theInstr
)
27581 UChar opc1
= ifieldOPC(theInstr
);
27582 UChar vD_addr
= ifieldRegDS(theInstr
);
27583 UChar vA_addr
= ifieldRegA(theInstr
);
27584 UChar vB_addr
= ifieldRegB(theInstr
);
27585 UChar vC_addr
= ifieldRegC(theInstr
);
27588 IRTemp vA
= newTemp(Ity_V128
);
27589 IRTemp vB
= newTemp(Ity_V128
);
27590 IRTemp vC
= newTemp(Ity_V128
);
27591 assign( vA
, getVReg(vA_addr
));
27592 assign( vB
, getVReg(vB_addr
));
27593 assign( vC
, getVReg(vC_addr
));
27596 vex_printf("dis_av_fp_arith(ppc)(instr)\n");
27600 IRTemp rm
= newTemp(Ity_I32
);
27601 assign(rm
, get_IR_roundingmode());
27603 opc2
= IFIELD( theInstr
, 0, 6 );
27605 case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
27606 DIP("vmaddfp v%d,v%d,v%d,v%d\n",
27607 vD_addr
, vA_addr
, vC_addr
, vB_addr
);
27610 triop( Iop_Add32Fx4
,
27611 mkU32( Irrm_NEAREST
),
27612 dnorm_adj_Vector( mkexpr( vB
) ),
27613 dnorm_adj_Vector( triop( Iop_Mul32Fx4
,
27614 mkU32( Irrm_NEAREST
),
27615 dnorm_adj_Vector( mkexpr( vA
) ),
27616 dnorm_adj_Vector( mkexpr( vC
) ) )
27620 case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
27621 DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
27622 vD_addr
, vA_addr
, vC_addr
, vB_addr
);
27624 negate_Vector( Ity_I32
,
27626 triop( Iop_Sub32Fx4
,
27627 mkU32( Irrm_NEAREST
),
27629 triop( Iop_Mul32Fx4
,
27630 mkU32( Irrm_NEAREST
),
27631 dnorm_adj_Vector( mkexpr( vA
) ),
27632 dnorm_adj_Vector( mkexpr( vC
) ) ) ),
27633 dnorm_adj_Vector( mkexpr( vB
) ) ) ) ) );
27638 break; // Fall through...
27641 opc2
= IFIELD( theInstr
, 0, 11 );
27643 case 0x00A: // vaddfp (Add FP, AV p137)
27644 DIP("vaddfp v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27646 dnorm_adj_Vector( triop( Iop_Add32Fx4
, mkU32( Irrm_NEAREST
),
27647 dnorm_adj_Vector( mkexpr( vA
) ),
27648 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
27651 case 0x04A: // vsubfp (Subtract FP, AV p261)
27652 DIP("vsubfp v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27654 dnorm_adj_Vector( triop( Iop_Sub32Fx4
, mkU32( Irrm_NEAREST
),
27655 dnorm_adj_Vector( mkexpr( vA
) ),
27656 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
27659 case 0x40A: // vmaxfp (Maximum FP, AV p178)
27660 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27662 dnorm_adj_Vector( binop( Iop_Max32Fx4
,
27663 mkexpr( vA
), mkexpr( vB
) ) ) );
27666 case 0x44A: // vminfp (Minimum FP, AV p187)
27667 DIP("vminfp v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27669 dnorm_adj_Vector( binop( Iop_Min32Fx4
,
27670 mkexpr( vA
), mkexpr( vB
) ) ) );
27674 break; // Fall through...
27678 if (vA_addr
!= 0) {
27679 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
27684 case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
27685 DIP("vrefp v%d,v%d\n", vD_addr
, vB_addr
);
27686 putVReg( vD_addr
, dnorm_adj_Vector( unop( Iop_RecipEst32Fx4
,
27687 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
27690 case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
27691 DIP("vrsqrtefp v%d,v%d\n", vD_addr
, vB_addr
);
27692 putVReg( vD_addr
, dnorm_adj_Vector( unop( Iop_RSqrtEst32Fx4
,
27693 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
27696 case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
27697 DIP("vexptefp v%d,v%d\n", vD_addr
, vB_addr
);
27698 /* NOTE, need to address dnormalized value handling when this is
27701 dnorm_adj_Vector( unop( Iop_Exp2_32Fx4
,
27702 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
27705 case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
27706 DIP("vlogefp v%d,v%d\n", vD_addr
, vB_addr
);
27707 /* NOTE, need to address dnormalized value handling when this is
27710 dnorm_adj_Vector( unop( Iop_Log2_32Fx4
,
27711 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
27715 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2
);
27722 AltiVec Floating Point Compare Instructions
27724 static Bool
dis_av_fp_cmp ( UInt theInstr
)
27727 UChar opc1
= ifieldOPC(theInstr
);
27728 UChar vD_addr
= ifieldRegDS(theInstr
);
27729 UChar vA_addr
= ifieldRegA(theInstr
);
27730 UChar vB_addr
= ifieldRegB(theInstr
);
27731 UChar flag_rC
= ifieldBIT10(theInstr
);
27732 UInt opc2
= IFIELD( theInstr
, 0, 10 );
27734 Bool cmp_bounds
= False
;
27736 IRTemp vA
= newTemp(Ity_V128
);
27737 IRTemp vB
= newTemp(Ity_V128
);
27738 IRTemp vD
= newTemp(Ity_V128
);
27739 assign( vA
, getVReg(vA_addr
));
27740 assign( vB
, getVReg(vB_addr
));
27743 vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
27748 case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
27749 DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
27750 vD_addr
, vA_addr
, vB_addr
);
27751 assign( vD
, binop( Iop_CmpEQ32Fx4
,
27752 dnorm_adj_Vector( mkexpr( vA
) ),
27753 dnorm_adj_Vector( mkexpr( vB
) ) ) );
27756 case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
27757 DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
27758 vD_addr
, vA_addr
, vB_addr
);
27759 assign( vD
, binop( Iop_CmpGE32Fx4
,
27760 dnorm_adj_Vector( mkexpr( vA
) ),
27761 dnorm_adj_Vector( mkexpr( vB
) ) ) );
27764 case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
27765 DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
27766 vD_addr
, vA_addr
, vB_addr
);
27767 assign( vD
, binop( Iop_CmpGT32Fx4
,
27768 dnorm_adj_Vector( mkexpr( vA
) ),
27769 dnorm_adj_Vector( mkexpr( vB
) ) ) );
27772 case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
27773 IRTemp gt
= newTemp(Ity_V128
);
27774 IRTemp lt
= newTemp(Ity_V128
);
27775 IRTemp zeros
= newTemp(Ity_V128
);
27776 IRTemp srcA
= newTemp(Ity_V128
);
27777 IRTemp srcB
= newTemp(Ity_V128
);
27779 DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
27780 vD_addr
, vA_addr
, vB_addr
);
27782 assign( zeros
, unop(Iop_Dup32x4
, mkU32(0)) );
27784 /* Note: making use of fact that the ppc backend for compare insns
27785 return zero'd lanes if either of the corresponding arg lanes is
27788 Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
27789 need this for the other compares too (vcmpeqfp etc)...
27790 Better still, tighten down the spec for compare irops.
27792 assign ( srcA
, dnorm_adj_Vector( mkexpr( vA
) ) );
27793 assign ( srcB
, dnorm_adj_Vector( mkexpr( vB
) ) );
27795 assign( gt
, unop( Iop_NotV128
,
27796 binop( Iop_CmpLE32Fx4
, mkexpr( srcA
),
27797 mkexpr( srcB
) ) ) );
27798 assign( lt
, unop( Iop_NotV128
,
27799 binop( Iop_CmpGE32Fx4
, mkexpr( srcA
),
27800 triop( Iop_Sub32Fx4
, mkU32( Irrm_NEAREST
),
27802 mkexpr( srcB
) ) ) ) );
27804 // finally, just shift gt,lt to correct position
27805 assign( vD
, binop(Iop_ShlN32x4
,
27807 binop(Iop_AndV128
, mkexpr(gt
),
27808 unop(Iop_Dup32x4
, mkU32(0x2))),
27809 binop(Iop_AndV128
, mkexpr(lt
),
27810 unop(Iop_Dup32x4
, mkU32(0x1)))),
27816 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
27820 putVReg( vD_addr
, mkexpr(vD
) );
27823 set_AV_CR6( mkexpr(vD
), !cmp_bounds
);
27829 AltiVec Floating Point Convert/Round Instructions
27831 static Bool
dis_av_fp_convert ( UInt theInstr
)
27834 UChar opc1
= ifieldOPC(theInstr
);
27835 UChar vD_addr
= ifieldRegDS(theInstr
);
27836 UChar UIMM_5
= ifieldRegA(theInstr
);
27837 UChar vB_addr
= ifieldRegB(theInstr
);
27838 UInt opc2
= IFIELD( theInstr
, 0, 11 );
27840 IRTemp vB
= newTemp(Ity_V128
);
27841 IRTemp vScale
= newTemp(Ity_V128
);
27842 IRTemp vInvScale
= newTemp(Ity_V128
);
27844 float scale
, inv_scale
;
27846 assign( vB
, getVReg(vB_addr
));
27848 /* scale = 2^UIMM, cast to float, reinterpreted as uint */
27849 scale
= (float)( (unsigned int) 1<<UIMM_5
);
27850 assign( vScale
, unop(Iop_Dup32x4
, mkU32( float_to_bits(scale
) )) );
27851 inv_scale
= 1/scale
;
27853 unop(Iop_Dup32x4
, mkU32( float_to_bits(inv_scale
) )) );
27856 vex_printf("dis_av_fp_convert(ppc)(instr)\n");
27861 case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
27862 DIP("vcfux v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
27863 putVReg( vD_addr
, triop(Iop_Mul32Fx4
, mkU32(Irrm_NEAREST
),
27864 unop(Iop_I32UtoF32x4_DEP
, mkexpr(vB
)),
27865 mkexpr(vInvScale
)) );
27868 case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
27869 DIP("vcfsx v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
27871 putVReg( vD_addr
, triop(Iop_Mul32Fx4
, mkU32(Irrm_NEAREST
),
27872 unop(Iop_I32StoF32x4_DEP
, mkexpr(vB
)),
27873 mkexpr(vInvScale
)) );
27876 case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
27877 DIP("vctuxs v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
27879 unop(Iop_QF32toI32Ux4_RZ
,
27880 triop(Iop_Mul32Fx4
, mkU32(Irrm_NEAREST
),
27881 mkexpr(vB
), mkexpr(vScale
))) );
27884 case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
27885 DIP("vctsxs v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
27887 unop(Iop_QF32toI32Sx4_RZ
,
27888 triop(Iop_Mul32Fx4
, mkU32(Irrm_NEAREST
),
27889 mkexpr(vB
), mkexpr(vScale
))) );
27893 break; // Fall through...
27897 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
27902 case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
27903 DIP("vrfin v%d,v%d\n", vD_addr
, vB_addr
);
27904 putVReg( vD_addr
, unop(Iop_RoundF32x4_RN
,
27905 dnorm_adj_Vector( mkexpr( vB
) ) ) );
27908 case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
27909 DIP("vrfiz v%d,v%d\n", vD_addr
, vB_addr
);
27910 putVReg( vD_addr
, unop(Iop_RoundF32x4_RZ
,
27911 dnorm_adj_Vector( mkexpr( vB
) ) ) );
27914 case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
27915 DIP("vrfip v%d,v%d\n", vD_addr
, vB_addr
);
27916 putVReg( vD_addr
, unop(Iop_RoundF32x4_RP
,
27917 dnorm_adj_Vector( mkexpr( vB
) ) ) );
27920 case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
27921 DIP("vrfim v%d,v%d\n", vD_addr
, vB_addr
);
27922 putVReg( vD_addr
, unop(Iop_RoundF32x4_RM
,
27923 dnorm_adj_Vector( mkexpr(vB
) ) ) );
27927 vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
27933 static Bool
dis_transactional_memory ( UInt theInstr
, UInt nextInstr
,
27934 const VexAbiInfo
* vbi
,
27935 /*OUT*/DisResult
* dres
)
27937 UInt opc2
= IFIELD( theInstr
, 1, 10 );
27940 case 0x28E: { //tbegin.
27941 /* The current implementation is to just fail the tbegin and execute
27942 * the failure path. The failure path is assumed to be functionaly
27943 * equivalent to the transactional path with the needed data locking
27944 * to ensure correctness. The tend is just a noop and shouldn't
27945 * actually get executed.
27946 * 1) set cr0 to 0x2
27947 * 2) Initialize TFHAR to CIA+4
27948 * 3) Initialize TEXASR
27949 * 4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
27950 * 5) Continue executing at the next instruction.
27952 UInt R
= IFIELD( theInstr
, 21, 1 );
27955 UInt failure_code
= 0; /* Forcing failure, will not be due to tabort
27958 UInt persistant
= 1; /* set persistant since we are always failing
27961 UInt nest_overflow
= 1; /* Alowed nesting depth overflow, we use this
27962 as the reason for failing the trasaction */
27963 UInt tm_exact
= 1; /* have exact address for failure */
27965 DIP("tbegin. %u\n", R
);
27967 /* Set the CR0 field to indicate the tbegin failed. Then let
27968 * the code do the branch to the failure path.
27970 * 000 || 0 Transaction initiation successful,
27971 * unnested (Transaction state of
27972 * Non-transactional prior to tbegin.)
27973 * 010 || 0 Transaction initiation successful, nested
27974 * (Transaction state of Transactional
27975 * prior to tbegin.)
27976 * 001 || 0 Transaction initiation unsuccessful,
27977 * (Transaction state of Suspended prior
27980 putCR321( 0, mkU8( 0x2 ) );
27982 tm_reason
= generate_TMreason( failure_code
, persistant
,
27983 nest_overflow
, tm_exact
);
27985 storeTMfailure( guest_CIA_curr_instr
, tm_reason
,
27986 guest_CIA_curr_instr
+4 );
27993 case 0x2AE: { //tend.
27994 /* The tend. is just a noop. Do nothing */
27995 UInt A
= IFIELD( theInstr
, 25, 1 );
27997 DIP("tend. %u\n", A
);
28001 case 0x2EE: { //tsr.
28002 /* The tsr. is just a noop. Do nothing */
28003 UInt L
= IFIELD( theInstr
, 21, 1 );
28005 DIP("tsr. %u\n", L
);
28009 case 0x2CE: { //tcheck.
28010 /* The tcheck. is just a noop. Do nothing */
28011 UInt BF
= IFIELD( theInstr
, 25, 1 );
28013 DIP("tcheck. %u\n", BF
);
28017 case 0x30E: { //tbortwc.
28018 /* The tabortwc. is just a noop. Do nothing */
28019 UInt TO
= IFIELD( theInstr
, 25, 1 );
28020 UInt RA
= IFIELD( theInstr
, 16, 5 );
28021 UInt RB
= IFIELD( theInstr
, 11, 5 );
28023 DIP("tabortwc. %u,%u,%u\n", TO
, RA
, RB
);
28027 case 0x32E: { //tbortdc.
28028 /* The tabortdc. is just a noop. Do nothing */
28029 UInt TO
= IFIELD( theInstr
, 25, 1 );
28030 UInt RA
= IFIELD( theInstr
, 16, 5 );
28031 UInt RB
= IFIELD( theInstr
, 11, 5 );
28033 DIP("tabortdc. %u,%u,%u\n", TO
, RA
, RB
);
28037 case 0x34E: { //tbortwci.
28038 /* The tabortwci. is just a noop. Do nothing */
28039 UInt TO
= IFIELD( theInstr
, 25, 1 );
28040 UInt RA
= IFIELD( theInstr
, 16, 5 );
28041 UInt SI
= IFIELD( theInstr
, 11, 5 );
28043 DIP("tabortwci. %u,%u,%u\n", TO
, RA
, SI
);
28047 case 0x36E: { //tbortdci.
28048 /* The tabortdci. is just a noop. Do nothing */
28049 UInt TO
= IFIELD( theInstr
, 25, 1 );
28050 UInt RA
= IFIELD( theInstr
, 16, 5 );
28051 UInt SI
= IFIELD( theInstr
, 11, 5 );
28053 DIP("tabortdci. %u,%u,%u\n", TO
, RA
, SI
);
28057 case 0x38E: { //tbort.
28058 /* The tabort. is just a noop. Do nothing */
28059 UInt RA
= IFIELD( theInstr
, 16, 5 );
28061 DIP("tabort. %u\n", RA
);
28065 case 0x3AE: { //treclaim.
28066 /* The treclaim. is just a noop. Do nothing */
28067 UInt RA
= IFIELD( theInstr
, 16, 5 );
28069 DIP("treclaim. %u\n", RA
);
28073 case 0x3EE: { //trechkpt.
28074 /* The trechkpt. is just a noop. Do nothing */
28075 DIP("trechkpt.\n");
28080 vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
28088 /* The 0x3C primary opcode (VSX category) uses several different forms of
28089 * extended opcodes:
28091 * - [10:2] (IBM notation [21:29])
28092 * o XX3-form variants:
28093 * - variant 1: [10:3] (IBM notation [21:28])
28094 * - variant 2: [9:3] (IBM notation [22:28])
28095 * - variant 3: [7:3] (IBM notation [24:28])
28097 * - [10:6] (IBM notation [21:25])
28099 * The XX2-form needs bit 0 masked from the standard extended opcode
28100 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
28101 * and the XX4-form needs bits 0, 1, and 2 masked. Additionally, the
28102 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
28103 * front end since their encoding does not begin at bit 21 like the standard
28106 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
28107 * secondary opcode for such VSX instructions.
28114 const HChar
* name
;
28117 // ATTENTION: Keep this array sorted on the opcocde!!!
28118 static struct vsx_insn vsx_xx2
[] = {
28119 { 0x14, "xsrsqrtesp" },
28120 { 0x16, "xssqrtsp" },
28122 { 0x34, "xsresp" },
28123 { 0x90, "xscvdpuxws" },
28124 { 0x92, "xsrdpi" },
28125 { 0x94, "xsrsqrtedp" },
28126 { 0x96, "xssqrtdp" },
28127 { 0xb0, "xscvdpsxws" },
28128 { 0xb2, "xsrdpiz" },
28129 { 0xb4, "xsredp" },
28130 { 0xd2, "xsrdpip" },
28131 { 0xd4, "xstsqrtdp" },
28132 { 0xd6, "xsrdpic" },
28133 { 0xf2, "xsrdpim" },
28134 { 0x112, "xvrspi" },
28135 { 0x116, "xvsqrtsp" },
28136 { 0x130, "xvcvspsxws" },
28137 { 0x132, "xvrspiz" },
28138 { 0x134, "xvresp" },
28139 { 0x148, "xxspltw" },
28140 { 0x14A, "xxextractuw" },
28141 { 0x150, "xvcvuxwsp" },
28142 { 0x152, "xvrspip" },
28143 { 0x154, "xvtsqrtsp" },
28144 { 0x156, "xvrspic" },
28145 { 0x16A, "xxinsertw" },
28146 { 0x170, "xvcvsxwsp" },
28147 { 0x172, "xvrspim" },
28148 { 0x190, "xvcvdpuxws" },
28149 { 0x192, "xvrdpi" },
28150 { 0x194, "xvrsqrtedp" },
28151 { 0x196, "xvsqrtdp" },
28152 { 0x1b0, "xvcvdpsxws" },
28153 { 0x1b2, "xvrdpiz" },
28154 { 0x1b4, "xvredp" },
28155 { 0x1d0, "xvcvuxwdp" },
28156 { 0x1d2, "xvrdpip" },
28157 { 0x1d4, "xvtsqrtdp" },
28158 { 0x1d6, "xvrdpic" },
28159 { 0x1f0, "xvcvsxwdp" },
28160 { 0x1f2, "xvrdpim" },
28161 { 0x212, "xscvdpsp" },
28162 { 0x216, "xscvdpspn" },
28163 { 0x232, "xxrsp" },
28164 { 0x250, "xscvuxdsp" },
28165 { 0x254, "xststdcsp" },
28166 { 0x270, "xscvsxdsp" },
28167 { 0x290, "xscvdpuxds" },
28168 { 0x292, "xscvspdp" },
28169 { 0x296, "xscvspdpn" },
28170 { 0x2b0, "xscvdpsxds" },
28171 { 0x2b2, "xsabsdp" },
28172 { 0x2b6, "xsxexpdp_xsxigdp" },
28173 { 0x2d0, "xscvuxddp" },
28174 { 0x2d2, "xsnabsdp" },
28175 { 0x2d4, "xststdcdp" },
28176 { 0x2e4, "xsnmsubmdp" },
28177 { 0x2f0, "xscvsxddp" },
28178 { 0x2f2, "xsnegdp" },
28179 { 0x310, "xvcvspuxds" },
28180 { 0x312, "xvcvdpsp" },
28181 { 0x330, "xvcvspsxds" },
28182 { 0x332, "xvabssp" },
28183 { 0x350, "xvcvuxdsp" },
28184 { 0x352, "xvnabssp" },
28185 { 0x370, "xvcvsxdsp" },
28186 { 0x372, "xvnegsp" },
28187 { 0x390, "xvcvdpuxds" },
28188 { 0x392, "xvcvspdp" },
28189 { 0x3b0, "xvcvdpsxds" },
28190 { 0x3b2, "xvabsdp" },
28191 { 0x3b6, "xxbr[h|w|d|q]|xvxexpdp|xvxexpsp|xvxsigdp|xvxsigsp|xvcvhpsp|xvcvsphp|xscvdphp|xscvhpdp" },
28192 { 0x3d0, "xvcvuxddp" },
28193 { 0x3d2, "xvnabsdp" },
28194 { 0x3f2, "xvnegdp" }
28196 #define VSX_XX2_LEN (sizeof vsx_xx2 / sizeof *vsx_xx2)
28198 // ATTENTION: Keep this array sorted on the opcocde!!!
28199 static struct vsx_insn vsx_xx3
[] = {
28200 { 0x0, "xsaddsp" },
28201 { 0x4, "xsmaddasp" },
28202 { 0x9, "xsmaddmsp" },
28203 { 0xC, "xscmpeqdp" },
28204 { 0x20, "xssubsp" },
28205 { 0x24, "xsmaddmsp" },
28206 { 0x2C, "xscmpgtdp" },
28207 { 0x3A, "xxpermr" },
28208 { 0x40, "xsmulsp" },
28209 { 0x44, "xsmsubasp" },
28210 { 0x48, "xxmrghw" },
28211 { 0x4C, "xscmpgedp" },
28212 { 0x60, "xsdivsp" },
28213 { 0x64, "xsmsubmsp" },
28214 { 0x68, "xxperm" },
28215 { 0x80, "xsadddp" },
28216 { 0x84, "xsmaddadp" },
28217 { 0x8c, "xscmpudp" },
28218 { 0xa0, "xssubdp" },
28219 { 0xa4, "xsmaddmdp" },
28220 { 0xac, "xscmpodp" },
28221 { 0xc0, "xsmuldp" },
28222 { 0xc4, "xsmsubadp" },
28223 { 0xc8, "xxmrglw" },
28224 { 0xd4, "xstsqrtdp" },
28225 { 0xe0, "xsdivdp" },
28226 { 0xe4, "xsmsubmdp" },
28227 { 0xe8, "xxpermr" },
28228 { 0xeC, "xscmpexpdp" },
28229 { 0xf4, "xstdivdp" },
28230 { 0x100, "xvaddsp" },
28231 { 0x104, "xvmaddasp" },
28232 { 0x10C, "xvcmpeqsp" },
28233 { 0x110, "xvcvspuxws" },
28234 { 0x114, "xvrsqrtesp" },
28235 { 0x120, "xvsubsp" },
28236 { 0x124, "xvmaddmsp" },
28237 { 0x130, "xvcvspsxws" },
28238 { 0x140, "xvmulsp" },
28239 { 0x144, "xvmsubasp" },
28240 { 0x14C, "xvcmpgesp", },
28241 { 0x160, "xvdivsp" },
28242 { 0x164, "xvmsubmsp" },
28243 { 0x174, "xvtdivsp" },
28244 { 0x180, "xvadddp" },
28245 { 0x184, "xvmaddadp" },
28246 { 0x18C, "xvcmpeqdp" },
28247 { 0x1a0, "xvsubdp" },
28248 { 0x1a4, "xvmaddmdp" },
28249 { 0x1aC, "xvcmpgtdp" },
28250 { 0x1c0, "xvmuldp" },
28251 { 0x1c4, "xvmsubadp" },
28252 { 0x1cc, "xvcmpgedp" },
28253 { 0x1e0, "xvdivdp" },
28254 { 0x1e4, "xvmsubmdp" },
28255 { 0x1f4, "xvtdivdp" },
28256 { 0x200, "xsmaxcdp" },
28257 { 0x204, "xsnmaddasp" },
28258 { 0x208, "xxland" },
28259 { 0x220, "xsmincdp" },
28260 { 0x224, "xsnmaddmsp" },
28261 { 0x228, "xxlandc" },
28262 { 0x244, "xsnmsubasp" },
28263 { 0x248, "xxlor" },
28264 { 0x264, "xsnmsubmsp" },
28265 { 0x268, "xxlxor" },
28266 { 0x280, "xsmaxdp" },
28267 { 0x284, "xsnmaddadp" },
28268 { 0x288, "xxlnor" },
28269 { 0x2a0, "xsmindp" },
28270 { 0x2a4, "xsnmaddmdp" },
28271 { 0x2a8, "xxlorc" },
28272 { 0x2c0, "xscpsgndp" },
28273 { 0x2c4, "xsnmsubadp" },
28274 { 0x2c8, "xxlnand" },
28275 { 0x2e4, "xsnmsubmdp" },
28276 { 0x2e8, "xxleqv" },
28277 { 0x300, "xvmaxsp" },
28278 { 0x304, "xvnmaddasp" },
28279 { 0x320, "xvminsp" },
28280 { 0x324, "xvnmaddmsp" },
28281 { 0x340, "xvcpsgnsp" },
28282 { 0x344, "xvnmsubasp" },
28283 { 0x360, "xviexpsp" },
28284 { 0x364, "xvnmsubmsp" },
28285 { 0x380, "xvmaxdp" },
28286 { 0x384, "xvnmaddadp" },
28287 { 0x3a0, "xvmindp" },
28288 { 0x3a4, "xvnmaddmdp" },
28289 { 0x3c0, "xvcpsgndp" },
28290 { 0x3c4, "xvnmsubadp" },
28291 { 0x3e0, "xviexpdp" },
28292 { 0x3e4, "xvnmsubmdp" },
28293 { 0x3f0, "xvcvsxddp" },
28295 #define VSX_XX3_LEN (sizeof vsx_xx3 / sizeof *vsx_xx3)
28298 /* ATTENTION: These search functions assumes vsx_xx2 and vsx_xx3 arrays
28301 static Int
findVSXextOpCode_xx2(UInt opcode
)
28303 Int low
, mid
, high
;
28305 high
= VSX_XX2_LEN
- 1;
28306 while (low
<= high
) {
28307 mid
= (low
+ high
)/2;
28308 if (opcode
< vsx_xx2
[mid
].opcode
)
28310 else if (opcode
> vsx_xx2
[mid
].opcode
)
28318 static Int
findVSXextOpCode_xx3(UInt opcode
)
28320 Int low
, mid
, high
;
28322 high
= VSX_XX3_LEN
- 1;
28323 while (low
<= high
) {
28324 mid
= (low
+ high
)/2;
28325 if (opcode
< vsx_xx3
[mid
].opcode
)
28327 else if (opcode
> vsx_xx3
[mid
].opcode
)
28336 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
28337 * passed, and we then try to match it up with one of the VSX forms
28340 static UInt
get_VSX60_opc2(UInt opc2_full
, UInt theInstr
)
28342 #define XX2_1_MASK 0x000003FF // xsiexpdp specific
28343 #define XX2_2_MASK 0x000003FE
28344 #define XX3_1_MASK 0x000003FC
28345 #define XX3_2_MASK 0x000001FC
28346 #define XX3_4_MASK 0x0000027C
28347 #define XX3_5_MASK 0x000003DC
28348 #define XX4_MASK 0x00000018
28351 UInt vsxExtOpcode
= 0;
28353 if (( ret
= findVSXextOpCode_xx2(opc2_full
& XX2_2_MASK
)) >= 0)
28354 return vsx_xx2
[ret
].opcode
;
28355 else if ((opc2_full
& XX2_1_MASK
) == 0x396 ) // xsiexpdp
28357 else if (( ret
= findVSXextOpCode_xx3(opc2_full
& XX3_1_MASK
)) >= 0)
28358 return vsx_xx3
[ret
].opcode
;
28361 /* There are only a few codes in each of these cases it is
28362 * probably faster to check for the codes then do the array lookups.
28364 vsxExtOpcode
= opc2_full
& XX3_2_MASK
;
28366 switch (vsxExtOpcode
) {
28367 case 0x10C: return vsxExtOpcode
; // xvcmpeqsp
28368 case 0x12C: return vsxExtOpcode
; // xvcmpgtsp, xvcmpgtsp.
28369 case 0x14C: return vsxExtOpcode
; // xvcmpgesp, xvcmpgesp.
28370 case 0x18C: return vsxExtOpcode
; // xvcmpeqdp, xvcmpeqdp.
28371 case 0x1AC: return vsxExtOpcode
; // xvcmpgtdp, xvcmpgtdp.
28372 case 0x1CC: return vsxExtOpcode
; // xvcmpgedp, xvcmpgedp.
28376 vsxExtOpcode
= opc2_full
& XX3_4_MASK
;
28378 switch (vsxExtOpcode
) {
28379 case 0x8: return vsxExtOpcode
; // xxsldwi
28380 case 0x28: return vsxExtOpcode
; // xxpermdi
28384 vsxExtOpcode
= opc2_full
& XX3_5_MASK
;
28386 switch (vsxExtOpcode
) {
28387 case 0x354: return vsxExtOpcode
; // xvtstdcsp
28388 case 0x3D4: return vsxExtOpcode
; // xvtstdcdp
28392 if (( opc2_full
& XX4_MASK
) == XX4_MASK
) { // xxsel
28393 vsxExtOpcode
= 0x18;
28394 return vsxExtOpcode
;
28398 vex_printf( "Error: undefined opcode 0x %x, the instruction = 0x %x\n",
28399 opc2_full
, theInstr
);
28400 vpanic( "ERROR: get_VSX60_opc2()\n" );
28404 /*------------------------------------------------------------*/
28405 /*--- Disassemble a single instruction ---*/
28406 /*------------------------------------------------------------*/
28408 /* Disassemble a single instruction into IR. The instruction
28409 is located in host memory at &guest_code[delta]. */
28412 DisResult
disInstr_PPC_WRK (
28414 const VexArchInfo
* archinfo
,
28415 const VexAbiInfo
* abiinfo
,
28423 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
28424 UInt hwcaps
= archinfo
->hwcaps
;
28426 Bool allow_F
= False
;
28427 Bool allow_V
= False
;
28428 Bool allow_FX
= False
;
28429 Bool allow_GX
= False
;
28430 Bool allow_VX
= False
; // Equates to "supports Power ISA 2.06
28431 Bool allow_DFP
= False
;
28432 Bool allow_isa_2_07
= False
;
28433 Bool allow_isa_3_0
= False
;
28435 /* What insn variants are we supporting today? */
28438 allow_V
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_V
));
28439 allow_FX
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_FX
));
28440 allow_GX
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_GX
));
28441 allow_VX
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_VX
));
28442 allow_DFP
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_DFP
));
28443 allow_isa_2_07
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_ISA2_07
));
28444 allow_isa_3_0
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_ISA3_0
));
28446 allow_F
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_F
));
28447 allow_V
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_V
));
28448 allow_FX
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_FX
));
28449 allow_GX
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_GX
));
28450 allow_VX
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_VX
));
28451 allow_DFP
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_DFP
));
28452 allow_isa_2_07
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_ISA2_07
));
28453 allow_isa_3_0
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_ISA3_0
));
28456 /* Enable writting the OV32 and CA32 bits added with ISA3.0 */
28457 OV32_CA32_supported
= allow_isa_3_0
;
28459 /* The running delta */
28460 delta
= (Long
)mkSzAddr(ty
, (ULong
)delta64
);
28462 /* Set result defaults. */
28463 dres
.whatNext
= Dis_Continue
;
28465 dres
.jk_StopHere
= Ijk_INVALID
;
28466 dres
.hint
= Dis_HintNone
;
28468 /* At least this is simple on PPC32: insns are all 4 bytes long, and
28469 4-aligned. So just fish the whole thing out of memory right now
28471 theInstr
= getUIntPPCendianly( &guest_code
[delta
] );
28473 if (0) vex_printf("insn: 0x%x\n", theInstr
);
28475 DIP("\t0x%llx: ", (ULong
)guest_CIA_curr_instr
);
28477 /* Spot "Special" instructions (see comment at top of file). */
28479 const UChar
* code
= guest_code
+ delta
;
28480 /* Spot the 16-byte preamble:
28482 5400183E rlwinm 0,0,3,0,31
28483 5400683E rlwinm 0,0,13,0,31
28484 5400E83E rlwinm 0,0,29,0,31
28485 5400983E rlwinm 0,0,19,0,31
28487 78001800 rotldi 0,0,3
28488 78006800 rotldi 0,0,13
28489 7800E802 rotldi 0,0,61
28490 78009802 rotldi 0,0,51
28492 UInt word1
= mode64
? 0x78001800 : 0x5400183E;
28493 UInt word2
= mode64
? 0x78006800 : 0x5400683E;
28494 UInt word3
= mode64
? 0x7800E802 : 0x5400E83E;
28495 UInt word4
= mode64
? 0x78009802 : 0x5400983E;
28496 Bool is_special_preamble
= False
;
28497 if (getUIntPPCendianly(code
+ 0) == word1
&&
28498 getUIntPPCendianly(code
+ 4) == word2
&&
28499 getUIntPPCendianly(code
+ 8) == word3
&&
28500 getUIntPPCendianly(code
+12) == word4
) {
28501 is_special_preamble
= True
;
28502 } else if (! mode64
&&
28503 getUIntPPCendianly(code
+ 0) == 0x54001800 &&
28504 getUIntPPCendianly(code
+ 4) == 0x54006800 &&
28505 getUIntPPCendianly(code
+ 8) == 0x5400E800 &&
28506 getUIntPPCendianly(code
+12) == 0x54009800) {
28507 static Bool reported
= False
;
28509 vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
28510 vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
28513 is_special_preamble
= True
;
28515 if (is_special_preamble
) {
28516 /* Got a "Special" instruction preamble. Which one is it? */
28517 if (getUIntPPCendianly(code
+16) == 0x7C210B78 /* or 1,1,1 */) {
28518 /* %R3 = client_request ( %R4 ) */
28519 DIP("r3 = client_request ( %%r4 )\n");
28521 putGST( PPC_GST_CIA
, mkSzImm( ty
, guest_CIA_bbstart
+ delta
));
28522 dres
.jk_StopHere
= Ijk_ClientReq
;
28523 dres
.whatNext
= Dis_StopHere
;
28524 goto decode_success
;
28527 if (getUIntPPCendianly(code
+16) == 0x7C421378 /* or 2,2,2 */) {
28528 /* %R3 = guest_NRADDR */
28529 DIP("r3 = guest_NRADDR\n");
28532 putIReg(3, IRExpr_Get( OFFB_NRADDR
, ty
));
28533 goto decode_success
;
28536 if (getUIntPPCendianly(code
+16) == 0x7C631B78 /* or 3,3,3 */) {
28538 if (host_endness
== VexEndnessLE
) {
28539 /* branch-and-link-to-noredir %R12 */
28540 DIP("branch-and-link-to-noredir r12\n");
28541 putGST( PPC_GST_LR
,
28542 mkSzImm(ty
, guest_CIA_bbstart
+ (Long
)delta
) );
28543 putGST( PPC_GST_CIA
, getIReg(12));
28545 /* branch-and-link-to-noredir %R11 */
28546 DIP("branch-and-link-to-noredir r11\n");
28547 putGST( PPC_GST_LR
,
28548 mkSzImm(ty
, guest_CIA_bbstart
+ (Long
)delta
) );
28549 putGST( PPC_GST_CIA
, getIReg(11));
28551 dres
.jk_StopHere
= Ijk_NoRedir
;
28552 dres
.whatNext
= Dis_StopHere
;
28553 goto decode_success
;
28556 if (getUIntPPCendianly(code
+16) == 0x7C842378 /* or 4,4,4 */) {
28557 /* %R3 = guest_NRADDR_GPR2 */
28558 DIP("r3 = guest_NRADDR_GPR2\n");
28561 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2
, ty
));
28562 goto decode_success
;
28565 if (getUIntPPCendianly(code
+16) == 0x7CA52B78 /* or 5,5,5 */) {
28566 DIP("IR injection\n");
28567 if (host_endness
== VexEndnessBE
)
28568 vex_inject_ir(irsb
, Iend_BE
);
28570 vex_inject_ir(irsb
, Iend_LE
);
28575 // Invalidate the current insn. The reason is that the IRop we're
28576 // injecting here can change. In which case the translation has to
28577 // be redone. For ease of handling, we simply invalidate all the
28580 stmt(IRStmt_Put(OFFB_CMSTART
, mkSzImm(ty
, guest_CIA_curr_instr
)));
28581 stmt(IRStmt_Put(OFFB_CMLEN
, mkSzImm(ty
, 20)));
28583 putGST( PPC_GST_CIA
, mkSzImm( ty
, guest_CIA_bbstart
+ delta
));
28584 dres
.whatNext
= Dis_StopHere
;
28585 dres
.jk_StopHere
= Ijk_InvalICache
;
28586 goto decode_success
;
28588 /* We don't know what it is. Set opc1/opc2 so decode_failure
28589 can print the insn following the Special-insn preamble. */
28590 theInstr
= getUIntPPCendianly(code
+16);
28591 opc1
= ifieldOPC(theInstr
);
28592 opc2
= ifieldOPClo10(theInstr
);
28593 goto decode_failure
;
28598 opc1
= ifieldOPC(theInstr
);
28599 opc2
= ifieldOPClo10(theInstr
);
28601 // Note: all 'reserved' bits must be cleared, else invalid
28604 /* Integer Arithmetic Instructions */
28605 case 0x0C: case 0x0D: case 0x0E: // addic, addic., addi
28606 case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic
28607 if (dis_int_arith( theInstr
)) goto decode_success
;
28608 goto decode_failure
;
28610 /* Integer Compare Instructions */
28611 case 0x0B: case 0x0A: // cmpi, cmpli
28612 if (dis_int_cmp( theInstr
)) goto decode_success
;
28613 goto decode_failure
;
28615 /* Integer Logical Instructions */
28616 case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
28617 case 0x19: case 0x1A: case 0x1B: // oris, xori, xoris
28618 if (dis_int_logic( theInstr
)) goto decode_success
;
28619 goto decode_failure
;
28621 /* Integer Rotate Instructions */
28622 case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm
28623 if (dis_int_rot( theInstr
)) goto decode_success
;
28624 goto decode_failure
;
28626 /* 64bit Integer Rotate Instructions */
28627 case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
28628 if (!mode64
) goto decode_failure
;
28629 if (dis_int_rot( theInstr
)) goto decode_success
;
28630 goto decode_failure
;
28632 /* Integer Load Instructions */
28633 case 0x22: case 0x23: case 0x2A: // lbz, lbzu, lha
28634 case 0x2B: case 0x28: case 0x29: // lhau, lhz, lhzu
28635 case 0x20: case 0x21: // lwz, lwzu
28636 if (dis_int_load( theInstr
)) goto decode_success
;
28637 goto decode_failure
;
28639 /* Integer Store Instructions */
28640 case 0x26: case 0x27: case 0x2C: // stb, stbu, sth
28641 case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu
28642 if (dis_int_store( theInstr
, abiinfo
)) goto decode_success
;
28643 goto decode_failure
;
28645 /* Integer Load and Store Multiple Instructions */
28646 case 0x2E: case 0x2F: // lmw, stmw
28647 if (dis_int_ldst_mult( theInstr
)) goto decode_success
;
28648 goto decode_failure
;
28650 /* Branch Instructions */
28651 case 0x12: case 0x10: // b, bc
28652 if (dis_branch(theInstr
, abiinfo
, &dres
))
28653 goto decode_success
;
28654 goto decode_failure
;
28656 /* System Linkage Instructions */
28658 if (dis_syslink(theInstr
, abiinfo
, &dres
)) goto decode_success
;
28659 goto decode_failure
;
28661 /* Trap Instructions */
28663 if (!mode64
) goto decode_failure
;
28664 if (dis_trapi(theInstr
, &dres
)) goto decode_success
;
28665 goto decode_failure
;
28668 if (dis_trapi(theInstr
, &dres
)) goto decode_success
;
28669 goto decode_failure
;
28671 /* Floating Point Load Instructions */
28672 case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
28674 if (!allow_F
) goto decode_noF
;
28675 if (dis_fp_load( theInstr
)) goto decode_success
;
28676 goto decode_failure
;
28678 /* Floating Point Store Instructions */
28679 case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
28680 case 0x37: // stfdux
28681 if (!allow_F
) goto decode_noF
;
28682 if (dis_fp_store( theInstr
)) goto decode_success
;
28683 goto decode_failure
;
28685 /* Floating Point Load Double Pair Instructions */
28686 case 0x39: case 0x3D: // lfdp, lxsd, lxssp, lxv
28687 // stfdp, stxsd, stxssp, stxv
28688 if (!allow_F
) goto decode_noF
;
28689 if (dis_fp_pair( theInstr
)) goto decode_success
;
28690 goto decode_failure
;
28692 /* 128-bit Integer Load */
28694 if (dis_int_load( theInstr
)) goto decode_success
;
28695 goto decode_failure
;
28697 /* 64bit Integer Loads */
28698 case 0x3A: // ld, ldu, lwa
28699 if (!mode64
) goto decode_failure
;
28700 if (dis_int_load( theInstr
)) goto decode_success
;
28701 goto decode_failure
;
28704 if (!allow_F
) goto decode_noF
;
28705 opc2
= ifieldOPClo10(theInstr
);
28708 case 0x2: // dadd - DFP Add
28709 case 0x202: // dsub - DFP Subtract
28710 case 0x22: // dmul - DFP Mult
28711 case 0x222: // ddiv - DFP Divide
28712 if (!allow_DFP
) goto decode_noDFP
;
28713 if (dis_dfp_arith( theInstr
))
28714 goto decode_success
;
28715 goto decode_failure
;
28716 case 0x82: // dcmpo, DFP comparison ordered instruction
28717 case 0x282: // dcmpu, DFP comparison unordered instruction
28718 if (!allow_DFP
) goto decode_noDFP
;
28719 if (dis_dfp_compare( theInstr
) )
28720 goto decode_success
;
28721 goto decode_failure
;
28722 case 0x102: // dctdp - DFP convert to DFP long
28723 case 0x302: // drsp - DFP round to dfp short
28724 case 0x122: // dctfix - DFP convert to fixed
28725 if (!allow_DFP
) goto decode_noDFP
;
28726 if (dis_dfp_fmt_conv( theInstr
))
28727 goto decode_success
;
28728 goto decode_failure
;
28729 case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
28731 goto decode_failure
;
28732 if (!allow_DFP
) goto decode_noDFP
;
28733 if (dis_dfp_fmt_conv( theInstr
))
28734 goto decode_success
;
28735 goto decode_failure
;
28736 case 0x2A2: // dtstsf - DFP number of significant digits
28737 case 0x2A3: // dtstsfi - DFP number of significant digits Immediate
28738 if (!allow_DFP
) goto decode_noDFP
;
28739 if (dis_dfp_significant_digits(theInstr
))
28740 goto decode_success
;
28741 goto decode_failure
;
28742 case 0x142: // ddedpd DFP Decode DPD to BCD
28743 case 0x342: // denbcd DFP Encode BCD to DPD
28744 if (!allow_DFP
) goto decode_noDFP
;
28745 if (dis_dfp_bcd(theInstr
))
28746 goto decode_success
;
28747 goto decode_failure
;
28748 case 0x162: // dxex - Extract exponent
28749 case 0x362: // diex - Insert exponent
28750 if (!allow_DFP
) goto decode_noDFP
;
28751 if (dis_dfp_extract_insert( theInstr
) )
28752 goto decode_success
;
28753 goto decode_failure
;
28754 case 0x3CE: // fcfidus (implemented as native insn)
28757 if (dis_fp_round( theInstr
))
28758 goto decode_success
;
28759 goto decode_failure
;
28760 case 0x34E: // fcfids
28761 if (dis_fp_round( theInstr
))
28762 goto decode_success
;
28763 goto decode_failure
;
28766 opc2
= ifieldOPClo9( theInstr
);
28768 case 0x42: // dscli, DFP shift left
28769 case 0x62: // dscri, DFP shift right
28770 if (!allow_DFP
) goto decode_noDFP
;
28771 if (dis_dfp_shift( theInstr
))
28772 goto decode_success
;
28773 goto decode_failure
;
28774 case 0xc2: // dtstdc, DFP test data class
28775 case 0xe2: // dtstdg, DFP test data group
28776 if (!allow_DFP
) goto decode_noDFP
;
28777 if (dis_dfp_class_test( theInstr
))
28778 goto decode_success
;
28779 goto decode_failure
;
28782 opc2
= ifieldOPClo8( theInstr
);
28784 case 0x3: // dqua - DFP Quantize
28785 case 0x23: // drrnd - DFP Reround
28786 case 0x43: // dquai - DFP Quantize immediate
28787 if (!allow_DFP
) goto decode_noDFP
;
28788 if (dis_dfp_quantize_sig_rrnd( theInstr
) )
28789 goto decode_success
;
28790 goto decode_failure
;
28791 case 0xA2: // dtstex - DFP Test exponent
28792 if (!allow_DFP
) goto decode_noDFP
;
28793 if (dis_dfp_exponent_test( theInstr
) )
28794 goto decode_success
;
28795 goto decode_failure
;
28796 case 0x63: // drintx - Round to an integer value
28797 case 0xE3: // drintn - Round to an integer value
28798 if (!allow_DFP
) goto decode_noDFP
;
28799 if (dis_dfp_round( theInstr
) ) {
28800 goto decode_success
;
28802 goto decode_failure
;
28804 break; /* fall through to next opc2 check */
28807 opc2
= IFIELD(theInstr
, 1, 5);
28809 /* Floating Point Arith Instructions */
28810 case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds
28811 case 0x19: // fmuls
28812 if (dis_fp_arith(theInstr
)) goto decode_success
;
28813 goto decode_failure
;
28814 case 0x16: // fsqrts
28815 if (!allow_FX
) goto decode_noFX
;
28816 if (dis_fp_arith(theInstr
)) goto decode_success
;
28817 goto decode_failure
;
28819 if (!allow_GX
) goto decode_noGX
;
28820 if (dis_fp_arith(theInstr
)) goto decode_success
;
28821 goto decode_failure
;
28823 /* Floating Point Mult-Add Instructions */
28824 case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
28825 case 0x1F: // fnmadds
28826 if (dis_fp_multadd(theInstr
)) goto decode_success
;
28827 goto decode_failure
;
28829 case 0x1A: // frsqrtes
28830 if (!allow_GX
) goto decode_noGX
;
28831 if (dis_fp_arith(theInstr
)) goto decode_success
;
28832 goto decode_failure
;
28835 goto decode_failure
;
28839 case 0x3C: // VSX instructions (except load/store)
28841 // All of these VSX instructions use some VMX facilities, so
28842 // if allow_V is not set, we'll skip trying to decode.
28843 if (!allow_V
) goto decode_noVX
;
28844 /* The xvtstdcdp and xvtstdcsp instructions do not have a
28845 contiguous opc2 field. The following vsxOpc2 = get_VSX60_opc2()
28846 doesn't correctly match these instructions for dc != 0. So,
28847 we will explicitly look for the two instructions. */
28848 opc2
= ifieldOPClo10(theInstr
);
28849 UInt opc2hi
= IFIELD(theInstr
, 7, 4);
28850 UInt opc2lo
= IFIELD(theInstr
, 3, 3);
28853 if (( opc2hi
== 13 ) && ( opc2lo
== 5)) { //xvtstdcsp
28854 if (dis_vxs_misc(theInstr
, abiinfo
, 0x354, allow_isa_3_0
))
28855 goto decode_success
;
28856 goto decode_failure
;
28859 if (( opc2hi
== 15 ) && ( opc2lo
== 5)) { //xvtstdcdp
28860 if (dis_vxs_misc(theInstr
, abiinfo
, 0x3D4, allow_isa_3_0
))
28861 goto decode_success
;
28862 goto decode_failure
;
28865 /* The vsxOpc2 returned is the "normalized" value, representing the
28866 * instructions secondary opcode as taken from the standard secondary
28867 * opcode field [21:30] (IBM notatition), even if the actual field
28868 * is non-standard. These normalized values are given in the opcode
28869 * appendices of the ISA 2.06 document.
28871 if ( ( opc2
== 0x168 ) && ( IFIELD( theInstr
, 19, 2 ) == 0 ) )// xxspltib
28873 /* This is a special case of the XX1 form where the RA, RB
28874 * fields hold an immediate value.
28876 if (dis_vxs_misc(theInstr
, abiinfo
, opc2
, allow_isa_3_0
)) goto decode_success
;
28877 goto decode_failure
;
28880 vsxOpc2
= get_VSX60_opc2(opc2
, theInstr
);
28883 case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
28884 case 0x068: case 0xE8: // xxperm, xxpermr
28885 case 0x018: case 0x148: // xxsel, xxspltw
28886 if (dis_vx_permute_misc(theInstr
, vsxOpc2
))
28887 goto decode_success
;
28888 goto decode_failure
;
28889 case 0xC: case 0x2C: case 0x4C: // xscmpeqdp, xscmpgtdp, xscmpgedp
28890 case 0x200: case 0x220: //xsmaxcdp, xsmincdp
28891 if (dis_vx_misc(theInstr
, vsxOpc2
)) goto decode_success
;
28892 goto decode_failure
;
28893 case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
28894 case 0x208: case 0x228: // xxland, xxlandc
28895 case 0x2A8: case 0x2C8: case 0x2E8: // xxlorc, xxlnand, xxleqv
28896 if (dis_vx_logic(theInstr
, vsxOpc2
)) goto decode_success
;
28897 goto decode_failure
;
28898 case 0x0ec: // xscmpexpdp
28899 case 0x14A: case 0x16A: // xxextractuw, xxinsertw
28900 case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
28901 case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
28902 case 0x280: case 0x2A0: // xsmaxdp, xsmindp
28903 case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
28904 case 0x034: case 0x014: // xsresp, xsrsqrtesp
28905 case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
28906 case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
28907 case 0x092: case 0x232: // xsrdpi, xsrsp
28908 case 0x3B6: // xxbrh, xvxexpdp, xvxexpsp, xvxsigdp
28909 // xvxsigsp, xvcvhpsp
28910 case 0x2b6: // xsxexpdp, xsxsigdp
28911 case 0x254: case 0x2d4: // xststdcsp, xststdcdp
28912 case 0x354: // xvtstdcsp
28913 case 0x360:case 0x396: // xviexpsp, xsiexpdp
28914 case 0x3D4: case 0x3E0: // xvtstdcdp, xviexpdp
28915 if (dis_vxs_misc(theInstr
, abiinfo
, vsxOpc2
, allow_isa_3_0
))
28916 goto decode_success
;
28917 goto decode_failure
;
28918 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
28919 if (dis_vx_cmp(theInstr
, vsxOpc2
)) goto decode_success
;
28920 goto decode_failure
;
28921 case 0x0: case 0x020: // xsaddsp, xssubsp
28922 case 0x080: // xsadddp
28923 case 0x060: case 0x0E0: // xsdivsp, xsdivdp
28924 case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
28925 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
28926 case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
28927 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
28928 case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
28929 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
28930 case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
28931 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
28932 case 0x040: case 0x0C0: // xsmulsp, xsmuldp
28933 case 0x0A0: // xssubdp
28934 case 0x016: case 0x096: // xssqrtsp,xssqrtdp
28935 case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
28936 if (dis_vxs_arith(theInstr
, vsxOpc2
)) goto decode_success
;
28937 goto decode_failure
;
28938 case 0x180: // xvadddp
28939 case 0x1E0: // xvdivdp
28940 case 0x1C0: // xvmuldp
28941 case 0x1A0: // xvsubdp
28942 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
28943 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
28944 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
28945 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
28946 case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
28947 case 0x196: // xvsqrtdp
28948 if (dis_vxv_dp_arith(theInstr
, vsxOpc2
)) goto decode_success
;
28949 goto decode_failure
;
28950 case 0x100: // xvaddsp
28951 case 0x160: // xvdivsp
28952 case 0x140: // xvmulsp
28953 case 0x120: // xvsubsp
28954 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
28955 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
28956 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
28957 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
28958 case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
28959 case 0x116: // xvsqrtsp
28960 if (dis_vxv_sp_arith(theInstr
, vsxOpc2
)) goto decode_success
;
28961 goto decode_failure
;
28963 case 0x250: // xscvuxdsp
28964 case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
28965 case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
28966 case 0x090: // xscvdpuxws
28967 // The above VSX conversion instructions employ some ISA 2.06
28968 // floating point conversion instructions under the covers,
28969 // so if allow_VX (which means "supports ISA 2.06") is not set,
28970 // we'll skip the decode.
28971 if (!allow_VX
) goto decode_noVX
;
28972 if (dis_vx_conv(theInstr
, vsxOpc2
)) goto decode_success
;
28973 goto decode_failure
;
28975 case 0x2B0: // xscvdpsxds
28976 case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
28977 case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
28978 case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
28979 case 0x212: case 0x216: // xscvdpsp, xscvdpspn
28980 case 0x292: case 0x296: // xscvspdp, xscvspdpn
28981 case 0x312: // xvcvdpsp
28982 case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
28983 case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
28984 case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
28985 case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
28986 case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
28987 case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
28988 if (dis_vx_conv(theInstr
, vsxOpc2
)) goto decode_success
;
28989 goto decode_failure
;
28991 case 0x18C: // xvcmpeqdp[.]
28992 case 0x10C: // xvcmpeqsp[.]
28993 case 0x14C: // xvcmpgesp[.]
28994 case 0x12C: // xvcmpgtsp[.]
28995 case 0x1CC: // xvcmpgedp[.]
28996 case 0x1AC: // xvcmpgtdp[.]
28997 if (dis_vvec_cmp(theInstr
, vsxOpc2
)) goto decode_success
;
28998 goto decode_failure
;
29000 case 0x134: // xvresp
29001 case 0x1B4: // xvredp
29002 case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
29003 case 0x372: // xvnegsp
29004 case 0x380: case 0x3A0: // xvmaxdp, xvmindp
29005 case 0x300: case 0x320: // xvmaxsp, xvminsp
29006 case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
29007 case 0x3B2: case 0x332: // xvabsdp, xvabssp
29008 case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
29009 case 0x192: case 0x1D6: // xvrdpi, xvrdpic
29010 case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
29011 case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
29012 case 0x112: case 0x156: // xvrspi, xvrspic
29013 case 0x172: case 0x152: // xvrspim, xvrspip
29014 case 0x132: // xvrspiz
29015 if (dis_vxv_misc(theInstr
, vsxOpc2
)) goto decode_success
;
29016 goto decode_failure
;
29019 goto decode_failure
;
29024 /* 64bit Integer Stores */
29025 case 0x3E: // std, stdu, stq
29026 if (dis_int_store( theInstr
, abiinfo
)) goto decode_success
;
29027 goto decode_failure
;
29030 if (!allow_F
) goto decode_noF
;
29031 /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
29032 so we can simply fall through the first switch statement */
29034 opc2
= IFIELD(theInstr
, 1, 5);
29036 /* Floating Point Arith Instructions */
29037 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
29039 if (dis_fp_arith(theInstr
)) goto decode_success
;
29040 goto decode_failure
;
29041 case 0x16: // fsqrt
29042 if (!allow_FX
) goto decode_noFX
;
29043 if (dis_fp_arith(theInstr
)) goto decode_success
;
29044 goto decode_failure
;
29045 case 0x17: case 0x1A: // fsel, frsqrte
29046 if (!allow_GX
) goto decode_noGX
;
29047 if (dis_fp_arith(theInstr
)) goto decode_success
;
29048 goto decode_failure
;
29050 /* Floating Point Mult-Add Instructions */
29051 case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
29052 case 0x1F: // fnmadd
29053 if (dis_fp_multadd(theInstr
)) goto decode_success
;
29054 goto decode_failure
;
29057 if (!allow_GX
) goto decode_noGX
;
29058 if (dis_fp_arith(theInstr
)) goto decode_success
;
29059 goto decode_failure
;
29062 break; // Fall through
29065 opc2
= IFIELD(theInstr
, 1, 8);
29067 case 0x5: // xsrqpi, xsrqpix
29068 case 0x25: // xsrqpxp
29069 if ( !mode64
|| !allow_isa_3_0
) goto decode_failure
;
29070 if ( dis_vx_Scalar_Round_to_quad_integer( theInstr
, abiinfo
) )
29071 goto decode_success
;
29072 goto decode_failure
;
29074 break; // Fall through
29077 opc2
= IFIELD(theInstr
, 1, 10);
29078 UInt inst_select
= IFIELD( theInstr
, 16, 5 );
29081 /* 128-bit DFP instructions */
29082 case 0x2: // daddq - DFP Add
29083 case 0x202: // dsubq - DFP Subtract
29084 case 0x22: // dmulq - DFP Mult
29085 case 0x222: // ddivq - DFP Divide
29086 if (!allow_DFP
) goto decode_noDFP
;
29087 if (dis_dfp_arithq( theInstr
))
29088 goto decode_success
;
29089 goto decode_failure
;
29090 case 0x162: // dxexq - DFP Extract exponent
29091 case 0x362: // diexq - DFP Insert exponent
29092 if (!allow_DFP
) goto decode_noDFP
;
29093 if (dis_dfp_extract_insertq( theInstr
))
29094 goto decode_success
;
29095 goto decode_failure
;
29097 case 0x82: // dcmpoq, DFP comparison ordered instruction
29098 case 0x282: // dcmpuq, DFP comparison unordered instruction
29099 if (!allow_DFP
) goto decode_noDFP
;
29100 if (dis_dfp_compare( theInstr
) )
29101 goto decode_success
;
29102 goto decode_failure
;
29104 case 0x102: // dctqpq - DFP convert to DFP extended
29105 case 0x302: // drdpq - DFP round to dfp Long
29106 case 0x122: // dctfixq - DFP convert to fixed quad
29107 case 0x322: // dcffixq - DFP convert from fixed quad
29108 if (!allow_DFP
) goto decode_noDFP
;
29109 if (dis_dfp_fmt_convq( theInstr
))
29110 goto decode_success
;
29111 goto decode_failure
;
29113 case 0x2A2: // dtstsfq - DFP number of significant digits
29114 case 0x2A3: // dtstsfiq - DFP number of significant digits Immediate
29115 if (!allow_DFP
) goto decode_noDFP
;
29116 if (dis_dfp_significant_digits(theInstr
))
29117 goto decode_success
;
29118 goto decode_failure
;
29120 case 0x142: // ddedpdq DFP Decode DPD to BCD
29121 case 0x342: // denbcdq DFP Encode BCD to DPD
29122 if (!allow_DFP
) goto decode_noDFP
;
29123 if (dis_dfp_bcdq(theInstr
))
29124 goto decode_success
;
29125 goto decode_failure
;
29127 /* Floating Point Compare Instructions */
29128 case 0x000: // fcmpu
29129 case 0x020: // fcmpo
29130 if (dis_fp_cmp(theInstr
)) goto decode_success
;
29131 goto decode_failure
;
29133 case 0x080: // ftdiv
29134 case 0x0A0: // ftsqrt
29135 if (dis_fp_tests(theInstr
)) goto decode_success
;
29136 goto decode_failure
;
29138 /* Floating Point Rounding/Conversion Instructions */
29139 case 0x00C: // frsp
29140 case 0x00E: // fctiw
29141 case 0x00F: // fctiwz
29142 case 0x32E: // fctid
29143 case 0x32F: // fctidz
29144 case 0x34E: // fcfid
29145 if (dis_fp_round(theInstr
)) goto decode_success
;
29146 goto decode_failure
;
29147 case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
29148 case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
29149 if (!allow_VX
) goto decode_noVX
;
29150 if (dis_fp_round(theInstr
)) goto decode_success
;
29151 goto decode_failure
;
29153 /* Power6 rounding stuff */
29154 case 0x1E8: // frim
29155 case 0x1C8: // frip
29156 case 0x188: // frin
29157 case 0x1A8: // friz
29158 /* A hack to check for P6 capability . . . */
29159 if ((allow_F
&& allow_V
&& allow_FX
&& allow_GX
) &&
29160 (dis_fp_round(theInstr
)))
29161 goto decode_success
;
29162 goto decode_failure
;
29164 /* Floating Point Move Instructions */
29165 case 0x008: // fcpsgn
29166 case 0x028: // fneg
29168 case 0x088: // fnabs
29169 case 0x108: // fabs
29170 if (dis_fp_move( theInstr
)) goto decode_success
;
29171 goto decode_failure
;
29173 case 0x3c6: case 0x346: // fmrgew, fmrgow
29174 if (dis_fp_merge( theInstr
)) goto decode_success
;
29175 goto decode_failure
;
29177 /* Floating Point Status/Control Register Instructions */
29178 case 0x026: // mtfsb1
29179 case 0x040: // mcrfs
29180 case 0x046: // mtfsb0
29181 case 0x086: // mtfsfi
29182 case 0x247: // mffs, mmfs., mffsce, mffscdrn, mffscdrni,
29183 // mffscrn, mffscrn, mffscri, mffsl
29184 case 0x2C7: // mtfsf
29185 // Some of the above instructions need to know more about the
29186 // ISA level supported by the host.
29187 if (dis_fp_scr( theInstr
, allow_GX
)) goto decode_success
;
29188 goto decode_failure
;
29190 case 0x324: // xsabsqp, xsxexpqp,xsnabsqp, xsnegqp, xsxsigqp
29191 if ( inst_select
== 27 ) { // xssqrtqp
29192 if ( dis_vx_Floating_Point_Arithmetic_quad_precision( theInstr
,
29194 goto decode_success
;
29196 /* fallthrough to dis_vx_scalar_quad_precision */
29198 /* Instructions implemented with Pre ISA 3.0 Iops */
29199 /* VSX Scalar Quad-Precision instructions */
29200 case 0x064: // xscpsgnqp
29201 case 0x0A4: // xscmpexpqp
29202 case 0x084: // xscmpoqp
29203 case 0x284: // xscmpuqp
29204 case 0x2C4: // xststdcqp
29205 case 0x364: // xsiexpqp
29206 if (dis_vx_scalar_quad_precision( theInstr
)) goto decode_success
;
29207 goto decode_failure
;
29209 /* Instructions implemented using ISA 3.0 instructions */
29210 // xsaddqpo (VSX Scalar Add Quad-Precision [using round to ODD]
29211 case 0x004: // xsaddqp (VSX Scalar Add Quad-Precision [using RN mode]
29212 // xsmulqpo (VSX Scalar Multiply Quad-Precision [using round to ODD]
29213 case 0x024: // xsmulqp (VSX Scalar Multiply Quad-Precision [using RN mode]
29214 // xsmaddqpo (VSX Scalar Multiply Add Quad-Precision [using round to ODD]
29215 case 0x184: // xsmaddqp (VSX Scalar Multiply Add Quad-Precision [using RN mode]
29216 // xsmsubqpo (VSX Scalar Multiply Sub Quad-Precision [using round to ODD]
29217 case 0x1A4: // xsmsubqp (VSX Scalar Multiply Sub Quad-Precision [using RN mode]
29218 // xsnmaddqpo (VSX Scalar Negative Multiply Add Quad-Precision [using round to ODD]
29219 case 0x1C4: // xsnmaddqp (VSX Scalar Negative Multiply Add Quad-Precision [using RN mode]
29220 // xsnmsubqpo (VSX Scalar Negative Multiply Sub Quad-Precision [using round to ODD]
29221 case 0x1E4: // xsnmsubqp (VSX Scalar Negative Multiply Sub Quad-Precision [usin RN mode]
29222 // xssubqpo (VSX Scalar Subrtact Quad-Precision [using round to ODD]
29223 case 0x204: // xssubqp (VSX Scalar Subrtact Quad-Precision [using RN mode]
29224 // xsdivqpo (VSX Scalar Divde Quad-Precision [using round to ODD]
29225 case 0x224: // xsdivqp (VSX Scalar Divde Quad-Precision [using RN mode]
29226 case 0x344: // xscvudqp, xscvsdqp, xscvqpdp, xscvqpdpo, xsvqpdp
29227 // xscvqpswz, xscvqpuwz, xscvqpudz, xscvqpsdz
29228 if ( !mode64
|| !allow_isa_3_0
) goto decode_failure
;
29229 if ( dis_vx_Floating_Point_Arithmetic_quad_precision( theInstr
,
29231 goto decode_success
;
29232 goto decode_failure
;
29235 break; // Fall through...
29238 opc2
= ifieldOPClo9( theInstr
);
29240 case 0x42: // dscli, DFP shift left
29241 case 0x62: // dscri, DFP shift right
29242 if (!allow_DFP
) goto decode_noDFP
;
29243 if (dis_dfp_shiftq( theInstr
))
29244 goto decode_success
;
29245 goto decode_failure
;
29246 case 0xc2: // dtstdc, DFP test data class
29247 case 0xe2: // dtstdg, DFP test data group
29248 if (!allow_DFP
) goto decode_noDFP
;
29249 if (dis_dfp_class_test( theInstr
))
29250 goto decode_success
;
29251 goto decode_failure
;
29256 opc2
= ifieldOPClo8( theInstr
);
29258 case 0x3: // dquaq - DFP Quantize Quad
29259 case 0x23: // drrndq - DFP Reround Quad
29260 case 0x43: // dquaiq - DFP Quantize immediate Quad
29261 if (!allow_DFP
) goto decode_noDFP
;
29262 if (dis_dfp_quantize_sig_rrndq( theInstr
))
29263 goto decode_success
;
29264 goto decode_failure
;
29265 case 0xA2: // dtstexq - DFP Test exponent Quad
29266 if (!allow_DFP
) goto decode_noDFP
;
29267 if (dis_dfp_exponent_test( theInstr
) )
29268 goto decode_success
;
29269 goto decode_failure
;
29270 case 0x63: // drintxq - DFP Round to an integer value
29271 case 0xE3: // drintnq - DFP Round to an integer value
29272 if (!allow_DFP
) goto decode_noDFP
;
29273 if (dis_dfp_roundq( theInstr
))
29274 goto decode_success
;
29275 goto decode_failure
;
29278 goto decode_failure
;
29284 opc2
= ifieldOPClo5(theInstr
);
29287 /* PC relative load/store */
29288 case 0x002: // addpcis
29289 if (dis_pc_relative(theInstr
)) goto decode_success
;
29290 goto decode_failure
;
29292 /* fall through to the next opc2 field size */
29295 opc2
= ifieldOPClo10(theInstr
);
29298 /* Condition Register Logical Instructions */
29299 case 0x101: case 0x081: case 0x121: // crand, crandc, creqv
29300 case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror
29301 case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf
29302 if (dis_cond_logic( theInstr
)) goto decode_success
;
29303 goto decode_failure
;
29305 /* Branch Instructions */
29306 case 0x210: case 0x010: // bcctr, bclr
29307 if (dis_branch(theInstr
, abiinfo
, &dres
))
29308 goto decode_success
;
29309 goto decode_failure
;
29311 /* Memory Synchronization Instructions */
29312 case 0x096: // isync
29313 if (dis_memsync( theInstr
)) goto decode_success
;
29314 goto decode_failure
;
29317 goto decode_failure
;
29324 /* For arith instns, bit10 is the OE flag (overflow enable) */
29326 opc2
= IFIELD(theInstr
, 1, 9);
29328 /* Integer Arithmetic Instructions */
29329 case 0x10A: case 0x00A: case 0x08A: // add, addc, adde
29330 case 0x0AA: // addex
29331 case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
29332 case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
29333 case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf
29334 case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
29335 case 0x0C8: // subfze
29336 if (dis_int_arith( theInstr
)) goto decode_success
;
29337 goto decode_failure
;
29339 case 0x18B: // divweu (implemented as native insn)
29340 case 0x1AB: // divwe (implemented as native insn)
29341 if (!allow_VX
) goto decode_noVX
;
29342 if (dis_int_arith( theInstr
)) goto decode_success
;
29343 goto decode_failure
;
29345 /* 64bit Integer Arithmetic */
29346 case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
29347 case 0x1C9: case 0x1E9: // divdu, divd
29348 if (!mode64
) goto decode_failure
;
29349 if (dis_int_arith( theInstr
)) goto decode_success
;
29350 goto decode_failure
;
29352 case 0x1A9: // divde (implemented as native insn)
29353 case 0x189: // divdeuo (implemented as native insn)
29354 if (!allow_VX
) goto decode_noVX
;
29355 if (!mode64
) goto decode_failure
;
29356 if (dis_int_arith( theInstr
)) goto decode_success
;
29357 goto decode_failure
;
29359 case 0x1FC: // cmpb
29360 if (dis_int_logic( theInstr
)) goto decode_success
;
29361 goto decode_failure
;
29364 break; // Fall through...
29367 /* All remaining opcodes use full 10 bits. */
29369 opc2
= IFIELD(theInstr
, 1, 10);
29372 /* Integer miscellaneous instructions */
29373 case 0x01E: // wait RFC 2500
29374 if (dis_int_misc( theInstr
)) goto decode_success
;
29375 goto decode_failure
;
29378 /* Integer Compare Instructions */
29379 case 0x000: case 0x020: case 0x080: // cmp, cmpl, setb
29380 if (dis_int_cmp( theInstr
)) goto decode_success
;
29381 goto decode_failure
;
29383 case 0x0C0: case 0x0E0: // cmprb, cmpeqb
29384 if (dis_byte_cmp( theInstr
)) goto decode_success
;
29385 goto decode_failure
;
29387 case 0x10B: case 0x30B: // moduw, modsw
29388 case 0x109: case 0x309: // modsd, modud
29389 case 0x21A: case 0x23A: // cnttzw, cnttzd
29390 if (dis_modulo_int( theInstr
)) goto decode_success
;
29391 goto decode_failure
;
29393 /* Integer Logical Instructions */
29394 case 0x01C: case 0x03C: case 0x01A: // and, andc, cntlzw
29395 case 0x11C: case 0x3BA: case 0x39A: // eqv, extsb, extsh
29396 case 0x1DC: case 0x07C: case 0x1BC: // nand, nor, or
29397 case 0x19C: case 0x13C: // orc, xor
29398 case 0x2DF: case 0x25F: // mftgpr, mffgpr
29399 if (dis_int_logic( theInstr
)) goto decode_success
;
29400 goto decode_failure
;
29402 case 0x28E: case 0x2AE: // tbegin., tend.
29403 case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
29404 case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
29405 case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
29406 if (dis_transactional_memory( theInstr
,
29407 getUIntPPCendianly( &guest_code
[delta
+ 4]),
29409 goto decode_success
;
29410 goto decode_failure
;
29412 /* 64bit Integer Logical Instructions */
29413 case 0x3DA: case 0x03A: // extsw, cntlzd
29414 if (!mode64
) goto decode_failure
;
29415 if (dis_int_logic( theInstr
)) goto decode_success
;
29416 goto decode_failure
;
29418 /* 64bit Integer Parity Instructions */
29419 case 0xba: // prtyd
29420 if (!mode64
) goto decode_failure
;
29421 if (dis_int_parity( theInstr
)) goto decode_success
;
29422 goto decode_failure
;
29424 case 0x9a: // prtyw
29425 if (dis_int_parity( theInstr
)) goto decode_success
;
29426 goto decode_failure
;
29428 /* Integer Shift Instructions */
29429 case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
29431 if (dis_int_shift( theInstr
)) goto decode_success
;
29432 goto decode_failure
;
29434 /* 64bit Integer Shift Instructions */
29435 case 0x01B: case 0x31A: // sld, srad
29436 case 0x33A: case 0x33B: // sradi
29438 if (!mode64
) goto decode_failure
;
29439 if (dis_int_shift( theInstr
)) goto decode_success
;
29440 goto decode_failure
;
29442 /* Integer Load Instructions */
29443 case 0x057: case 0x077: case 0x157: // lbzx, lbzux, lhax
29444 case 0x177: case 0x117: case 0x137: // lhaux, lhzx, lhzux
29445 case 0x017: case 0x037: // lwzx, lwzux
29446 if (dis_int_load( theInstr
)) goto decode_success
;
29447 goto decode_failure
;
29449 /* 64bit Integer Load Instructions */
29450 case 0x035: case 0x015: // ldux, ldx
29451 case 0x175: case 0x155: // lwaux, lwax
29452 if (!mode64
) goto decode_failure
;
29453 if (dis_int_load( theInstr
)) goto decode_success
;
29454 goto decode_failure
;
29456 /* Integer Store Instructions */
29457 case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux
29458 case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx
29459 if (dis_int_store( theInstr
, abiinfo
)) goto decode_success
;
29460 goto decode_failure
;
29462 /* 64bit Integer Store Instructions */
29463 case 0x0B5: case 0x095: // stdux, stdx
29464 if (!mode64
) goto decode_failure
;
29465 if (dis_int_store( theInstr
, abiinfo
)) goto decode_success
;
29466 goto decode_failure
;
29468 /* Integer Load and Store with Byte Reverse Instructions */
29469 case 0x214: case 0x294: // ldbrx, stdbrx
29470 if (!mode64
) goto decode_failure
;
29471 if (dis_int_ldst_rev( theInstr
)) goto decode_success
;
29472 goto decode_failure
;
29474 case 0x216: case 0x316: case 0x296: // lwbrx, lhbrx, stwbrx
29475 case 0x396: // sthbrx
29476 if (dis_int_ldst_rev( theInstr
)) goto decode_success
;
29477 goto decode_failure
;
29479 /* Integer Load and Store String Instructions */
29480 case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
29481 case 0x295: { // stswx
29482 Bool stopHere
= False
;
29483 Bool ok
= dis_int_ldst_str( theInstr
, &stopHere
);
29484 if (!ok
) goto decode_failure
;
29486 putGST( PPC_GST_CIA
, mkSzImm(ty
, nextInsnAddr()) );
29487 dres
.jk_StopHere
= Ijk_Boring
;
29488 dres
.whatNext
= Dis_StopHere
;
29490 goto decode_success
;
29493 /* Memory Synchronization Instructions */
29494 case 0x034: case 0x074: // lbarx, lharx
29495 case 0x2B6: case 0x2D6: // stbcx, sthcx
29496 if (!allow_isa_2_07
) goto decode_noP8
;
29497 if (dis_memsync( theInstr
)) goto decode_success
;
29498 goto decode_failure
;
29500 case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
29501 case 0x256: // sync
29502 if (dis_memsync( theInstr
)) goto decode_success
;
29503 goto decode_failure
;
29505 /* 64bit Memory Synchronization Instructions */
29506 case 0x054: case 0x0D6: // ldarx, stdcx.
29507 if (!mode64
) goto decode_failure
;
29508 if (dis_memsync( theInstr
)) goto decode_success
;
29509 goto decode_failure
;
29511 case 0x114: case 0x0B6: // lqarx, stqcx.
29512 if (dis_memsync( theInstr
)) goto decode_success
;
29513 goto decode_failure
;
29515 /* Processor Control Instructions */
29516 case 0x33: case 0x73: // mfvsrd, mfvsrwz
29517 case 0xB3: case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
29518 case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr
29519 case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr
29520 case 0x220: // mcrxrt
29521 if (dis_proc_ctl( abiinfo
, theInstr
)) goto decode_success
;
29522 goto decode_failure
;
29524 /* Cache Management Instructions */
29525 case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst
29526 case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
29527 case 0x3D6: // icbi
29528 if (dis_cache_manage( theInstr
, &dres
, archinfo
))
29529 goto decode_success
;
29530 goto decode_failure
;
29532 //zz /* External Control Instructions */
29533 //zz case 0x136: case 0x1B6: // eciwx, ecowx
29534 //zz DIP("external control op => not implemented\n");
29535 //zz goto decode_failure;
29537 /* Trap Instructions */
29539 if (dis_trap(theInstr
, &dres
)) goto decode_success
;
29540 goto decode_failure
;
29543 if (!mode64
) goto decode_failure
;
29544 if (dis_trap(theInstr
, &dres
)) goto decode_success
;
29545 goto decode_failure
;
29547 /* Floating Point Load Instructions */
29548 case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
29549 case 0x277: // lfdux
29550 if (!allow_F
) goto decode_noF
;
29551 if (dis_fp_load( theInstr
)) goto decode_success
;
29552 goto decode_failure
;
29554 /* Floating Point Store Instructions */
29555 case 0x297: case 0x2B7: case 0x2D7: // stfs, stfsu, stfd
29556 case 0x2F7: // stfdu, stfiwx
29557 if (!allow_F
) goto decode_noF
;
29558 if (dis_fp_store( theInstr
)) goto decode_success
;
29559 goto decode_failure
;
29560 case 0x3D7: // stfiwx
29561 if (!allow_F
) goto decode_noF
;
29562 if (!allow_GX
) goto decode_noGX
;
29563 if (dis_fp_store( theInstr
)) goto decode_success
;
29564 goto decode_failure
;
29566 /* Floating Point Double Pair Indexed Instructions */
29567 case 0x317: // lfdpx (Power6)
29568 case 0x397: // stfdpx (Power6)
29569 if (!allow_F
) goto decode_noF
;
29570 if (dis_fp_pair(theInstr
)) goto decode_success
;
29571 goto decode_failure
;
29573 case 0x357: // lfiwax
29574 if (!allow_F
) goto decode_noF
;
29575 if (dis_fp_load( theInstr
)) goto decode_success
;
29576 goto decode_failure
;
29578 case 0x377: // lfiwzx
29579 if (!allow_F
) goto decode_noF
;
29580 if (dis_fp_load( theInstr
)) goto decode_success
;
29581 goto decode_failure
;
29583 /* AltiVec instructions */
29585 /* AV Cache Control - Data streams */
29586 case 0x156: case 0x176: case 0x336: // dst, dstst, dss
29587 if (!allow_V
) goto decode_noV
;
29588 if (dis_av_datastream( theInstr
)) goto decode_success
;
29589 goto decode_failure
;
29592 case 0x006: case 0x026: // lvsl, lvsr
29593 case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
29594 case 0x067: case 0x167: // lvx, lvxl
29595 if (!allow_V
) goto decode_noV
;
29596 if (dis_av_load( abiinfo
, theInstr
)) goto decode_success
;
29597 goto decode_failure
;
29600 case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
29601 case 0x0E7: case 0x1E7: // stvx, stvxl
29602 if (!allow_V
) goto decode_noV
;
29603 if (dis_av_store( theInstr
)) goto decode_success
;
29604 goto decode_failure
;
29607 case 0x00C: // lxsiwzx
29608 case 0x04C: // lxsiwax
29609 case 0x10C: // lxvx
29610 case 0x10D: // lxvl
29611 case 0x12D: // lxvll
29612 case 0x16C: // lxvwsx
29613 case 0x20C: // lxsspx
29614 case 0x24C: // lxsdx
29615 case 0x32C: // lxvh8x
29616 case 0x30D: // lxsibzx
29617 case 0x32D: // lxsihzx
29618 case 0x34C: // lxvd2x
29619 case 0x36C: // lxvb16x
29620 case 0x14C: // lxvdsx
29621 case 0x30C: // lxvw4x
29622 // All of these VSX load instructions use some VMX facilities, so
29623 // if allow_V is not set, we'll skip trying to decode.
29624 if (!allow_V
) goto decode_noV
;
29626 if (dis_vx_load( theInstr
)) goto decode_success
;
29627 goto decode_failure
;
29630 case 0x08C: // stxsiwx
29631 case 0x18C: // stxvx
29632 case 0x18D: // stxvl
29633 case 0x1AD: // stxvll
29634 case 0x28C: // stxsspx
29635 case 0x2CC: // stxsdx
29636 case 0x38C: // stxvw4x
29637 case 0x3CC: // stxvd2x
29638 case 0x38D: // stxsibx
29639 case 0x3AD: // stxsihx
29640 case 0x3AC: // stxvh8x
29641 case 0x3EC: // stxvb16x
29642 // All of these VSX store instructions use some VMX facilities, so
29643 // if allow_V is not set, we'll skip trying to decode.
29644 if (!allow_V
) goto decode_noV
;
29646 if (dis_vx_store( theInstr
)) goto decode_success
;
29647 goto decode_failure
;
29649 case 0x133: case 0x193: case 0x1B3: // mfvsrld, mfvsrdd, mtvsrws
29650 // The move from/to VSX instructions use some VMX facilities, so
29651 // if allow_V is not set, we'll skip trying to decode.
29652 if (!allow_V
) goto decode_noV
;
29653 if (dis_vx_move( theInstr
)) goto decode_success
;
29654 goto decode_failure
;
29656 /* Miscellaneous ISA 2.06 instructions */
29657 case 0x1FA: // popcntd
29658 if (!mode64
) goto decode_failure
;
29659 /* else fallthru */
29660 case 0x17A: // popcntw
29661 case 0x7A: // popcntb
29662 if (dis_int_logic( theInstr
)) goto decode_success
;
29663 goto decode_failure
;
29665 case 0x0FC: // bpermd
29666 if (!mode64
) goto decode_failure
;
29667 if (dis_int_logic( theInstr
)) goto decode_success
;
29668 goto decode_failure
;
29671 /* Deal with some other cases that we would otherwise have
29673 /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
29674 /* only decode this insn when reserved bit 0 (31 in IBM's
29675 notation) is zero */
29676 if (IFIELD(theInstr
, 0, 6) == (15<<1)) {
29677 UInt rT
= ifieldRegDS( theInstr
);
29678 UInt rA
= ifieldRegA( theInstr
);
29679 UInt rB
= ifieldRegB( theInstr
);
29680 UInt bi
= ifieldRegC( theInstr
);
29683 IRExpr_ITE( binop(Iop_CmpNE32
, getCRbit( bi
), mkU32(0)),
29684 rA
== 0 ? (mode64
? mkU64(0) : mkU32(0))
29689 DIP("isel r%u,r%u,r%u,crb%u\n", rT
,rA
,rB
,bi
);
29690 goto decode_success
;
29694 opc2
= IFIELD(theInstr
, 2, 9);
29697 if (!mode64
) goto decode_failure
;
29698 if (dis_int_logic( theInstr
)) goto decode_success
;
29699 goto decode_failure
;
29702 goto decode_failure
;
29708 /* AltiVec instructions */
29710 opc2
= IFIELD(theInstr
, 0, 6);
29712 /* AV Mult-Add, Mult-Sum */
29713 case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
29714 case 0x23: // vmsumudm
29715 case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
29716 case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
29717 if (!allow_V
) goto decode_noV
;
29718 if (dis_av_multarith( theInstr
)) goto decode_success
;
29719 goto decode_failure
;
29721 case 0x30: case 0x31: case 0x33: // maddhd, madhdu, maddld
29722 if (!mode64
) goto decode_failure
;
29723 if (dis_int_mult_add( theInstr
)) goto decode_success
;
29724 goto decode_failure
;
29726 /* AV Permutations */
29728 case 0x2B: // vperm
29729 case 0x2C: // vsldoi
29730 if (!allow_V
) goto decode_noV
;
29731 if (dis_av_permute( theInstr
)) goto decode_success
;
29732 goto decode_failure
;
29734 case 0x2D: // vpermxor
29735 case 0x3B: // vpermr
29736 if (!allow_isa_2_07
) goto decode_noP8
;
29737 if (dis_av_permute( theInstr
)) goto decode_success
;
29738 goto decode_failure
;
29740 /* AV Floating Point Mult-Add/Sub */
29741 case 0x2E: case 0x2F: // vmaddfp, vnmsubfp
29742 if (!allow_V
) goto decode_noV
;
29743 if (dis_av_fp_arith( theInstr
)) goto decode_success
;
29744 goto decode_failure
;
29746 case 0x3D: case 0x3C: // vaddecuq, vaddeuqm
29747 case 0x3F: case 0x3E: // vsubecuq, vsubeuqm
29748 if (!allow_V
) goto decode_noV
;
29749 if (dis_av_quad( theInstr
)) goto decode_success
;
29750 goto decode_failure
;
29753 break; // Fall through...
29756 opc2
= IFIELD(theInstr
, 0, 9);
29757 if (IFIELD(theInstr
, 10, 1) == 1) {
29758 /* The following instructions have bit 21 set and a PS bit (bit 22)
29759 * Bit 21 distinquishes them from instructions with an 11 bit opc2
29763 /* BCD arithmetic */
29764 case 0x001: case 0x041: // bcdadd, bcdsub
29765 case 0x101: case 0x141: // bcdtrunc., bcdutrunc.
29766 case 0x081: case 0x0C1: case 0x1C1: // bcdus., bcds., bcdsr.
29767 case 0x181: // bcdcfn., bcdcfz.
29768 // bcdctz., bcdcfsq., bcdctsq.
29769 if (!allow_isa_2_07
) goto decode_noP8
;
29770 if (dis_av_bcd( theInstr
, abiinfo
)) goto decode_success
;
29771 goto decode_failure
;
29773 break; // Fall through...
29777 opc2
= IFIELD(theInstr
, 0, 11);
29779 /* BCD manipulation */
29780 case 0x341: // bcdcpsgn
29782 if (!allow_isa_2_07
) goto decode_noP8
;
29783 if (dis_av_bcd_misc( theInstr
, abiinfo
)) goto decode_success
;
29784 goto decode_failure
;
29787 /* AV Arithmetic */
29788 case 0x180: // vaddcuw
29789 case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
29790 case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
29791 case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
29792 case 0x580: // vsubcuw
29793 case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
29794 case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
29795 case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
29796 case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
29797 case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
29798 case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
29799 case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
29800 case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
29801 case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
29802 case 0x008: case 0x048: // vmuloub, vmulouh
29803 case 0x108: case 0x148: // vmulosb, vmulosh
29804 case 0x208: case 0x248: // vmuleub, vmuleuh
29805 case 0x308: case 0x348: // vmulesb, vmulesh
29806 case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
29807 case 0x688: case 0x788: // vsum2sws, vsumsws
29808 if (!allow_V
) goto decode_noV
;
29809 if (dis_av_arith( theInstr
)) goto decode_success
;
29810 goto decode_failure
;
29812 case 0x088: case 0x089: // vmulouw, vmuluwm
29813 case 0x0C0: case 0x0C2: // vaddudm, vmaxud
29814 case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
29815 case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
29816 case 0x4C0: // vsubudm
29817 if (!allow_isa_2_07
) goto decode_noP8
;
29818 if (dis_av_arith( theInstr
)) goto decode_success
;
29819 goto decode_failure
;
29821 /* AV Polynomial Vector Multiply Add */
29822 case 0x408: case 0x448: // vpmsumb, vpmsumd
29823 case 0x488: case 0x4C8: // vpmsumw, vpmsumh
29824 if (!allow_isa_2_07
) goto decode_noP8
;
29825 if (dis_av_polymultarith( theInstr
)) goto decode_success
;
29826 goto decode_failure
;
29828 /* AV Rotate, Shift */
29829 case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
29830 case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
29831 case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
29832 case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
29833 case 0x1C4: case 0x2C4: // vsl, vsr
29834 case 0x40C: case 0x44C: // vslo, vsro
29835 if (!allow_V
) goto decode_noV
;
29836 if (dis_av_shift( theInstr
)) goto decode_success
;
29837 goto decode_failure
;
29839 case 0x0C4: // vrld
29840 case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
29841 if (!allow_isa_2_07
) goto decode_noP8
;
29842 if (dis_av_shift( theInstr
)) goto decode_success
;
29843 goto decode_failure
;
29846 case 0x404: case 0x444: case 0x484: // vand, vandc, vor
29847 case 0x4C4: case 0x504: // vxor, vnor
29848 if (!allow_V
) goto decode_noV
;
29849 if (dis_av_logic( theInstr
)) goto decode_success
;
29850 goto decode_failure
;
29852 case 0x544: // vorc
29853 case 0x584: case 0x684: // vnand, veqv
29854 if (!allow_isa_2_07
) goto decode_noP8
;
29855 if (dis_av_logic( theInstr
)) goto decode_success
;
29856 goto decode_failure
;
29859 case 0x085: case 0x185: // vrlwmi, vrlwnm
29860 case 0x0C5: case 0x1C5: // vrldmi, vrldnm
29861 if (!allow_V
) goto decode_noV
;
29862 if (dis_av_rotate( theInstr
)) goto decode_success
;
29863 goto decode_failure
;
29865 /* AV Processor Control */
29866 case 0x604: case 0x644: // mfvscr, mtvscr
29867 if (!allow_V
) goto decode_noV
;
29868 if (dis_av_procctl( theInstr
)) goto decode_success
;
29869 goto decode_failure
;
29871 /* AV Vector Extract Element instructions */
29872 case 0x60D: case 0x64D: case 0x68D: // vextublx, vextuhlx, vextuwlx
29873 case 0x70D: case 0x74D: case 0x78D: // vextubrx, vextuhrx, vextuwrx
29874 if (!allow_V
) goto decode_noV
;
29875 if (dis_av_extract_element( theInstr
)) goto decode_success
;
29876 goto decode_failure
;
29879 /* AV Floating Point Arithmetic */
29880 case 0x00A: case 0x04A: // vaddfp, vsubfp
29881 case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
29882 case 0x1CA: // vlogefp
29883 case 0x40A: case 0x44A: // vmaxfp, vminfp
29884 if (!allow_V
) goto decode_noV
;
29885 if (dis_av_fp_arith( theInstr
)) goto decode_success
;
29886 goto decode_failure
;
29888 /* AV Floating Point Round/Convert */
29889 case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
29890 case 0x2CA: // vrfim
29891 case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
29892 case 0x3CA: // vctsxs
29893 if (!allow_V
) goto decode_noV
;
29894 if (dis_av_fp_convert( theInstr
)) goto decode_success
;
29895 goto decode_failure
;
29897 /* AV Merge, Splat, Extract, Insert */
29898 case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
29899 case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
29900 case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
29901 case 0x20D: case 0x24D: // vextractub, vextractuh,
29902 case 0x28D: case 0x2CD: // vextractuw, vextractd,
29903 case 0x30D: case 0x34D: // vinsertb, vinserth
29904 case 0x38D: case 0x3CD: // vinsertw, vinsertd
29905 case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
29906 if (!allow_V
) goto decode_noV
;
29907 if (dis_av_permute( theInstr
)) goto decode_success
;
29908 goto decode_failure
;
29910 case 0x68C: case 0x78C: // vmrgow, vmrgew
29911 if (!allow_isa_2_07
) goto decode_noP8
;
29912 if (dis_av_permute( theInstr
)) goto decode_success
;
29913 goto decode_failure
;
29915 /* AltiVec 128 bit integer multiply by 10 Instructions */
29916 case 0x201: case 0x001: //vmul10uq, vmul10cuq
29917 case 0x241: case 0x041: //vmul10euq, vmul10ceuq
29918 if (!allow_V
) goto decode_noV
;
29919 if (!allow_isa_3_0
) goto decode_noP9
;
29920 if (dis_av_mult10( theInstr
)) goto decode_success
;
29921 goto decode_failure
;
29923 /* AV Pack, Unpack */
29924 case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
29925 case 0x0CE: // vpkuwus
29926 case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
29927 case 0x1CE: // vpkswss
29928 case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
29929 case 0x2CE: // vupklsh
29930 case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
29931 if (!allow_V
) goto decode_noV
;
29932 if (dis_av_pack( theInstr
)) goto decode_success
;
29933 goto decode_failure
;
29935 case 0x403: case 0x443: case 0x483: // vabsdub, vabsduh, vabsduw
29936 if (!allow_V
) goto decode_noV
;
29937 if (dis_abs_diff( theInstr
)) goto decode_success
;
29938 goto decode_failure
;
29940 case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
29941 case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
29942 if (!allow_isa_2_07
) goto decode_noP8
;
29943 if (dis_av_pack( theInstr
)) goto decode_success
;
29944 goto decode_failure
;
29946 case 0x508: case 0x509: // vcipher, vcipherlast
29947 case 0x548: case 0x549: // vncipher, vncipherlast
29948 case 0x5C8: // vsbox
29949 if (!allow_isa_2_07
) goto decode_noP8
;
29950 if (dis_av_cipher( theInstr
)) goto decode_success
;
29951 goto decode_failure
;
29953 /* AV Vector Extend Sign Instructions and
29954 * Vector Count Leading/Trailing zero Least-Significant bits Byte.
29955 * Vector Integer Negate Instructions
29957 case 0x602: // vextsb2w, vextsh2w, vextsb2d, vextsh2d, vextsw2d
29958 // vclzlsbb and vctzlsbb
29960 // vprtybw, vprtybd, vprtybq
29961 // vctzb, vctzh, vctzw, vctzd
29962 if (!allow_V
) goto decode_noV
;
29963 if (dis_av_extend_sign_count_zero( theInstr
, allow_isa_3_0
))
29964 goto decode_success
;
29965 goto decode_failure
;
29967 case 0x6C2: case 0x682: // vshasigmaw, vshasigmad
29968 if (!allow_isa_2_07
) goto decode_noP8
;
29969 if (dis_av_hash( theInstr
)) goto decode_success
;
29970 goto decode_failure
;
29972 case 0x702: case 0x742: // vclzb, vclzh
29973 case 0x782: case 0x7c2: // vclzw, vclzd
29974 if (!allow_isa_2_07
) goto decode_noP8
;
29975 if (dis_av_count_bitTranspose( theInstr
, opc2
)) goto decode_success
;
29976 goto decode_failure
;
29978 case 0x703: case 0x743: // vpopcntb, vpopcnth
29979 case 0x783: case 0x7c3: // vpopcntw, vpopcntd
29980 if (!allow_isa_2_07
) goto decode_noP8
;
29981 if (dis_av_count_bitTranspose( theInstr
, opc2
)) goto decode_success
;
29982 goto decode_failure
;
29984 case 0x50c: // vgbbd
29985 case 0x5cc: // vbpermd
29986 if (!allow_isa_2_07
) goto decode_noP8
;
29987 if (dis_av_count_bitTranspose( theInstr
, opc2
)) goto decode_success
;
29988 goto decode_failure
;
29990 case 0x140: case 0x100: // vaddcuq, vadduqm
29991 case 0x540: case 0x500: // vsubcuq, vsubuqm
29992 case 0x54C: // vbpermq
29993 if (!allow_V
) goto decode_noV
;
29994 if (dis_av_quad( theInstr
)) goto decode_success
;
29995 goto decode_failure
;
29998 break; // Fall through...
30001 opc2
= IFIELD(theInstr
, 0, 10);
30005 case 0x006: case 0x007: case 0x107: // vcmpequb, vcmpneb, vcmpnezb
30006 case 0x046: case 0x047: case 0x147: // vcmpequh, vcmpneh, vcmpnezh
30007 case 0x086: case 0x087: case 0x187: // vcmpequw, vcmpnew, vcmpnezw
30008 case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
30009 case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
30010 if (!allow_V
) goto decode_noV
;
30011 if (dis_av_cmp( theInstr
)) goto decode_success
;
30012 goto decode_failure
;
30014 case 0x0C7: // vcmpequd
30015 case 0x2C7: // vcmpgtud
30016 case 0x3C7: // vcmpgtsd
30017 if (!allow_isa_2_07
) goto decode_noP8
;
30018 if (dis_av_cmp( theInstr
)) goto decode_success
;
30019 goto decode_failure
;
30021 /* AV Floating Point Compare */
30022 case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
30023 case 0x3C6: // vcmpbfp
30024 if (!allow_V
) goto decode_noV
;
30025 if (dis_av_fp_cmp( theInstr
)) goto decode_success
;
30026 goto decode_failure
;
30029 goto decode_failure
;
30034 goto decode_failure
;
30039 vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
30040 "can't be handled by Valgrind on this host. This instruction\n"
30041 "requires a host that supports Floating Point instructions.\n",
30043 goto not_supported
;
30047 vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
30048 "that can't be handled by Valgrind. If this instruction is an\n"
30049 "Altivec instruction, Valgrind must be run on a host that supports"
30050 "AltiVec instructions. If the application was compiled for e500, then\n"
30051 "unfortunately Valgrind does not yet support e500 instructions.\n",
30053 goto not_supported
;
30055 vassert(!allow_VX
);
30057 vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
30058 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
30059 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
30061 goto not_supported
;
30063 vassert(!allow_FX
);
30065 vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
30066 "that can't be handled by Valgrind on this host. This instruction\n"
30067 "requires a host that supports the General Purpose-Optional instructions.\n",
30069 goto not_supported
;
30071 vassert(!allow_GX
);
30073 vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
30074 "that can't be handled by Valgrind on this host. This instruction\n"
30075 "requires a host that supports the Graphic-Optional instructions.\n",
30077 goto not_supported
;
30079 vassert(!allow_DFP
);
30081 vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
30082 "that can't be handled by Valgrind on this host. This instruction\n"
30083 "requires a host that supports DFP instructions.\n",
30085 goto not_supported
;
30087 vassert(!allow_isa_2_07
);
30089 vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
30090 "by Valgrind on this host. This instruction requires a host that\n"
30091 "supports Power 8 instructions.\n",
30093 goto not_supported
;
30096 vassert(!allow_isa_3_0
);
30098 vex_printf("disInstr(ppc): found the Power 9 instruction 0x%x that can't be handled\n"
30099 "by Valgrind on this host. This instruction requires a host that\n"
30100 "supports Power 9 instructions.\n",
30102 goto not_supported
;
30105 /* All decode failures end up here. */
30106 opc2
= (theInstr
) & 0x7FF;
30108 vex_printf("disInstr(ppc): unhandled instruction: "
30109 "0x%x\n", theInstr
);
30110 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n",
30111 opc1
, opc1
, opc2
, opc2
);
30115 /* Tell the dispatcher that this insn cannot be decoded, and so has
30116 not been executed, and (is currently) the next to be executed.
30117 CIA should be up-to-date since it made so at the start of each
30118 insn, but nevertheless be paranoid and update it again right
30120 putGST( PPC_GST_CIA
, mkSzImm(ty
, guest_CIA_curr_instr
) );
30122 dres
.whatNext
= Dis_StopHere
;
30123 dres
.jk_StopHere
= Ijk_NoDecode
;
30125 } /* switch (opc) for the main (primary) opcode switch. */
30128 /* All decode successes end up here. */
30129 switch (dres
.whatNext
) {
30131 putGST( PPC_GST_CIA
, mkSzImm(ty
, guest_CIA_curr_instr
+ 4));
30140 if (dres
.len
== 0) {
30143 vassert(dres
.len
== 20);
30152 /*------------------------------------------------------------*/
30153 /*--- Top-level fn ---*/
30154 /*------------------------------------------------------------*/
30156 /* Disassemble a single instruction into IR. The instruction
30157 is located in host memory at &guest_code[delta]. */
30159 DisResult
disInstr_PPC ( IRSB
* irsb_IN
,
30160 const UChar
* guest_code_IN
,
30163 VexArch guest_arch
,
30164 const VexArchInfo
* archinfo
,
30165 const VexAbiInfo
* abiinfo
,
30166 VexEndness host_endness_IN
,
30167 Bool sigill_diag_IN
)
30171 UInt mask32
, mask64
;
30172 UInt hwcaps_guest
= archinfo
->hwcaps
;
30174 vassert(guest_arch
== VexArchPPC32
|| guest_arch
== VexArchPPC64
);
30176 /* global -- ick */
30177 mode64
= guest_arch
== VexArchPPC64
;
30178 ty
= mode64
? Ity_I64
: Ity_I32
;
30179 if (!mode64
&& (host_endness_IN
== VexEndnessLE
)) {
30180 vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
30182 dres
.whatNext
= Dis_StopHere
;
30183 dres
.jk_StopHere
= Ijk_NoDecode
;
30184 dres
.hint
= Dis_HintNone
;
30188 /* do some sanity checks */
30189 mask32
= VEX_HWCAPS_PPC32_F
| VEX_HWCAPS_PPC32_V
30190 | VEX_HWCAPS_PPC32_FX
| VEX_HWCAPS_PPC32_GX
| VEX_HWCAPS_PPC32_VX
30191 | VEX_HWCAPS_PPC32_DFP
| VEX_HWCAPS_PPC32_ISA2_07
;
30193 mask64
= VEX_HWCAPS_PPC64_V
| VEX_HWCAPS_PPC64_FX
30194 | VEX_HWCAPS_PPC64_GX
| VEX_HWCAPS_PPC64_VX
| VEX_HWCAPS_PPC64_DFP
30195 | VEX_HWCAPS_PPC64_ISA2_07
| VEX_HWCAPS_PPC64_ISA3_0
;
30198 vassert((hwcaps_guest
& mask32
) == 0);
30200 vassert((hwcaps_guest
& mask64
) == 0);
30203 /* Set globals (see top of this file) */
30204 guest_code
= guest_code_IN
;
30206 host_endness
= host_endness_IN
;
30208 guest_CIA_curr_instr
= mkSzAddr(ty
, guest_IP
);
30209 guest_CIA_bbstart
= mkSzAddr(ty
, guest_IP
- delta
);
30211 dres
= disInstr_PPC_WRK ( delta
, archinfo
, abiinfo
, sigill_diag_IN
);
30216 /*--------------------------------------------------------------------*/
30217 /*--- end guest_ppc_toIR.c ---*/
30218 /*--------------------------------------------------------------------*/